diff --git a/galgebra-master/doc/galgebra.pdf b/galgebra-master/doc/galgebra.pdf index 3676a73a..82765fec 100644 Binary files a/galgebra-master/doc/galgebra.pdf and b/galgebra-master/doc/galgebra.pdf differ diff --git a/galgebra-master/doc/galgebra.tex b/galgebra-master/doc/galgebra.tex index a51bd0d2..1c682360 100755 --- a/galgebra-master/doc/galgebra.tex +++ b/galgebra-master/doc/galgebra.tex @@ -38,6 +38,16 @@ \definecolor{gray}{rgb}{0.95,0.95,0.95} \setlength{\parindent}{0in} \usepackage{sectsty} + +\usepackage[utf8]{inputenc} +\usepackage{fancybox} + +\makeatletter +\newenvironment{CenteredBox}{% +\begin{Sbox}}{% Save the content in a box +\end{Sbox}\centerline{\parbox{\wd\@Sbox}{\TheSbox}}}% And output it centered +\makeatother + \sectionfont{\large} %\titlespacing*{\section}{0pt}{6pt}{3pt} \title{\galgebra: \bf\Large a Geometric Algebra Module for \emph{Sympy}} @@ -126,7 +136,8 @@ well as linear multivector differential operators and linear transformations. In addition the module includes the geometric, outer (curl) and inner (div) derivatives. The module requires the \emph{sympy} module and the numpy module for numerical linear - algebra calculations. For \LaTeX output a \LaTeX distribution must be installed. + algebra calculations. For \LaTeX\ output a \LaTeX\ distribution and pdf viewer must be installed. + \tableofcontents @@ -153,7 +164,9 @@ \section{Install sympy} \begin{tabular}{cl} mode & \multicolumn{1}{c}{method} \vspace{5pt} \\ \hline latest release & \parbox{4in}{\vspace{5pt}Go to \url{https://github.com/sympy/sympy/releases} and select - option appropriate for your system.\vspace{5pt}} \\ \hline + option appropriate for your system. Note that if you have \emph{pip} + (see \url{https://pip.pypa.io/en/latest/installing.html}) installed you can install + the latest release by entering the command ``\T{pip sympy}.'' \vspace{5pt}} \\ \hline development version & \parbox{4in}{\vspace{5pt}Go to \url{https://github.com/sympy/sympy} and download zipped archive. Unzip archive. Open terminal/command line in top directory of unzipped archive. For linux or osx run ``\T{sudo python setup.py install}.'' For windows run @@ -169,7 +182,7 @@ \section{Install galgebra} Then with whatever version you are using open a terminal/command line in the \T{galgebra} directory that is in the top directory of the archive. If you are in the correct the directory it should contain the python program \T{setgapth.py}. If you are in -linux or osx run the program with the command \T{sudo python setgapth.py}, if in windows use \T{python setgapth.py}. +linux or osx run the program with the command ``\T{sudo python setgapth.py},'' if in windows use ``\T{python setgapth.py}.'' This program creates the file \T{Ga.pth} in the correct directory to simplify importing the \T{galgebra} modules into your python programs. The modules you will use for programming with geometric algebra/calculus are \T{ga}, \T{mv}, \T{lt}, and @@ -192,16 +205,23 @@ \section{{\LaTeX} Options} \end{tabular} \end{center} \section{``Ipython notebook'' Options} -To use ``ipython notebook'' with \T{galgebra} it must be installed. To install ``ipython notebook'' do the following. +To use \emph{ipython notebook} with \T{galgebra} it must be installed. To install \emph{ipython notebook} do the following. Go to \url{http://pip.readthedocs.org/en/latest/installing.html} and install \T{pip}. Then run in a terminal/command line -``\T{pip install "ipython[notebook]"}''. +\T{pip install "ipython[notebook]"}. If you have already installed \emph{ipython notebook} you should enter +\T{pip install "ipython[notebook]" --upgrade} to make sure you have the latest version. Linux and OSX users will have to +use \T{sudo} with the commands. The version of \emph{ipython notebook} we are using is \textbf{jupyter} and that should be +shown when the notebook is started. + +Note that to correctly print latex from \emph{ipython notebook} one must use the \T{Format()} function from the \emph{printer} +module. Go to the section on latex printing for more information. \section{The ANSI Console} The \T{printer} module of \T{galgebra} contains the class \T{Eprint} which is described in section~(\ref{stdprint}). This function uses the capabilities of the ansi console (terminal) for enhanced multivector printing where multivector bases, sympy functions and derivatives -are printed in different colors. The ansi console is native to Linux and OSX, but not windows. The best available free substitute for +are printed in different colors. The ansi console is native to Linux and OSX (which is really Unix under the hood), but not windows. +The best available free substitute for the ansi console on windows is \emph{ConEmu}. The web page for ConEmu is \url{http://conemu.github.io/}. In order to install \emph{ConEmu} download the appropriate version of the \emph{ConEmu} installer (exe file) for your system (32 bit or 64 bit) from the website and and execute it. Instructions for using \emph{ConEmu} are given in section~(\ref{stdprint}). @@ -215,6 +235,8 @@ \section{Geany Programmers Editor} \chapter{What is Geometric Algebra?} +\section{Basics of Geometric Algebra} + Geometric algebra is the Clifford algebra of a real finite dimensional vector space or the algebra that results when the vector space is extended with a product of vectors (geometric product) that is associative, @@ -230,17 +252,17 @@ \chapter{What is Geometric Algebra?} a\lp bc \rp = \lp ab \rp c \\ a\lp b+c \rp = ab+ac \\ \lp a + b \rp c = ac+bc \\ - aa = a^{2} \in \Re + aa = a^{2} \in \Re. \end{array} \end{equation} -The dot product of two vectors is defined by (\cite{Doran},p86) +If the dot (inner) product of two vectors is defined by (\cite{Doran},p86) \begin{equation} - a\cdot b \equiv (ab+ba)/2 + a\cdot b \equiv (ab+ba)/2, \end{equation} -Then consider +then we have \begin{align} c &= a+b \\ @@ -251,7 +273,7 @@ \chapter{What is Geometric Algebra?} Thus $a\cdot b$ is real. The objects generated from linear combinations of the geometric products of vectors are called multivectors. If a basis for -the underlying vector space is the set of vectors formed from $\eb_{1},\dots,\eb_{n}$ (we use +the underlying vector space are the vectors $\set{\eb_{1},\dots,\eb_{n}}$ (we use boldface $\eb$'s to denote basis vectors) a complete basis for the geometric algebra is given by the scalar $1$, the vectors $\eb_{1},\dots,\eb_{n}$ and all geometric products of vectors @@ -330,7 +352,11 @@ \chapter{What is Geometric Algebra?} Using the blades $\eb_{i_{1}}\W \eb_{i_{2}}\W\dots\W \eb_{r}$ creates a graded algebra where $r$ is the grade of the basis blades. The grade-$r$ part of $\bm{B}$ is the linear combination of all terms with -grade $r$ basis blades. The scalar part of $\bm{B}$ is defined to +grade $r$ basis blades. + +\subsection{Grade Projection} + +The scalar part of $\bm{B}$ is defined to be grade-$0$. Now that the blade expansion of $\bm{B}$ is defined we can also define the grade projection operator $\proj{\bm{B}}{r}$ by @@ -344,6 +370,8 @@ \chapter{What is Geometric Algebra?} \proj{\bm{B}}{} \equiv \proj{\bm{B}}{0} = B \end{equation} +\subsection{Multivector Products} + Then if $\bm{A}_{r}$ is an $r$-grade multivector and $\bm{B}_{s}$ is an $s$-grade multivector we have \begin{equation} @@ -377,6 +405,8 @@ \chapter{What is Geometric Algebra?} 0 & s < r\end{array}} \end{align} +\subsection{Reverse of Multivector} + A final operation for multivectors is the reverse. If a multivector $\bm{A}$ is the geometric product of $r$ vectors (versor) so that $\bm{A} = a_{1}\dots a_{r}$ the reverse is defined by @@ -396,1179 +426,1080 @@ \chapter{What is Geometric Algebra?} \bm{A}^{-1} = \bfrac{\bm{A}^{\R}}{\bm{AA}^{\R}} \end{equation} -\section{Representation of Multivectors in \emph{sympy}} +The reverse is important in the theory of rotations in $n$-dimensions. If +$R$ is the product of an even number of vectors and $RR^{\R} = 1$ +then $RaR^{\R}$ is a composition of rotations of the vector $a$. +If $R$ is the product of two vectors then the plane that $R$ defines +is the plane of the rotation. That is to say that $RaR^{\R}$ rotates the +component of $a$ that is projected into the plane defined by $a$ and +$b$ where $R=ab$. $R$ may be written +$R = e^{\frac{\theta}{2}U}$, where $\theta$ is the angle of rotation +and $U$ is a unit blade $\lp U^{2} = \pm 1\rp$ that defines the +plane of rotation. -The \emph{sympy} python module offers a simple way of representing multivectors using linear -combinations of commutative expressions (expressions consisting only of commuting \emph{sympy} objects) -and non-commutative symbols. We start by defining $n$ non-commutative \emph{sympy} symbols as a basis for -the vector space +\subsection{Reciprocal Frames} -\begin{lstlisting}[numbers=none] - (e_1,...,e_n) = symbols('e_1,...,e_n',commutative=False,real=True) -\end{lstlisting} +If we have $M$ linearly independent vectors (a frame), +$a_{1},\dots,a_{M}$, then the reciprocal frame is +$a^{1},\dots,a^{M}$ where $a_{i}\cdot a^{j} = \delta_{i}^{j}$, +$\delta_{i}^{j}$ is the Kronecker delta (zero if $i \ne j$ and one +if $i = j$). The reciprocal frame is constructed as follows: -Several software packages for numerical geometric algebra calculations are -available from Doran-Lasenby group and the Dorst group. Symbolic packages for -Clifford algebra using orthogonal bases such as -$\eb_{i}\eb_{j}+\eb_{j}\eb_{i} = 2\eta_{ij}$, where $\eta_{ij}$ is a numeric -array are available in Maple and Mathematica. The symbolic algebra module, -{\em ga}, developed for python does not depend on an orthogonal basis -representation, but rather is generated from a set of $n$ arbitrary -symbolic vectors $\eb_{1},\eb_{2},\dots,\eb_{n}$ and a symbolic metric -tensor $g_{ij} = \eb_{i}\cdot \eb_{j}$ (the symbolic metric can be symbolic constants -or symbolic function in the case of a manifold). + \begin{equation} + E_{M} = a_{1}\W\dots\W a_{M} + \end{equation} -In order not to reinvent the wheel all scalar symbolic algebra is handled by the -python module \emph{sympy} and the abstract basis vectors are encoded as -non-commuting \emph{sympy} symbols. + \begin{equation} + E_{M}^{-1} = \bfrac{E_{M}}{E_{M}^{2}} + \end{equation} -The basic geometric algebra operations will be implemented in python by defining -a geometric algebra class, {\em Ga}, that performs all required geometric algebra an -calculus operations on \emph{sympy} expressions of the form (Einstein summation convention) -\be - F +\sum_{r=1}^{n}F^{i_{1}\dots i_{r}}\eb_{i_{1}}\dots\eb_{i_{r}} -\ee -where the $F$'s are \emph{sympy} symbolic constants or functions of the -coordinates and a multivector class, {\em Mv}, that wraps {\em Ga} and overloads the python operators to provide -all the needed multivector operations as shown in Table~\ref{ops} - where $A$ and $B$ are any two multivectors (In the case of -$+$, $-$, $*$, $\W$, $|$, $<$, and $>$ the operation is also defined if $A$ or -$B$ is a \emph{sympy} symbol or a \emph{sympy} real number). +Then -\begin{table} -\begin{center} -\begin{tabular}{cc} - $A+B$ & sum of multivectors \\ - $A-B$ & difference of multivectors \\ - $A*B$ & geometric product of multivectors \\ - $A\W B$ & outer product of multivectors \\ - $A|B$ & inner product of multivectors \\ - $AB$ & right contraction of multivectors -\end{tabular} -\end{center} -\caption{Multivector operations for GA}\label{ops} -\end{table} + \begin{equation} + a^{i} = \lp -1\rp^{i-1}\lp a_{1}\W\dots\W \breve{a}_{i} \W\dots\W a_{M}\rp E_{M}^{-1} + \end{equation} -Since \T{<} and \T{>} have no r-forms (in python for the \T{<} and \T{>} operators there are no \lstinline$__rlt__()$ and - \lstinline$__rgt__()$ member functions to overload) -we can only have mixed modes (sympy scalars and multivectors) if the first operand is a multivector. +where $\breve{a}_{i}$ indicates that $a_{i}$ is to be deleted from +the product. In the standard notation if a vector is denoted with a subscript +the reciprocal vector is denoted with a superscript. The set of reciprocal vectors +will be calculated if a coordinate set is given when a geometric algebra is instantiated since +they are required for geometric differentiation when the \T{Ga} member function \T{Ga.mvr()} +is called to return the reciprocal basis in terms of the basis vectors. +\section{Manifolds and Submanifolds}\label{sect_manifold} - Except for \T{<} and \T{>} all the multivector operators have r-forms so that as long as one of the - operands, left or right, is a multivector the other can be a multivector or a scalar (\emph{sympy} symbol or integer). +A $m$-dimensional vector manifold\footnote{By the manifold embedding theorem any $m$-dimensional +manifold is isomorphic to a $m$-dimensional vector manifold}, $\mathcal{M}$, is defined by a +coordinate tuple (tuples are indicated by the vector accent ``$\vec{\;\;\;}$'') +\be + \vec{x} = \paren{x^{1},\dots,x^{m}}, +\ee +and the differentiable mapping ($U^{m}$ is an $m$-dimensional subset of $\Re^{m}$) +\be + \f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{m}\subseteq\Re^{m}\rightarrow \mathcal{V}, +\ee +where $\mathcal{V}$ is a vector space with an inner product\footnote{This product in not necessarily positive definite.} ($\cdot$) and is of $\f{\dim}{\mathcal{V}} \ge m$. - Note that the operator order precedence is determined by python and is not - necessarily that used by geometric algebra. It is \emph{absolutely essential} to - use parenthesis in multivector - expressions containing \T{\^}, \T{|}, \T{<}, and/or \T{>}. As an example let - \T{A} and \T{B} be any two multivectors. Then \T{A + A*B = A +(A*B)}, but - \lstinline!A+A^B = (2*A)^B! since in python the \T{\^} operator has a lower precedence - than the \T{+} operator. In geometric algebra the outer and inner products and - the left and right contractions have a higher precedence than the geometric - product and the geometric product has a higher precedence than addition and - subtraction. In python the \T{\^}, \T{|}, \T{>}, and \T{<} all have a lower - precedence than \T{+} and \T{-} while \T{*} has a higher precedence than - \T{+} and \T{-}. +Then a set of basis vectors for the tangent space of $\mathcal{M}$ at $\vec{x}$, $\Tn{\mathcal{M}}{\vec{x}}$, are +\be + \bm{e}_{i}^{\mathcal{M}} = \pdiff{\bm{e}^{\mathcal{M}}}{x^{i}} +\ee +and +\be + \f{g_{ij}^{\mathcal{M}}}{\vec{x}} = \bm{e}_{i}^{\mathcal{M}}\cdot\bm{e}_{j}^{\mathcal{M}}. +\ee +A $n$-dimensional ($n\le m$) submanifold $\mathcal{N}$ of $\mathcal{M}$ is defined by a coordinate tuple +\be + \vec{u} = \paren{u^{1},\dots,u^{n}}, +\ee +and a differentiable mapping +\be\label{eq_79} + \f{\vec{x}}{\vec{u}}\colon U^{n}\subseteq\Re^{n}\rightarrow U^{m}\subseteq\Re^{m}, +\ee +which induces a mapping +\be + \f{\bm{e}^{\mathcal{M}}}{\f{\vec{x}}{\vec{u}}}\colon U^{n}\subseteq\Re^{n}\rightarrow \mathcal{V}. +\ee +Then the basis vectors for the tangent space $\Tn{\mathcal{N}}{\vec{u}}$ are +(using $\f{\eb^{\mathcal{N}}}{\vec{u}} = \f{\eb^{\mathcal{M}}}{\f{\vec{x}}{\vec{u}}}$ and the chain rule)\footnote{In + this section and all following sections we are using the Einstein summation convention unless otherwise stated.} +\be + \f{\bm{e}_{i}^{\mathcal{N}}}{\vec{u}} = \pdiff{\f{\bm{e}^{\mathcal{N}}}{\vec{u}}}{u^{i}} + = \pdiff{\f{\bm{e}^{\mathcal{M}}}{\vec{x}}}{x^{j}}\pdiff{x^{j}}{u^{i}} + = \f{\bm{e}_{j}^{\mathcal{M}}}{\f{\vec{x}}{\vec{u}}}\pdiff{x^{j}}{u^{i}}, +\ee +and +\be\label{eq_81} + \f{g_{ij}^{\mathcal{N}}}{\vec{u}} = \pdiff{x^{k}}{u^{i}}\pdiff{x^{l}}{u^{j}} + \f{g_{kl}^{\mathcal{M}}}{\f{\vec{x}}{\vec{u}}}. +\ee +Going back to the base manifold, $\mathcal{M}$, note that the mapping +$\f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{n}\subseteq\Re^{n}\rightarrow \mathcal{V}$ allows us to calculate an unnormalized pseudo-scalar +for $\Tn{\mathcal{M}}{\vec{x}}$, +\be + \f{I^{\mathcal{M}}}{\vec{x}} = \f{\bm{e}_{1}^{\mathcal{M}}}{\vec{x}} + \W\dots\W\f{\bm{e}_{m}^{\mathcal{M}}}{\vec{x}}. +\ee +With the pseudo-scalar we can define a projection operator from $\mathcal{V}$ +to the tangent space of $\mathcal{M}$ by +\be + \f{P_{\vec{x}}}{\bm{v}} = (\bm{v}\cdot \f{I^{\mathcal{M}}}{\vec{x}}) + \paren{\f{I^{\mathcal{M}}}{\vec{x}}}^{-1} \;\forall\; \bm{v}\in\mathcal{V}. +\ee +In fact for each tangent space $\Tn{\mathcal{M}}{\vec{x}}$ we can define a geometric algebra +$\f{\mathcal{G}}{\Tn{\mathcal{M}}{\vec{x}}}$ with pseudo-scalar $I^{\mathcal{M}}$ so that if +$A \in \f{\mathcal{G}}{\mathcal{V}}$ then +\be + \f{P_{\vec{x}}}{A} = \paren{A\cdot \f{I^{\mathcal{M}}}{\vec{x}}} + \paren{\f{I^{\mathcal{M}}}{\vec{x}}}^{-1} + \in \f{\mathcal{G}}{\Tn{\mathcal{M}}{\vec{x}}}\;\forall\; + A \in \f{\mathcal{G}}{\mathcal{V}} +\ee +and similarly for the submanifold $\mathcal{N}$. -For those users who wish to define a default operator precedence the functions -\T{def\_prec()} and \T{GAeval()} are available in the module printer. +If the embedding $\f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{n}\subseteq\Re^{n}\rightarrow \mathcal{V}$ is not given, +but the metric tensor $\f{g_{ij}^{\mathcal{M}}}{\vec{x}}$ is given the geometric algebra of the +tangent space can be constructed. Also the derivatives of the basis vectors of the tangent space can +be calculated from the metric tensor using the Christoffel symbols, $\f{\Gamma_{ij}^{k}}{\vec{u}}$, where the derivatives of the basis vectors are given by +\be + \pdiff{\bm{e}_{j}^{\mathcal{M}}}{x^{i}} =\f{\Gamma_{ij}^{k}}{\vec{u}}\bm{e}_{k}^{\mathcal{M}}. +\ee +If we have a submanifold, $\mathcal{N}$, defined by eq.~(\ref{eq_79}) we can calculate the metric of +$\mathcal{N}$ from eq.~(\ref{eq_81}) and hence construct the geometric algebra and calculus of the +tangent space, $\Tn{\mathcal{N}}{\vec{u}}\subseteq \Tn{\mathcal{M}}{\f{\vec{x}}{\vec{u}}}$. - \lstinline$def_prec(gd,op_ord='<>|,^,*')$ - \begin{quote} - Define the precedence of the multivector operations. The function - \T{def\_prec()} must be called from the main program and the - first argument \T{gd} must be set to \T{globals()}. The second argument - \T{op\_ord} determines the operator precedence for expressions input to - the function \T{GAeval()}. The default value of \T{op\_ord} is \lstinline$'<>|,^,*'$. - For the default value the \T{<}, \T{>}, and \T{|} operations have equal - precedence followed by \T{\^}, and \T{\^} is followed by \T{*}. - \end{quote} +\textbf{If the base manifold is normalized (use the hat symbol to denote normalized tangent vectors, + $\hat{\bm{e}}_{i}^{\mathcal{M}}$, and the resulting metric tensor, $\hat{g}_{ij}^{\mathcal{M}}$) we have +$\hat{\bm{e}}_{i}^{\mathcal{M}}\cdot\hat{\bm{e}}_{i}^{\mathcal{M}} = \pm 1$ and $\hat{g}_{ij}^{\mathcal{M}}$ does not posses enough +information to calculate $g_{ij}^{\mathcal{N}}$. In that case we need to know $g_{ij}^{\mathcal{M}}$, the +metric tensor of the base manifold before normalization. Likewise, for the case of a vector +manifold unless the mapping, $\f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{m}\subseteq\Re^{m}\rightarrow \mathcal{V}$, is +constant the tangent vectors and metric tensor can only be normalized after the fact (one cannot have a +mapping that automatically normalizes all the tangent vectors).} - \T{GAeval(s,pstr=False)} - \begin{quote} - The function \T{GAeval()} returns a multivector expression defined by the - string \T{s} where the operations in the string are parsed according to - the precedences defined by \T{define\_precedence()}. \T{pstr} is a flag - to print the input and output of \T{GAeval()} for debugging purposes. - \T{GAeval()} works by adding parenthesis to the input string \T{s} with the - precedence defined by \T{op\_ord='<>|,\^,*'}. Then the parsed string is - converted to a \emph{sympy} expression using the python \T{eval()} function. - For example consider where \T{X}, \T{Y}, \T{Z}, and \T{W} are multivectors +\section{Geometric Derivative} - \begin{lstlisting}[numbers=none] - def_prec(globals()) - V = GAeval('X|Y^Z*W') - \end{lstlisting} +The directional derivative of a multivector field $\f{F}{x}$ is defined by ($a$ is a vector and $h$ is a scalar) +\be\label{eq_50} + \paren{a\cdot\nabla_{x}}F \equiv \lim_{h\rightarrow 0}\bfrac{\f{F}{x+ah}-\f{F}{x}}{h}. +\ee +Note that $a\cdot\nabla_{x}$ is a scalar operator. It will give a result containing only those grades +that are already in $F$. $\paren{a\cdot\nabla_{x}}F$ is the best linear approximation of $\f{F}{x}$ +in the direction $a$. Equation~(\ref{eq_50}) also defines the operator $\nabla_{x}$ which for +the basis vectors, $\set{\bm{e}_{i}}$, has the representation (note that the $\set{\bm{e}^{j}}$ are reciprocal +basis vectors) +\begin{equation} + \nabla_{x} F = \bm{e}^{j}\bfrac{\partial F}{\partial x^{j}} +\end{equation} +If $F_{r}$ is a $r$-grade multivector (if the independent vector, $x$, is obvious we suppress it in the +notation and just write $\nabla$) and +$F_{r} = F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W \bm{e}_{i_{r}}$ +then + \begin{equation} + \nabla F_{r} = \bfrac{\partial F_{r}^{i_{1}\dots i_{r}}}{\partial x^{j}}\bm{e}^{j}\lp\bm{e}_{i_{1}}\W + \dots\W \bm{e}_{i_{r}} \rp + \end{equation} +Note that +$\bm{e}^{j}\lp\bm{e}_{i_{1}}\W\dots\W \bm{e}_{i_{r}} \rp$ +can only contain grades $r-1$ and $r+1$ so that $\nabla F_{r}$ +also can only contain those grades. For a grade-$r$ multivector +$F_{r}$ the inner (div) and outer (curl) derivatives are - The \emph{sympy} variable \T{V} would evaluate to \lstinline!((X|Y)^Z)*W!. - \end{quote} + \begin{equation} + \nabla\cdot F_{r} = \left < \nabla F_{r}\right >_{r-1} = \bm{e}^{j}\cdot \pdiff{F_{r}}{x^{j}} + \end{equation} -\section{Vector Basis and Metric}\label{BasisMetric} +and -The two structures that define the \T{metric} class (inherited by the -geometric algebra class) are the -symbolic basis vectors and the symbolic metric. The symbolic basis -vectors are input as a string with the symbol name separated by spaces. For -example if we are calculating the geometric algebra of a system with three -vectors that we wish to denote as \T{a0}, \T{a1}, and \T{a2} we would define the -string variable: + \begin{equation} + \nabla\W F_{r} = \left < \nabla F_{r}\right >_{r+1} = \bm{e}^{j}\W \pdiff{F_{r}}{x^{j}} + \end{equation} -\begin{lstlisting}[numbers=none] - basis = 'a0 a1 a2' -\end{lstlisting} +For a general multivector function $F$ the inner and outer derivatives are +just the sum of the inner and outer derivatives of each grade of the multivector +function. -that would be input into the geometric algebra class instantiation function, \T{Ga()}. The next step would be -to define the symbolic metric for the geometric algebra of the basis we -have defined. The default metric is the most general and is the matrix of -the following symbols - - \begin{equation}\label{metric} - g = \lbrk - \begin{array}{ccc} - (a0.a0) & (a0.a1) & (a0.a2) \\ - (a0.a1) & (a1.a1) & (a1.a2) \\ - (a0.a2) & (a1.a2) & (a2.a2) \\ - \end{array} - \rbrk - \end{equation} - - -where each of the $g_{ij}$ is a symbol representing all of the dot -products of the basis vectors. Note that the symbols are named so that -$g_{ij} = g_{ji}$ since for the symbol function -$(a0.a1) \ne (a1.a0)$. +\subsection{Geometric Derivative on a Manifold} -Note that the strings shown in eq.~(\ref{metric}) are only used when the values -of $g_{ij}$ are output (printed). In the ga module (library) -the $g_{ij}$ symbols are stored in a member of the geometric algebra -instance so that if \T{o3d} is a geometric algebra then \T{o3d.g} is -the metric tensor ($g_{ij} = $\T{o3d.g[i,j]}) for that algebra. +In the case of a manifold the derivatives of the $\bm{e}_{i}$'s are functions of the coordinates, +$\set{x^{i}}$, so that the geometric derivative of a $r$-grade multivector field is +\begin{align} + \nabla F_{r} &= \bm{e}^{i}\pdiff{F_{r}}{x^{i}} = \bm{e}^{i}\pdiff{}{x^{i}} + \paren{F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} \nonumber \\ + &= \pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\bm{e}^{i}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} + +F_{r}^{i_{1}\dots i_{r}}\bm{e}^{i}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} +\end{align} +where the multivector functions $\bm{e}^{i}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}$ are the +connection for the manifold.\footnote{We use the Christoffel symbols of the first kind +to calculate the derivatives of the basis vectors and the product rule to +calculate the derivatives of the basis blades where (\url{http://en.wikipedia.org/wiki/Christoffel_symbols}) +\begin{equation*} +\Gamma_{ijk} = \half \paren{\pdiff{g_{jk}}{x^{i}}+\pdiff{g_{ik}}{x^{j}}-\pdiff{g_{ij}}{x^{k}}}, +\end{equation*} +and +\begin{equation*} +\pdiff{\eb_{j}}{x^{i}} = \Gamma_{ijk}\eb^{k}. +\end{equation*} +The Christoffel symbols of the second kind, +\begin{equation*} +\Gamma_{ij}^{k} = \half g^{kl}\paren{\pdiff{g_{li}}{x^{j}}+\pdiff{g_{lj}}{x^{i}}-\pdiff{g_{ij}}{x^{l}}}, +\end{equation*} +could also be used to calculate the derivatives in term of the original basis vectors, but since we need to calculate the +reciprocal basis vectors for the geometric derivative +it is more efficient to use the symbols of the first kind.} -The default definition of $g$ can be overwritten by specifying a string -that will define $g$. As an example consider a symbolic representation -for conformal geometry. Define for a basis +The directional (material/convective) derivative, $\paren{v\cdot\nabla}F_{r}$ is given by +\begin{align} + \paren{v\cdot\nabla} F_{r} &= v^{i}\pdiff{F_{r}}{x^{i}} = v^{i}\pdiff{}{x^{i}} + \paren{F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} \nonumber \\ + &= v^{i}\pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} + +v^{i}F_{r}^{i_{1}\dots i_{r}}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}, +\end{align} +so that the multivector connection functions for the directional derivative are +$\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}$. Be careful and note that +$\paren{v\cdot\nabla} F_{r} \ne v\cdot \paren{\nabla F_{r}}$ since the dot and geometric products are +not associative with respect to one another ($v\cdot\nabla$ is a scalar operator). -\begin{lstlisting}[numbers=none] - basis = 'a0 a1 a2 n nbar' -\end{lstlisting} +\subsection{Normalizing Basis for Derivatives} -and for a metric +The basis vector set, $\set{\bm{e}_{i}}$, is not in general normalized. We define a normalized set of basis +vectors, $\set{\bm{\hat{e}}_{i}}$, by -\begin{lstlisting}[numbers=none] - g = '# # # 0 0, # # # 0 0, # # # 0 0, 0 0 0 0 2, 0 0 0 2 0' -\end{lstlisting} +\begin{equation} + \bm{\hat{e}}_{i} = \bfrac{\bm{e}_{i}}{\sqrt{\abs{\bm{e}_{i}^{2}}}} = \bfrac{\bm{e}_{i}}{\abs{\bm{e}_{i}}}. +\end{equation} -then calling \T{cf3d = Ga(basis,g=g)} would initialize the metric tensor +This works for all $\bm{e}_{i}^{2} \neq 0$. Note that $\bm{\hat{e}}_{i}^{2} = \pm 1$. - \begin{equation} - g = \lbrk - \begin{array}{ccccc} - (a0.a0) & (a0.a1) & (a0.a2) & 0 & 0\\ - (a0.a1) & (a1.a1) & (a1.a2) & 0 & 0\\ - (a0.a2) & (a1.a2) & (a2.a2) & 0 & 0 \\ - 0 & 0 & 0 & 0 & 2 \\ - 0 & 0 & 0 & 2 & 0 - \end{array} - \rbrk - \end{equation} +Thus the geometric derivative for a set of normalized basis vectors is (where +$F_{r} = F_{r}^{i_{1}\dots i_{r}} \bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}$ and [no summation] +$\hat{F}_{r}^{i_{1}\dots i_{r}} = F_{r}^{i_{1}\dots i_{r}} \abs{\bm{\hat{e}}_{i_{1}}}\dots\abs{\bm{\hat{e}}_{i_{r}}}$). +\be + \nabla F_{r} = \eb^{i}\pdiff{F_{r}}{x^{i}} = + \pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\bm{e}^{i} + \paren{\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}} + +F_{r}^{i_{1}\dots i_{r}}\bm{e}^{i}\pdiff{}{x^{i}} + \paren{\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}}. +\ee +To calculate $\bm{e}^{i}$ in terms of the $\bm{\hat{e}}_{i}$'s we have +\begin{align} + \bm{e}^{i} &= g^{ij}\bm{e}_{j} \nonumber \\ + \bm{e}^{i} &= g^{ij}\abs{\bm{e}_{j}}\bm{\hat{e}}_{j}. +\end{align} +This is the general (non-orthogonal) formula. If the basis vectors are orthogonal then (no summation over repeated indexes) +\begin{align} + \bm{e}^{i} &= g^{ii}\abs{\bm{e}_{i}}\bm{\hat{e}}_{i} \nonumber \\ + \bm{e}^{i} &= \bfrac{\abs{\bm{e}_{i}}}{g_{ii}}\bm{\hat{e}}_{i} = \bfrac{\abs{\bm{\hat{e}}_{i}}}{\bm{e}_{i}^{2}}\bm{\hat{e}}_{i}. +\end{align} +Additionally, one can calculate the connection of the normalized basis as follows +\begin{align} + \pdiff{\paren{\abs{\bm{e}_{i}}\bm{\hat{e}}_{i}}}{x^{j}} =& \pdiff{\bm{e}_{i}}{x^{j}}, \nonumber \\ + \pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i} + +\abs{\bm{e}_{i}}\pdiff{\bm{\hat{e}}_{i}}{x^{j}} =& \pdiff{\bm{e}_{i}}{x^{j}}, \nonumber \\ + \pdiff{\bm{\hat{e}}_{i}}{x^{j}} =& \bfrac{1}{\abs{\bm{e}_{i}}}\paren{\pdiff{\bm{e}_{i}}{x^{j}} + -\pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i}},\nonumber \\ + =& \bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\bm{e}_{i}}{x^{j}} + -\bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i},\nonumber \\ + =& \bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\bm{e}_{i}}{x^{j}} + -\bfrac{1}{2g_{ii}}\pdiff{g_{ii}}{x^{j}}\bm{\hat{e}}_{i}, +\end{align} +where $\pdiff{\bm{e}_{i}}{x^{j}}$ is expanded in terms of the $\bm{\hat{e}}_{i}$'s. -for the \T{cf3d} (conformal 3-d) geometric algebra. +\subsection{Linear Differential Operators}\label{ldops} -Here we have specified that \T{n} and \T{nbar} are orthogonal to all the -\T{a}'s, \T{(n.n) = (nbar.nbar) = 0}, and \T{(n.nbar) = 2}. Using -\T{\#} in the metric definition string just tells the program to use the -default symbol for that value. +First a note on partial derivative notation. We shall use the following notation for a partial derivative where +the manifold coordinates are $x_{1},\dots,x_{n}$: +\be\label{eq_66a} + \bfrac{\partial^{j_{1}+\cdots+j_{n}}}{\partial x_{1}^{j_{1}}\dots\partial x_{n}^{j_{n}}} = \partial_{j_{1}\dots j_{n}}. +\ee +If $j_{k}=0$ the partial derivative with respect to the $k^{th}$ coordinate is not taken. If $j_{k} = 0$ for all +$1 \le k \le n$ then the partial derivative operator is the scalar one. If we consider a partial derivative where the $x$'s are +not in normal order such as +\begin{equation*} + \bfrac{\partial^{j_{1}+\cdots+j_{n}}}{\partial x_{i_{1}}^{j_{1}}\dots\partial x_{i_{n}}^{j_{n}}}, +\end{equation*} +and the $i_{k}$'s are not in ascending order. The derivative can always be put in the form in eq~(\ref{eq_66a}) since the order +of differentiation does not change the value of the partial derivative (for the smooth functions we are considering). +Additionally, using our notation the product of two partial derivative operations is given by +\be + \partial_{i_{1}\dots i_{n}}\partial_{j_{1}\dots j_{n}} = \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}. +\ee -When \T{Ga} is called multivector representations of the basis local to -the program are instantiated. For the case of an orthogonal 3-d vector -space that means the -symbolic vectors named \T{a0}, \T{a1}, and \T{a2} are created. We can -instantiate the geometric algebra and obtain the basis vectors with - +A general general multivector linear differential operator is a linear combination of multivectors and partial derivative operators +denoted by +\be\label{eq_66b} + D \equiv D^{i_{1}\dots i_{n}}\partial_{i_{1}\dots i_{n}}. +\ee +Equation~(\ref{eq_66b}) is the normal form of the differential operator in that the partial derivative operators are written to the right +of the multivector coefficients and do not operate upon the multivector coefficients. +The operator of eq~(\ref{eq_66b}) can operate on mulitvector functions, returning a multivector function via the following definitions. -\begin{lstlisting}[numbers=none] - o3d = Ga('a_1 a_2 a_3',g=[1,1,1]) - (a_1,a_2,a_3) = o3d.mv() -\end{lstlisting} -or use the \T{Ga.build()} function - +$F$ as +\be\label{eq_67a} + D\circ F = D^{j_{1}\dots j_{n}}\circ\partial_{j_{1}\dots j_{n}}F, +\ee +or +\be\label{eq_68a} + F\circ D = \partial_{j_{1}\dots j_{n}}F\circ D^{j_{1}\dots j_{n}}, +\ee +where the $D^{j_{1}\dots j_{n}}$ are multivector functions and $\circ$ is any of the multivector multiplicative operations. -\begin{lstlisting}[numbers=none] - (o3d,a_1,a_2,a_3) = Ga.build('a_1 a_2 a_3',g=[1,1,1]) -\end{lstlisting} +Equations~(\ref{eq_67a}) and (\ref{eq_68a}) are not the most general multivector linear differential operators, the most general would be +\be + \f{D}{F} = \f{D^{j_{1}\dots j_{n}}}{\partial_{j_{1}\dots j_{n}}F}, +\ee +where $\f{D^{j_{1}\dots j_{n}}}{}$ are linear multivector functionals. -Note that the python variable name for a basis vector does not have to -correspond to the name give in \T{Ga()} or \T{Ga.build()}, one may wish to use a -shortened python variable name to reduce programming (typing) errors, for -example one could use - +The definition of the sum of two differential operators is obvious since any multivector operator, $\circ$, is a bilinear operator +$\paren{\paren{D_{A}+D_{B}}\circ F = D_{A}\circ F+D_{B}\circ F}$, the product of two differential operators $D_{A}$ and $D_{B}$ operating on a multivector function $F$ is defined to be ($\circ_{1}$ and $\circ_{2}$ are any two multivector multiplicative operations) +\begin{align*} + \paren{D_{A}\circ_{1}D_{B}}\circ_{2}F &\equiv \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1} + \partial_{i_{1}\dots i_{n}}\paren{D_{B}^{j_{1}\dots j_{n}} + \partial_{j_{1}\dots j_{n}}}}\circ_{2}F \nonumber \\ + &= \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1} + \paren{\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}} + \partial_{j_{1}\dots j_{n}}+ + D_{B}^{j_{1}\dots j_{n}}} + \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}}\circ_{2}F \nonumber \\ + &= \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}}} + \circ_{2}\partial_{j_{1}\dots j_{n}}F+ + \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}D_{B}^{j_{1}\dots j_{n}}} + \circ_{2}\partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}F, +\end{align*} +where we have used the fact that the $\partial$ operator is a scalar operator and commutes with $\circ_{1}$ and $\circ_{2}$. -\begin{lstlisting}[numbers=none] - (o3d,a1,a2,a3) = Ga.build('a_1 a_2 a_3',g=[1,1,1]) -\end{lstlisting} +Thus for a pure operator product $D_{A}\circ D_{B}$ we have +\be\label{eq_71a} + D_{A}\circ D_{B} = \paren{D_{A}^{i_{1}\dots i_{n}}\circ\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}}} + \partial_{j_{1}\dots j_{n}}+ + \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}D_{B}^{j_{1}\dots j_{n}}} + \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}} +\ee +and the form of eq~(\ref{eq_71a}) is the same as eq~(\ref{eq_67a}). The basis of eq~(\ref{eq_71a}) is that the $\partial$ operator +operates on all object to the right of it as products so that the product rule must be used in all differentiations. Since eq~(\ref{eq_71a}) +puts the product of two differential operators in standard form we also evaluate $F\circ_{2}\paren{D_{A}\circ_{1}D_{B}}$. -or +We now must distinguish between the following cases. If $D$ is a differential operator and $F$ a multivector function should $D\circ F$ and +$F\circ D$ return a differential operator or a multivector. In order to be consistent with the standard vector analysis we have $D\circ F$ +return a multivector and $F\circ D$ return a differential operator. Then we define the complementary differential operator $\bar{D}$ which +is identical to $D$ except that $\bar{D}\circ F$ returns a differential operator according to eq~(\ref{eq_71a})\footnote{In this case +$D_{B}^{j_{1}\dots j_{n}} = F$ and $\partial_{j_{1}\dots j_{n}} = 1$.} and $F\circ\bar{D}$ returns a multivector according to eq~(\ref{eq_68a}). -\begin{lstlisting}[numbers=none] - (st4d,g0,g1,g2,g3) = Ga.build('gamma_0 gamma_1 gamma_2 gamma_3',\ - g=[1,-1,-1,-1]) -\end{lstlisting} +A general differential operator is built from repeated applications of the basic operator building blocks $\paren{\bar{\nabla}\circ A}$, +$\paren{A\circ\bar{\nabla}}$, $\paren{\bar{\nabla}\circ\bar{\nabla}}$, and $\paren{A\pm \bar{\nabla}}$. Both $\nabla$ and $\bar{\nabla}$ +are represented by the operator +\be + \nabla = \bar{\nabla} = e^{i}\pdiff{}{x^{i}}, +\ee +but are flagged to produce the appropriate result. -for Minkowski space time. +In the our notation the directional derivative operator is $a\cdot\nabla$, the Laplacian +$\nabla\cdot\nabla$ and the expression for the Riemann tensor, $R^{i}_{jkl}$, is +\be + \paren{\nabla\W\nabla}\eb^{i} = \half R^{i}_{jkl}\paren{\eb^{j}\W\eb^{k}}\eb^{l}. +\ee +We would use the complement if we wish a quantum mechanical type commutator defining +\be + \com{x,\nabla} \equiv x\nabla - \bar{\nabla}x, +\ee +or if we wish to simulate the dot notation (Doran and Lasenby) +\be + \dot{F}\dot{\nabla} = F\bar{\nabla}. +\ee -If the latex printer is used \T{e1} would print as $\bm{e_{1}}$ -and \T{g1} as $\bm{\gamma_{1}}$. +\section{Linear Transformations/Outermorphisms}\label{Ltrans} -\notebox{ - Additionally \T{Ga()} and \T{Ga.build()} has simplified options for naming a set of basis vectors and for - inputing an orthogonal basis. - \vspace{4pt} - If one wishes to name the basis vectors $\bm{e}_{x}$, $\bm{e}_{y}$, and - $\bm{e}_{z}$ then set \T{basis='e*x|y|z'} or to name $\bm{\gamma}_{t}$, - $\bm{\gamma}_{x}$, $\bm{\gamma}_{y}$, and $\bm{\gamma}_{z}$ then set - \T{basis='gamma*t|x|y|z'}. - For the case of an orthogonal basis if the signature of the - vector space is $(1,1,1)$ (Euclidean 3-space) set \T{g=[1,1,1]} or if it - is $(1,-1,-1,-1)$ (Minkowski 4-space) set \T{g=[1,-1,-1,-1]}. If \T{g} is a - function of position then \T{g} can be entered as a \emph{sympy} matrix with \emph{sympy} - functions as the entries of the matrix or as a list of functions for the - case of a orthogonal metric. In the case of spherical coordinates we have - \T{g=[1,r**2,r**2*sin(th)**2]}. - } - -\section{Representation and Reduction of Multivector Bases} - -In our symbolic geometric algebra all multivectors -can be obtained from the symbolic basis vectors we have input, via the -different operations available to geometric algebra. The first problem we have -is representing the general multivector in terms terms of the basis vectors. To -do this we form the ordered geometric products of the basis vectors and develop -an internal representation of these products in terms of python classes. The -ordered geometric products are all multivectors of the form -$a_{i_{1}}a_{i_{2}}\dots a_{i_{r}}$ where $i_{1}0}A_{r}\cdot B_{s} - \end{equation} - - \begin{equation} - A\wedge B = \sum_{r,s}A_{r}\wedge B_{s} - \end{equation} - -Likewise the right ($\lfloor$) and left ($\rfloor$) contractions are defined as - - \begin{equation} - A_{r}\lfloor B_{s} = \left \{ \begin{array}{cc} - \proj{A_{r}B_{s}}{r-s} & r \ge s \\ - 0 & r < s \end{array} \right \} - \end{equation} - - \begin{equation} - A_{r}\rfloor B_{s} = \left \{ \begin{array}{cc} - \proj{A_{r}B_{s}}{s-r} & s \ge r \\ - 0 & s < r \end{array} \right \} - \end{equation} - -and - - \begin{equation} - A\lfloor B = \sum_{r,s}A_{r}\lfloor B_{s} - \end{equation} - - \begin{equation} - A\rfloor B = \sum_{r,s}A_{r}\rfloor B_{s} - \end{equation} - -\warningbox{ - In the \T{Mv} class we have overloaded the \T{\^} operator to represent the outer - product so that instead of calling the outer product function we can write \lstinline!mv1^mv2!. - Due to the precedence rules for python it is \emph{absolutely essential} to enclose outer products - in parenthesis.} - -\warningbox{ - In the \T{Mv} class we have overloaded the \T{|} operator for the inner product, - \T{>} operator for the right contraction, and \T{<} operator for the left contraction. - Instead of calling the inner product function we can write \T{mv1|mv2}, \T{mv1>mv2}, or - \T{mv1$ the operation is also defined if $A$ or +$B$ is a \emph{sympy} symbol or a \emph{sympy} real number). + +\begin{table} +\begin{center} +\begin{tabular}{cc} + $A+B$ & sum of multivectors \\ + $A-B$ & difference of multivectors \\ + $A*B$ & geometric product of multivectors \\ + $A\W B$ & outer product of multivectors \\ + $A|B$ & inner product of multivectors \\ + $AB$ & right contraction of multivectors \\ + $A/B$ & division of multivectors\footnotemark +\end{tabular} +\end{center} +\caption{Multivector operations for GA}\label{ops} +\end{table} +\footnotetext{Division uses right multiplication by + the inverse function, $A/B = AB^{-1}$, for those cases where $B^{-1}$ can + be calculated ($B$, or $B^{2}$, or $BB^{\R}$ is a scalar).} +Since \T{<} and \T{>} have no r-forms (in python for the \T{<} and \T{>} operators there are no \lstinline$__rlt__()$ and + \lstinline$__rgt__()$ member functions to overload) +we can only have mixed modes (sympy scalars and multivectors) if the first operand is a multivector. + + + Except for \T{<} and \T{>} all the multivector operators have r-forms so that as long as one of the + operands, left or right, is a multivector the other can be a multivector or a scalar (\emph{sympy} symbol or number). + +\subsection{Operator Precedence}\label{OpPrec} + \textbf{\textit{Note that the operator order precedence is determined by python and is not + necessarily that used by geometric algebra. It is \emph{absolutely essential} to + use parenthesis in multivector + expressions containing \T{\^}, \T{|}, \T{<}, and/or \T{>}. As an example let + \T{A} and \T{B} be any two multivectors. Then \T{A + A*B = A +(A*B)}, but + \lstinline!A+A^B = (2*A)^B! since in python the \T{\^} operator has a lower precedence + than the \T{+} operator. In geometric algebra the outer and inner products and + the left and right contractions have a higher precedence than the geometric + product and the geometric product has a higher precedence than addition and + subtraction. In python the \T{\^}, \T{|}, \T{>}, and \T{<} all have a lower + precedence than \T{+} and \T{-} while \T{*} has a higher precedence than + \T{+} and \T{-}.}} + + \textbf{Additional care has to be used when using the operators \T{!=} and \T{==} with + the operators \T{<} and \T{>}. All these operators have the same precedence and are + evaluated chained from left to right. To be completely safe for expressions such as + \T{A == B} or \T{A != B} always user \T{(A) == (B)} and \T{(A) != (B)} if \T{A} or \T{B} + contains a left, \T{<}, or right, \T{>}, contraction.} + +For those users who wish to define a default operator precedence the functions +\T{def\_prec()} and \T{GAeval()} are available in the module printer. + + \lstinline$def_prec(gd,op_ord='<>|,^,*')$ + \begin{quote} + Define the precedence of the multivector operations. The function + \T{def\_prec()} must be called from the main program and the + first argument \T{gd} must be set to \T{globals()}. The second argument + \T{op\_ord} determines the operator precedence for expressions input to + the function \T{GAeval()}. The default value of \T{op\_ord} is \lstinline$'<>|,^,*'$. + For the default value the \T{<}, \T{>}, and \T{|} operations have equal + precedence followed by \T{\^}, and \T{\^} is followed by \T{*}. + \end{quote} -If the embedding $\f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{n}\subseteq\Re^{n}\rightarrow \mathcal{V}$ is not given, -but the metric tensor $\f{g_{ij}^{\mathcal{M}}}{\vec{x}}$ is given the geometric algebra of the -tangent space can be constructed. Also the derivatives of the basis vectors of the tangent space can -be calculated from the metric tensor using the Christoffel symbols, $\f{\Gamma_{ij}^{k}}{\vec{u}}$, where the derivatives of the basis vectors are given by -\be - \pdiff{\bm{e}_{j}^{\mathcal{M}}}{x^{i}} =\f{\Gamma_{ij}^{k}}{\vec{u}}\bm{e}_{k}^{\mathcal{M}}. -\ee -If we have a submanifold, $\mathcal{N}$, defined by eq.~(\ref{eq_79}) we can calculate the metric of -$\mathcal{N}$ from eq.~(\ref{eq_81}) and hence construct the geometric algebra and calculus of the -tangent space, $\Tn{\mathcal{N}}{\vec{u}}\subseteq \Tn{\mathcal{M}}{\f{\vec{x}}{\vec{u}}}$. + \T{GAeval(s,pstr=False)} + \begin{quote} + The function \T{GAeval()} returns a multivector expression defined by the + string \T{s} where the operations in the string are parsed according to + the precedences defined by \T{define\_precedence()}. \T{pstr} is a flag + to print the input and output of \T{GAeval()} for debugging purposes. + \T{GAeval()} works by adding parenthesis to the input string \T{s} with the + precedence defined by \T{op\_ord='<>|,\^,*'}. Then the parsed string is + converted to a \emph{sympy} expression using the python \T{eval()} function. + For example consider where \T{X}, \T{Y}, \T{Z}, and \T{W} are multivectors -If the base manifold is normalized (use the hat symbol to denote normalized tangent vectors, - $\hat{\bm{e}}_{i}^{\mathcal{M}}$, and the resulting metric tensor, $\hat{g}_{ij}^{\mathcal{M}}$) we have -$\hat{\bm{e}}_{i}^{\mathcal{M}}\cdot\hat{\bm{e}}_{i}^{\mathcal{M}} = \pm 1$ and $\hat{g}_{ij}^{\mathcal{M}}$ does not posses enough -information to calculate $g_{ij}^{\mathcal{N}}$. In that case we need to know $g_{ij}^{\mathcal{M}}$, the -metric tensor of the base manifold before normalization. Likewise, for the case of a vector -manifold unless the mapping, $\f{\bm{e}^{\mathcal{M}}}{\vec{x}}\colon U^{m}\subseteq\Re^{m}\rightarrow \mathcal{V}$, is -constant the tangent vectors and metric tensor can only be normalized after the fact (one cannot have a -mapping that automatically normalizes all the tangent vectors). + \begin{lstlisting}[numbers=none] + def_prec(globals()) + V = GAeval('X|Y^Z*W') + \end{lstlisting} -\section{Geometric Derivative} + The \emph{sympy} variable \T{V} would evaluate to \lstinline!((X|Y)^Z)*W!. + \end{quote} -The directional derivative of a multivector field $\f{F}{x}$ is defined by ($a$ is a vector and $h$ is a scalar) -\be\label{eq_50} - \paren{a\cdot\nabla_{x}}F \equiv \lim_{h\rightarrow 0}\bfrac{\f{F}{x+ah}-\f{F}{x}}{h}. -\ee -Note that $a\cdot\nabla_{x}$ is a scalar operator. It will give a result containing only those grades -that are already in $F$. $\paren{a\cdot\nabla_{x}}F$ is the best linear approximation of $\f{F}{x}$ -in the direction $a$. Equation~(\ref{eq_50}) also defines the operator $\nabla_{x}$ which for -the basis vectors, $\set{\bm{e}_{i}}$, has the representation (note that the $\set{\bm{e}^{j}}$ are reciprocal -basis vectors) -\begin{equation} - \nabla_{x} F = \bm{e}^{j}\bfrac{\partial F}{\partial x^{j}} -\end{equation} -If $F_{r}$ is a $r$-grade multivector (if the independent vector, $x$, is obvious we suppress it in the -notation and just write $\nabla$) and -$F_{r} = F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W \bm{e}_{i_{r}}$ -then - \begin{equation} - \nabla F_{r} = \bfrac{\partial F_{r}^{i_{1}\dots i_{r}}}{\partial x^{j}}\bm{e}^{j}\lp\bm{e}_{i_{1}}\W - \dots\W \bm{e}_{i_{r}} \rp - \end{equation} -Note that -$\bm{e}^{j}\lp\bm{e}_{i_{1}}\W\dots\W \bm{e}_{i_{r}} \rp$ -can only contain grades $r-1$ and $r+1$ so that $\nabla F_{r}$ -also can only contain those grades. For a grade-$r$ multivector -$F_{r}$ the inner (div) and outer (curl) derivatives are +\section{Vector Basis and Metric}\label{BasisMetric} - \begin{equation} - \nabla\cdot F_{r} = \left < \nabla F_{r}\right >_{r-1} = \bm{e}^{j}\cdot \pdiff{F_{r}}{x^{j}} - \end{equation} +The two structures that define the \T{metric} class (inherited by the +geometric algebra class) are the +symbolic basis vectors and the symbolic metric. The symbolic basis +vectors are input as a string with the symbol name separated by spaces. For +example if we are calculating the geometric algebra of a system with three +vectors that we wish to denote as \T{a0}, \T{a1}, and \T{a2} we would define the +string variable: -and +\begin{lstlisting}[numbers=none] + basis = 'a0 a1 a2' +\end{lstlisting} - \begin{equation} - \nabla\W F_{r} = \left < \nabla F_{r}\right >_{r+1} = \bm{e}^{j}\W \pdiff{F_{r}}{x^{j}} +that would be input into the geometric algebra class instantiation function, \T{Ga()}. The next step would be +to define the symbolic metric for the geometric algebra of the basis we +have defined. The default metric is the most general and is the matrix of +the following symbols + + \begin{equation}\label{metric} + g = \lbrk + \begin{array}{ccc} + (a0.a0) & (a0.a1) & (a0.a2) \\ + (a0.a1) & (a1.a1) & (a1.a2) \\ + (a0.a2) & (a1.a2) & (a2.a2) \\ + \end{array} + \rbrk \end{equation} -For a general multivector function $F$ the inner and outer derivatives are -just the sum of the inner and outer derivatives of each grade of the multivector -function. -\subsection{Geometric Derivative on a Manifold} +where each of the $g_{ij}$ is a symbol representing all of the dot +products of the basis vectors. Note that the symbols are named so that +$g_{ij} = g_{ji}$ since for the symbol function +$(a0.a1) \ne (a1.a0)$. -In the case of a manifold the derivatives of the $\bm{e}_{i}$'s are functions of the coordinates, -$\set{x^{i}}$, so that the geometric derivative of a $r$-grade multivector field is (Einstein summation -convention) -\begin{align} - \nabla F_{r} &= \bm{e}^{i}\pdiff{F_{r}}{x^{i}} = \bm{e}^{i}\pdiff{}{x^{i}} - \paren{F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} \nonumber \\ - &= \pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\bm{e}^{i}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} - +F_{r}^{i_{1}\dots i_{r}}\bm{e}^{i}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} -\end{align} -where the multivector functions $\bm{e}^{i}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}$ are the -connection for the manifold.\footnote{We use the Christoffel symbols of the first kind -to calculate the derivatives of the basis vectors and the product rule to -calculate the derivatives of the basis blades where (\url{http://en.wikipedia.org/wiki/Christoffel_symbols}) -\begin{equation*} -\Gamma_{ijk} = \half \paren{\pdiff{g_{jk}}{x^{i}}+\pdiff{g_{ik}}{x^{j}}-\pdiff{g_{ij}}{x^{k}}}, -\end{equation*} -and -\begin{equation*} -\pdiff{\eb_{j}}{x^{i}} = \Gamma_{ijk}\eb^{k}. -\end{equation*} -The Christoffel symbols of the second kind, -\begin{equation*} -\Gamma_{ij}^{k} = \half g^{kl}\paren{\pdiff{g_{li}}{x^{j}}+\pdiff{g_{lj}}{x^{i}}-\pdiff{g_{ij}}{x^{l}}}, -\end{equation*} -could also be used to calculate the derivatives in term of the original basis vectors, but since we need to calculate the -reciprocal basis vectors for the geometric derivative -it is more efficient to use the symbols of the first kind.} +Note that the strings shown in eq.~(\ref{metric}) are only used when the values +of $g_{ij}$ are output (printed). In the ga module (library) +the $g_{ij}$ symbols are stored in a member of the geometric algebra +instance so that if \T{o3d} is a geometric algebra then \T{o3d.g} is +the metric tensor ($g_{ij} = $\T{o3d.g[i,j]}) for that algebra. -The directional (material/convective) derivative, $\paren{v\cdot\nabla}F_{r}$ is given by -\begin{align} - \paren{v\cdot\nabla} F_{r} &= v^{i}\pdiff{F_{r}}{x^{i}} = v^{i}\pdiff{}{x^{i}} - \paren{F_{r}^{i_{1}\dots i_{r}}\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} \nonumber \\ - &= v^{i}\pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}} - +v^{i}F_{r}^{i_{1}\dots i_{r}}\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}, -\end{align} -so that the multivector connection functions for the directional derivative are -$\pdiff{}{x^{i}}\paren{\bm{e}_{i_{1}}\W\dots\W\bm{e}_{i_{r}}}$. Be careful and note that -$\paren{v\cdot\nabla} F_{r} \ne v\cdot \paren{\nabla F_{r}}$ since the dot and geometric products are -not associative with respect to one another ($v\cdot\nabla$ is a scalar operator). +The default definition of $g$ can be overwritten by specifying a string +that will define $g$. As an example consider a symbolic representation +for conformal geometry. Define for a basis -\subsection{Normalizing Basis for Derivatives} +\begin{lstlisting}[numbers=none] + basis = 'a0 a1 a2 n nbar' +\end{lstlisting} -The basis vector set, $\set{\bm{e}_{i}}$, is not in general normalized. We define a normalized set of basis -vectors, $\set{\bm{\hat{e}}_{i}}$, by +and for a metric -\begin{equation} - \bm{\hat{e}}_{i} = \bfrac{\bm{e}_{i}}{\sqrt{\abs{\bm{e}_{i}^{2}}}} = \bfrac{\bm{e}_{i}}{\abs{\bm{e}_{i}}}. -\end{equation} +\begin{lstlisting}[numbers=none] + g = '# # # 0 0, # # # 0 0, # # # 0 0, 0 0 0 0 2, 0 0 0 2 0' +\end{lstlisting} -This works for all $\bm{e}_{i}^{2} \neq 0$. Note that $\bm{\hat{e}}_{i}^{2} = \pm 1$. +then calling \T{cf3d = Ga(basis,g=g)} would initialize the metric tensor -Thus the geometric derivative for a set of normalized basis vectors is (where -$F_{r} = F_{r}^{i_{1}\dots i_{r}} \bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}$ and [no summation] -$\hat{F}_{r}^{i_{1}\dots i_{r}} = F_{r}^{i_{1}\dots i_{r}} \abs{\bm{\hat{e}}_{i_{1}}}\dots\abs{\bm{\hat{e}}_{i_{r}}}$). -\be - \nabla F_{r} = \eb^{i}\pdiff{F_{r}}{x^{i}} = - \pdiff{F_{r}^{i_{1}\dots i_{r}}}{x^{i}}\bm{e}^{i} - \paren{\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}} - +F_{r}^{i_{1}\dots i_{r}}\bm{e}^{i}\pdiff{}{x^{i}} - \paren{\bm{\hat{e}}_{i_{1}}\W\dots\W\bm{\hat{e}}_{i_{r}}}. -\ee -To calculate $\bm{e}^{i}$ in terms of the $\bm{\hat{e}}_{i}$'s we have -\begin{align} - \bm{e}^{i} &= g^{ij}\bm{e}_{j} \nonumber \\ - \bm{e}^{i} &= g^{ij}\abs{\bm{e}_{j}}\bm{\hat{e}}_{j}. -\end{align} -This is the general (non-orthogonal) formula. If the basis vectors are orthogonal then (no summation over repeated indexes) -\begin{align} - \bm{e}^{i} &= g^{ii}\abs{\bm{e}_{i}}\bm{\hat{e}}_{i} \nonumber \\ - \bm{e}^{i} &= \bfrac{\abs{\bm{e}_{i}}}{g_{ii}}\bm{\hat{e}}_{i} = \bfrac{\abs{\bm{\hat{e}}_{i}}}{\bm{e}_{i}^{2}}\bm{\hat{e}}_{i}. -\end{align} -Additionally, one can calculate the connection of the normalized basis as follows -\begin{align} - \pdiff{\paren{\abs{\bm{e}_{i}}\bm{\hat{e}}_{i}}}{x^{j}} =& \pdiff{\bm{e}_{i}}{x^{j}}, \nonumber \\ - \pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i} - +\abs{\bm{e}_{i}}\pdiff{\bm{\hat{e}}_{i}}{x^{j}} =& \pdiff{\bm{e}_{i}}{x^{j}}, \nonumber \\ - \pdiff{\bm{\hat{e}}_{i}}{x^{j}} =& \bfrac{1}{\abs{\bm{e}_{i}}}\paren{\pdiff{\bm{e}_{i}}{x^{j}} - -\pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i}},\nonumber \\ - =& \bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\bm{e}_{i}}{x^{j}} - -\bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\abs{\bm{e}_{i}}}{x^{j}}\bm{\hat{e}}_{i},\nonumber \\ - =& \bfrac{1}{\abs{\bm{e}_{i}}}\pdiff{\bm{e}_{i}}{x^{j}} - -\bfrac{1}{2g_{ii}}\pdiff{g_{ii}}{x^{j}}\bm{\hat{e}}_{i}, -\end{align} -where $\pdiff{\bm{e}_{i}}{x^{j}}$ is expanded in terms of the $\bm{\hat{e}}_{i}$'s. + \begin{equation} + g = \lbrk + \begin{array}{ccccc} + (a0.a0) & (a0.a1) & (a0.a2) & 0 & 0\\ + (a0.a1) & (a1.a1) & (a1.a2) & 0 & 0\\ + (a0.a2) & (a1.a2) & (a2.a2) & 0 & 0 \\ + 0 & 0 & 0 & 0 & 2 \\ + 0 & 0 & 0 & 2 & 0 + \end{array} + \rbrk + \end{equation} -\subsection{Linear Differential Operators}\label{ldops} +for the \T{cf3d} (conformal 3-d) geometric algebra. -First a note on partial derivative notation. We shall use the following notation for a partial derivative where -the manifold coordinates are $x_{1},\dots,x_{n}$: -\be\label{eq_66a} - \bfrac{\partial^{j_{1}+\cdots+j_{n}}}{\partial x_{1}^{j_{1}}\dots\partial x_{n}^{j_{n}}} = \partial_{j_{1}\dots j_{n}}. -\ee -If $j_{k}=0$ the partial derivative with respect to the $k^{th}$ coordinate is not taken. If the $j_{k} = 0$ for all -$1 \le k \le n$ then the partial derivative operator is the scalar one. If we consider a partial derivative where the $x$'s are -not in normal order such as -\begin{equation*} - \bfrac{\partial^{j_{1}+\cdots+j_{n}}}{\partial x_{i_{1}}^{j_{1}}\dots\partial x_{i_{n}}^{j_{n}}}, -\end{equation*} -and the $i_{k}$'s are not in ascending order. The derivative can always be put in the form in eq~(\ref{eq_66a}) since the order -of differentiation does not change the value of the partial derivative (for the smooth functions we are considering). -Additionally, using our notation the product of two partial derivative operations is given by -\be - \partial_{i_{1}\dots i_{n}}\partial_{j_{1}\dots j_{n}} = \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}. -\ee +Here we have specified that \T{n} and \T{nbar} are orthogonal to all the +\T{a}'s, \T{(n.n) = (nbar.nbar) = 0}, and \T{(n.nbar) = 2}. Using +\T{\#} in the metric definition string just tells the program to use the +default symbol for that value. -A general general multivector linear differential operator is a linear combination of multivectors and partial derivative operators -denoted by (in all of this section we will use the Einstein summation convention) -\be\label{eq_66b} - D \equiv D^{i_{1}\dots i_{n}}\partial_{i_{1}\dots i_{n}}. -\ee -Equation~(\ref{eq_66b}) is the normal form of the differential operator in that the partial derivative operators are written to the right -of the multivector coefficients and do not operate upon the multivector coefficients. -The operator of eq~(\ref{eq_66b}) can operate on mulitvector functions, returning a multivector function via the following definitions. +When \T{Ga} is called multivector representations of the basis local to +the program are instantiated. For the case of an orthogonal 3-d vector +space that means the +symbolic vectors named \T{a0}, \T{a1}, and \T{a2} are created. We can +instantiate the geometric algebra and obtain the basis vectors with - + +\begin{lstlisting}[numbers=none] + o3d = Ga('a_1 a_2 a_3',g=[1,1,1]) + (a_1,a_2,a_3) = o3d.mv() +\end{lstlisting} + +or use the \T{Ga.build()} function - + +\begin{lstlisting}[numbers=none] + (o3d,a_1,a_2,a_3) = Ga.build('a_1 a_2 a_3',g=[1,1,1]) +\end{lstlisting} +Note that the python variable name for a basis vector does not have to +correspond to the name give in \T{Ga()} or \T{Ga.build()}, one may wish to use a +shortened python variable name to reduce programming (typing) errors, for +example one could use - + +\begin{lstlisting}[numbers=none] + (o3d,a1,a2,a3) = Ga.build('a_1 a_2 a_3',g=[1,1,1]) +\end{lstlisting} -$F$ as (Einstein summation convention) -\be\label{eq_67a} - D\circ F = D^{j_{1}\dots j_{n}}\circ\partial_{j_{1}\dots j_{n}}F, -\ee or -\be\label{eq_68a} - F\circ D = \partial_{j_{1}\dots j_{n}}F\circ D^{j_{1}\dots j_{n}}, -\ee -where the $D^{j_{1}\dots j_{n}}$ are multivector functions and $\circ$ is any of the multivector multiplicative operations. -Equations~(\ref{eq_67a}) and (\ref{eq_68a}) are not the most general multivector linear differential operators, the most general would be -\be - \f{D}{F} = \f{D^{j_{1}\dots j_{n}}}{\partial_{j_{1}\dots j_{n}}F}, -\ee -where $\f{D^{j_{1}\dots j_{n}}}{}$ are linear multivector functionals. +\begin{lstlisting}[numbers=none] + (st4d,g0,g1,g2,g3) = Ga.build('gamma_0 gamma_1 gamma_2 gamma_3',\ + g=[1,-1,-1,-1]) +\end{lstlisting} -The definition of the sum of two differential operators is obvious since any multivector operator, $\circ$, is a bilinear operator -$\paren{\paren{D_{A}+D_{B}}\circ F = D_{A}\circ F+D_{B}\circ F}$, the product of two differential operators $D_{A}$ and $D_{B}$ operating on a multivector function $F$ is defined to be ($\circ_{1}$ and $\circ_{2}$ are any two multivector multiplicative operations) -\begin{align*} - \paren{D_{A}\circ_{1}D_{B}}\circ_{2}F &\equiv \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1} - \partial_{i_{1}\dots i_{n}}\paren{D_{B}^{j_{1}\dots j_{n}} - \partial_{j_{1}\dots j_{n}}}}\circ_{2}F \nonumber \\ - &= \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1} - \paren{\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}} - \partial_{j_{1}\dots j_{n}}+ - D_{B}^{j_{1}\dots j_{n}}} - \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}}\circ_{2}F \nonumber \\ - &= \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}}} - \circ_{2}\partial_{j_{1}\dots j_{n}}F+ - \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}D_{B}^{j_{1}\dots j_{n}}} - \circ_{2}\partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}}F, -\end{align*} -where we have used the fact that the $\partial$ operator is a scalar operator and commutes with $\circ_{1}$ and $\circ_{2}$. +for Minkowski space time. -Thus for a pure operator product $D_{A}\circ D_{B}$ we have -\be\label{eq_71a} - D_{A}\circ D_{B} = \paren{D_{A}^{i_{1}\dots i_{n}}\circ\paren{\partial_{i_{1}\dots i_{n}}D_{B}^{j_{1}\dots j_{n}}}} - \partial_{j_{1}\dots j_{n}}+ - \paren{D_{A}^{i_{1}\dots i_{n}}\circ_{1}D_{B}^{j_{1}\dots j_{n}}} - \partial_{i_{1}+j_{1},\dots, i_{n}+j_{n}} -\ee -and the form of eq~(\ref{eq_71a}) is the same as eq(\ref{eq_67a}). The basis of eq~(\ref{eq_71a}) is that the $\partial$ operator -operates on all object to the right of it as products so that the product rule must be used in all differentiations. Since eq~(\ref{eq_71a}) -puts the product of two differential operators in standard form we also evaluate $F\circ_{2}\paren{D_{A}\circ_{1}D_{B}}$. +If the latex printer is used \T{e1} would print as $\bm{e_{1}}$ +and \T{g1} as $\bm{\gamma_{1}}$. -We now must distinguish between the following cases. If $D$ is a differential operator and $F$ a multivector function should $D\circ F$ and -$F\circ D$ return a differential operator or a multivector. In order to be consistent with the standard vector analysis we have $D\circ F$ -return a multivector and $F\circ D$ return a differential operator. The we define the complementary differential operator $\bar{D}$ which -is identical to $D$ except that $\bar{D}\circ F$ returns a differential operator according to eq~(\ref{eq_71a})\footnote{In this case -$D_{B}^{j_{1}\dots j_{n}} = F$ and $\partial_{j_{1}\dots j_{n}} = 1$.} and $F\circ\bar{D}$ returns a multivector according to eq~(\ref{eq_68a}). +\notebox{ + Additionally \T{Ga()} and \T{Ga.build()} has simplified options for naming a set of basis vectors and for + inputing an orthogonal basis. + \vspace{4pt} + If one wishes to name the basis vectors $\bm{e}_{x}$, $\bm{e}_{y}$, and + $\bm{e}_{z}$ then set \T{basis='e*x|y|z'} or to name $\bm{\gamma}_{t}$, + $\bm{\gamma}_{x}$, $\bm{\gamma}_{y}$, and $\bm{\gamma}_{z}$ then set + \T{basis='gamma*t|x|y|z'}. + For the case of an orthogonal basis if the signature of the + vector space is $(1,1,1)$ (Euclidean 3-space) set \T{g=[1,1,1]} or if it + is $(1,-1,-1,-1)$ (Minkowski 4-space) set \T{g=[1,-1,-1,-1]}. If \T{g} is a + function of position then \T{g} can be entered as a \emph{sympy} matrix with \emph{sympy} + functions as the entries of the matrix or as a list of functions for the + case of a orthogonal metric. In the case of spherical coordinates we have + \T{g=[1,r**2,r**2*sin(th)**2]}. + } -A general differential operator is built from repeated applications of the basic operator building blocks $\paren{\bar{\nabla}\circ A}$, -$\paren{A\circ\bar{\nabla}}$, $\paren{\bar{\nabla}\circ\bar{\nabla}}$, and $\paren{A\pm \bar{\nabla}}$. Both $\nabla$ and $\bar{\nabla}$ -are represented by the operator -\be - \nabla = \bar{\nabla} = e^{i}\pdiff{}{x^{i}}, -\ee -but are flagged to produce the appropriate result. +\section{Representation and Reduction of Multivector Bases} -In the our notation the directional derivative operator is $a\cdot\nabla$, the Laplacian -$\nabla\cdot\nabla$ and the expression for the Riemann tensor, $R^{i}_{jkl}$, is -\be - \paren{\nabla\W\nabla}\eb^{i} = \half R^{i}_{jkl}\paren{\eb^{j}\W\eb^{k}}\eb^{l}. -\ee -We would use the complement if we wish a quantum mechanical type commutator defining -\be - \com{x,\nabla} \equiv x\nabla - \bar{\nabla}x, -\ee -or if we wish to simulate the dot notation (Doran and Lasenby) -\be - \dot{F}\dot{\nabla} = F\bar{\nabla}. -\ee +In our symbolic geometric algebra all multivectors +can be obtained from the symbolic basis vectors we have input, via the +different operations available to geometric algebra. The first problem we have +is representing the general multivector in terms terms of the basis vectors. To +do this we form the ordered geometric products of the basis vectors and develop +an internal representation of these products in terms of python classes. The +ordered geometric products are all multivectors of the form +$a_{i_{1}}a_{i_{2}}\dots a_{i_{r}}$ where $i_{1} 0$ is assumed so that - \begin{equation*} - e^{A} = \f{\cosh}{\sqrt{A^{2}}}+\f{\sinh}{\sqrt{A^{2}}}\bfrac{A}{\sqrt{A^{2}}}. - \end{equation*} + If $A$ is a multivector then $e^{A}$ is defined for any $A$ via the series expansion for $e$. However as + a practical matter we only have a simple closed form formula for $e^{A}$ if $A^{2}$ is a scalar.\footnote{In the + future it should be possible to generate closed form expressions for $e^{A}$ if $A^{r}$ is a scalar for some + interger $r$.} If $A^{2}$ is a scalar and we know the sign of $A^{2}$ we have the following formulas for $e^{A}$. + \begin{center} + \begin{tabular}{lll} + $A^{2} > 0$: & & \\ + & $A = \sqrt{A^{2}} \bfrac{A}{\sqrt{A^{2}}}$, & $e^{A} = \f{\cosh}{\sqrt{A^{2}}}+\f{\sinh}{\sqrt{A^{2}}}\bfrac{A}{\sqrt{A^{2}}}$ \\ + $A^{2} < 0$: & & \\ + & $A = \sqrt{-A^{2}} \bfrac{A}{\sqrt{-A^{2}}}$, & $e^{A} = \f{\cos}{\sqrt{-A^{2}}}+\f{\sin}{\sqrt{-A^{2}}}\bfrac{A}{\sqrt{-A^{2}}}$ \\ + $A^{2} = 0$: & & \\ + & & $e^{A} = 1 + A$ + \end{tabular} + \end{center} The hint is required for symbolic multivectors $A$ since in general \emph{sympy} cannot determine if - $A^{2}$ is positive or negative. If $A$ is purely numeric the hint is ignored. + $A^{2}$ is positive or negative. If $A$ is purely numeric the hint is ignored since the sign can be calculated. \end{quote} \T{expand(self)} @@ -1981,8 +1930,11 @@ \section{Basic Multivector Class Functions} \T{inv(self)} \begin{quote} - Return the inverse of the multivector $M$ (\T{M.inv()}) if $MM^{\R}$ is a non-zero scalar. If $MM^{\R}$ - is not a scalar the program exits with an error message. + Return the inverse of the multivector $M$ (\T{M.inv()}). If $M$ is a non-zero scalar return $1/M$. If $M^{2}$ is a non-zero + scalar return $M/\paren{M^{2}}$, If $MM^{\R}$ is a non-zero scalar return $M^{\R}/\paren{MM^{\R}}$. Otherwise exit the program with + an error message. + + All division operators (\T{/}, \T{/=}) use right multiplication by the inverse. \end{quote} \T{norm(self,hint='+')} @@ -1998,8 +1950,8 @@ \section{Basic Multivector Class Functions} \T{norm2(self)} \begin{quote} - Return the square of the norm of the multivector $M$ (\T{M.norm2()}) defined by $MM^{\R}$ if $MM^{\R}$ is a scalar (a \emph{sympy} scalar - is returned). If $MM^{\R}$ is not a scalar the program exits with an error message. + Return the absolute value (using sympy \T{Abs()} function) of the scalar defined by $MM^{\R}$ if $MM^{\R}$ is a scalar. If + $MM^{\R}$ is not a scalar the program exits with an error message. \end{quote} @@ -2017,6 +1969,11 @@ \section{Basic Multivector Class Functions} $\paren{A\rfloor B}B^{-1} $ in \cite{Macdonald 1}, page 121. \end{quote} +\T{odd(self)} +\begin{quote} + Return odd part of multivector. +\end{quote} + \T{reflect\_in\_blade(self,blade)} \begin{quote} Return the reflection of the mutivector $A$ in the subspace defined by the $r$-grade blade, $B_{r}$, using the formula @@ -2105,6 +2062,11 @@ \section{Basic Multivector Functions} function\T{Mv.dual(mode)} \end{quote} +\T{even(A)} +\begin{quote} + Return even part of $A$. +\end{quote} + \T{exp(A,hint='-')} \begin{quote} If $A$ is a multivector then \T{A.exp(hint)} is returned. If $A$ is a \emph{sympy} @@ -2147,6 +2109,11 @@ \section{Basic Multivector Functions} If $A$ is a multivector and $AA^{\R}$ is a scalar return $\abs{AA^{\R}}$. \end{quote} +\T{odd(A)} +\begin{quote} + Return odd part of $A$. +\end{quote} + \T{proj(B,A)} \begin{quote} Project blade \T{A} on blade \T{B} returning $\paren{A\rfloor B}B^{-1}$. @@ -2207,10 +2174,10 @@ \section{Multivector Derivatives} F \W \bar{\nabla} &= \mbox{\lstinline!F^rgrad!} \\ \nabla \cdot F &= \mbox{\lstinline!grad|F!} \\ F \cdot \bar{\nabla} &= \mbox{\lstinline!F|rgrad!} \\ - \nabla \lfloor F &= \mbox{\lstinline!gradF!} \\ - F \rfloor \bar{\nabla} &= \mbox{\lstinline!F>rgrad!} + \nabla \rfloor F &= \mbox{\lstinline!gradF!} \\ + F \lfloor \bar{\nabla} &= \mbox{\lstinline!F>rgrad!} \end{align*} The preceding list gives examples of all possible multivector @@ -2224,10 +2191,10 @@ \section{Multivector Derivatives} \bar{\nabla} \W F &= \mbox{\lstinline!rgrad^F!} \\ F \cdot \nabla &= \mbox{\lstinline!F|grad!} \\ \bar{\nabla}\cdot F &= \mbox{\lstinline!rgrad|F!} \\ - F \lfloor \nabla &= \mbox{\lstinline!Fgrad!} \\ - \bar{\nabla} \rfloor F &= \mbox{\lstinline!rgrad>F!} + F \rfloor \nabla &= \mbox{\lstinline!Fgrad!} \\ + \bar{\nabla} \lfloor F &= \mbox{\lstinline!rgrad>F!} \end{align*} all return multivector linear differential operators. @@ -2284,7 +2251,7 @@ \section{Linear Transformations} coefficients of the linear transformation are symbolic constants) linear transformation. \emph{Note that to instantiate linear transformations coordinates, $\set{\bm{e}_{i}}$, must be defined when the geometric algebra associated with the linear transformation is instantiated. This is due to the naming conventions of the general linear transformation (coordinate names are used) and for the calculation -of the trace of the linear transformation which requires taking a divergence.}.To instantiate a specific linear transformation +of the trace of the linear transformation which requires taking a divergence.} To instantiate a specific linear transformation the usage of \T{lt()} is \T{Ga.lt(M,f=False)} \begin{quote} @@ -2295,7 +2262,7 @@ \section{Linear Transformations} string \T{M} & \parbox[t]{4in}{Coefficients are symbolic constants with names $\T{M}^{x_{i}x_{j}}$ where $x_{i}$ and $x_{j}$ are the names of the $i^{th}$ and $j^{th}$ coordinates (see output of \T{Ltrans.py}). } \\ \hline - list \T{M} & \parbox[t]{4in}{If \T{M} is a list of multivectors equal in length to the dimension of the vector space then + list \T{M} & \parbox[t]{4in}{If \T{M} is a list of vectors equal in length to the dimension of the vector space then the linear transformation is $\f{L}{\ebf_{i}} = \T{M}\mat{i}$. If \T{M} is a list of lists of scalars where all lists are equal in length to the dimension of the vector space then the linear transformation is $\f{L}{\ebf_{i}} = \T{M}\mat{i}\mat{j}\ebf_{j}$.} \\ \hline @@ -2349,7 +2316,7 @@ \section{Linear Transformations} $\f{\paren{\alpha A}}{V} = \alpha\f{A}{V}$. The \T{matrix()} member function returns a \emph{sympy} \T{Matrix} object which can be printed in IPython notebook. To directly print -an linear transformation in IPython notebook one must implement (yet to be done) a printing method similar to \T{mv.Fmt()}. +an linear transformation in \emph{ipython notebook} one must implement (yet to be done) a printing method similar to \T{mv.Fmt()}. Note that in \T{Ltrans.py} lines 30 and 49 are commented out since the latex output of those statements would run off the page. The use can uncomment those statements and run the code in the ``LaTeX docs'' directory to see the output. @@ -2487,6 +2454,8 @@ \section{Latex Printing}\label{LatexPrinting} \T{Dmode} & \T{True} & Print partial derivatives with condensed notation, $\partial_{x}f$ \\ & \T{False} & Print partial derivatives with standard \emph{sympy} latex formatting $\frac{\partial f}{\partial x}$ \\ \end{tabular} + + \T{Format()} is also required for printing from \emph{ipython notebook} (note that \T{xpdf()} is not needed to print from \emph{ipython notebook}). \end{quote} \T{Fmt(obj,fmt=1)} @@ -2619,8 +2588,8 @@ \section{Latex Printing}\label{LatexPrinting} \lstinline!A^B! & \lstinline!A\wedge B! & $A\wedge B$ \\ \lstinline!A|B! & \lstinline!A\cdot B! & $A\cdot B$ \\ \lstinline!A*B! & \lstinline!AB! & $AB$ \\ - \lstinline!AB! & \lstinline!A\rfloor B! & $A\rfloor B$ + \lstinline!AB! & \lstinline!A\lfloor B! & $A\lfloor B$ \end{tabular} \end{center} @@ -2683,9 +2652,15 @@ \subsection{Printing Lists/Tuples of Multivectors/Differential Operators} \bibitem {Doran} Chris Doran and Anthony Lasenby, ``Geometric Algebra for Physicists,'' Cambridge University Press, 2003. \url{http://www.mrao.cam.ac.uk/~clifford} \bibitem {Hestenes} David Hestenes and Garret Sobczyk, ``Clifford Algebra to Geometric Calculus,'' Kluwer Academic -Publishers, 1984. \url{http://modelingnts.la.asu.edu} +Publishers, 1984. \url{http://geocalc.clas.asu.edu/html/CA_to_GC.html} \bibitem {Macdonald 1} Alan Macdonald, ``Linear and Geometric Algebra,'' 2010. \url{http://faculty.luther.edu/~macdonal/laga} \bibitem {Macdonald 2} Alan Macdonald, ``Vector and Geometric Calculus,'' 2012. \url{http://faculty.luther.edu/~macdonal/vagc} +\bibitem {Hestenes Mech} D. Hestenes, ``\emph{New Foundations for Classical Mechanics},'' Kluwer Academic Publishers, 1999. \url{http://geocalc.clas.asu.edu/html/NFCM.html} +\bibitem {Dorst} L. Dorst, D. Fontijne, S. Mann, ``\emph{Geometric Algebra for Computer Science}: +\emph{An Object-Oriented Approach to Geometry},'' Morgan Kaufmann, $2^{\text{nd}}$ printing, 2009. +\url{http://www.geometricalgebra.net/} +\bibitem {Perwass} Christian Perwass, ``\emph{Geometric Algebra with Applications in Engineering},'' Springer, 2008 +\bibitem {Arthur} John W. Arthur, ``\emph{Understanding Geometric Algebra for Electromagnetic Theory},'' Wiley-IEEE Press, 2011. \end{thebibliography} \end{document} diff --git a/galgebra-master/examples/LaTeX/Dop.pdf b/galgebra-master/examples/LaTeX/Dop.pdf index a73d3ba2..2fb46686 100755 Binary files a/galgebra-master/examples/LaTeX/Dop.pdf and b/galgebra-master/examples/LaTeX/Dop.pdf differ diff --git a/galgebra-master/examples/LaTeX/Dop.py b/galgebra-master/examples/LaTeX/Dop.py index 5c13bbc4..ecd8addb 100755 --- a/galgebra-master/examples/LaTeX/Dop.py +++ b/galgebra-master/examples/LaTeX/Dop.py @@ -8,6 +8,7 @@ (o3d, ex, ey, ez) = Ga.build('e', g=[1, 1, 1], coords=xyz_coords, norm=True) f = o3d.mv('f', 'scalar', f=True) lap = o3d.grad*o3d.grad +print r'\nabla =', o3d.grad print r'%\nabla^{2} = \nabla . \nabla =', lap print r'%\lp\nabla^{2}\rp f =', lap*f print r'%\nabla\cdot\lp\nabla f\rp =', o3d.grad | (o3d.grad * f) diff --git a/galgebra-master/examples/LaTeX/FmtChk.pdf b/galgebra-master/examples/LaTeX/FmtChk.pdf index b66b5d9e..619a748b 100755 Binary files a/galgebra-master/examples/LaTeX/FmtChk.pdf and b/galgebra-master/examples/LaTeX/FmtChk.pdf differ diff --git a/galgebra-master/examples/LaTeX/FmtChk.py b/galgebra-master/examples/LaTeX/FmtChk.py index 704a98ef..ce5eb561 100755 --- a/galgebra-master/examples/LaTeX/FmtChk.py +++ b/galgebra-master/examples/LaTeX/FmtChk.py @@ -14,8 +14,6 @@ print Fmt(l,1) print F.Fmt(3) print B.Fmt(3) -print Fmt(l) -print Fmt(l,1) lap = o3d.grad*o3d.grad print r'%\nabla^{2} = \nabla\cdot\nabla =', lap diff --git a/galgebra-master/examples/LaTeX/diffeq_sys.pdf b/galgebra-master/examples/LaTeX/diffeq_sys.pdf index c7653014..da6cdc5c 100644 Binary files a/galgebra-master/examples/LaTeX/diffeq_sys.pdf and b/galgebra-master/examples/LaTeX/diffeq_sys.pdf differ diff --git a/galgebra-master/examples/LaTeX/em_waves_latex.pdf b/galgebra-master/examples/LaTeX/em_waves_latex.pdf index 4b934976..00ee25e6 100755 Binary files a/galgebra-master/examples/LaTeX/em_waves_latex.pdf and b/galgebra-master/examples/LaTeX/em_waves_latex.pdf differ diff --git a/galgebra-master/examples/LaTeX/em_waves_latex.py b/galgebra-master/examples/LaTeX/em_waves_latex.py index 6733e6b4..a2f48e8a 100755 --- a/galgebra-master/examples/LaTeX/em_waves_latex.py +++ b/galgebra-master/examples/LaTeX/em_waves_latex.py @@ -1,7 +1,8 @@ import sys -from sympy import symbols,sin,cos,exp,I,Matrix,solve,simplify -from printer import Format,xpdf,Get_Program,Print_Function +from sympy import symbols,sin,cos,exp,I,Matrix,simplify,Eq,S +from sympy.solvers import solve +from printer import Format,xpdf,Get_Program,Print_Function,Fmt from ga import Ga from metric import linear_expand @@ -10,7 +11,7 @@ def EM_Waves_in_Geom_Calculus(): X = (t,x,y,z) = symbols('t x y z',real=True) (st4d,g0,g1,g2,g3) = Ga.build('gamma*t|x|y|z',g=[1,-1,-1,-1],coords=X) - i = st4d.i + i = st4d.I() B = st4d.mv('B','vector') E = st4d.mv('E','vector') @@ -31,20 +32,23 @@ def EM_Waves_in_Geom_Calculus(): print r'\text{Pseudo Scalar\;\;}I =',i print r'%I_{xyz} =',Ixyz - F.Fmt(3,'\\text{Electromagnetic Field Bi-Vector\\;\\;} F') + print F.Fmt(3,'\\text{Electromagnetic Field Bi-Vector\\;\\;} F') gradF = st4d.grad*F print '#Geom Derivative of Electomagnetic Field Bi-Vector' - gradF.Fmt(3,'grad*F = 0') + print gradF.Fmt(3,'grad*F = 0') gradF = gradF / (I * exp(I*KX)) - gradF.Fmt(3,r'%\lp\bm{\nabla}F\rp /\lp i e^{iK\cdot X}\rp = 0') + print gradF.Fmt(3,r'%\lp\bm{\nabla}F\rp /\lp i e^{iK\cdot X}\rp = 0') - g = '1 # 0 0,# 1 0 0,0 0 1 0,0 0 0 -1' + g = '-1 # 0 0,# -1 0 0,0 0 -1 0,0 0 0 1' X = (xE,xB,xk,t) = symbols('x_E x_B x_k t',real=True) - (EBkst,eE,eB,ek,et) = Ga.build('e_E e_B e_k t',g=g,coords=X) - i = EBkst.i + # The correct signature sig=p for signature (p,q) is needed + # since the correct value of I**2 is needed to compute exp(I) + (EBkst,eE,eB,ek,et) = Ga.build('e_E e_B e_k t',g=g,coords=X,sig=1) + + i = EBkst.I() E,B,k,w = symbols('E B k omega',real=True) @@ -65,31 +69,30 @@ def EM_Waves_in_Geom_Calculus(): gradF_reduced = (EBkst.grad*F)/(I*exp(I*KX)) - gradF_reduced.Fmt(3,r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0') + print gradF_reduced.Fmt(3,r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0') print r'%\mbox{Previous equation requires that: }e_{E}\cdot e_{B} = 0\mbox{ if }B\ne 0\mbox{ and }k\ne 0' - gradF_reduced = gradF_reduced.subs({EBkst.g[0,1]:0}) - gradF_reduced.Fmt(3,r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0') + gradF_reduced = gradF_reduced.subs({EBkst.g[0,1]:0}).expand() + print gradF_reduced.Fmt(3,r'%\lp\bm{\nabla}F\rp/\lp ie^{iK\cdot X} \rp = 0') (coefs,bases) = linear_expand(gradF_reduced.obj) eq1 = coefs[0] eq2 = coefs[1] + print r'0 =', eq1 + print r'0 =', eq2 + B1 = solve(eq1,B)[0] B2 = solve(eq2,B)[0] - print r'\mbox{eq1: }B =',B1 - print r'\mbox{eq2: }B =',B2 - eq3 = B1-B2 print r'\mbox{eq3 = eq1-eq2: }0 =',eq3 eq3 = simplify(eq3 / E) print r'\mbox{eq3 = (eq1-eq2)/E: }0 =',eq3 print 'k =',Matrix(solve(eq3,k)) - print 'B =',Matrix([B1.subs(w,k),B1.subs(-w,k)]) return diff --git a/galgebra-master/examples/LaTeX/groups.pdf b/galgebra-master/examples/LaTeX/groups.pdf index ed79ee32..3378965a 100755 Binary files a/galgebra-master/examples/LaTeX/groups.pdf and b/galgebra-master/examples/LaTeX/groups.pdf differ diff --git a/galgebra-master/examples/LaTeX/groups.py b/galgebra-master/examples/LaTeX/groups.py index 03c85123..fac06000 100755 --- a/galgebra-master/examples/LaTeX/groups.py +++ b/galgebra-master/examples/LaTeX/groups.py @@ -71,7 +71,7 @@ def main(): Get_Program() Format() Product_of_Rotors() - xpdf(paper=(8.5,11),debug=True) + xpdf(paper=(8.5,11)) return if __name__ == "__main__": diff --git a/galgebra-master/examples/LaTeX/latex_check.pdf b/galgebra-master/examples/LaTeX/latex_check.pdf index a75080e1..01d56766 100755 Binary files a/galgebra-master/examples/LaTeX/latex_check.pdf and b/galgebra-master/examples/LaTeX/latex_check.pdf differ diff --git a/galgebra-master/examples/LaTeX/latex_check.py b/galgebra-master/examples/LaTeX/latex_check.py index 0bd98525..49a7619e 100755 --- a/galgebra-master/examples/LaTeX/latex_check.py +++ b/galgebra-master/examples/LaTeX/latex_check.py @@ -1,7 +1,7 @@ from sympy import Symbol, symbols, sin, cos, Rational, expand, simplify, collect from printer import Format, Eprint, Get_Program, Print_Function, xpdf, Fmt from ga import Ga, one, zero -from mv import Nga, com +from mv import Nga, com, cross HALF = Rational(1,2) @@ -30,24 +30,25 @@ def basic_multivector_operations_3D(): A = g3d.mv('A','mv') - A.Fmt(1,'A') - A.Fmt(2,'A') - A.Fmt(3,'A') + print A.Fmt(1,'A') + print A.Fmt(2,'A') + print A.Fmt(3,'A') - A.even().Fmt(1,'%A_{+}') - A.odd().Fmt(1,'%A_{-}') + print A.even().Fmt(1,'%A_{+}') + print A.odd().Fmt(1,'%A_{-}') X = g3d.mv('X','vector') Y = g3d.mv('Y','vector') print 'g_{ij} = ',g3d.g - X.Fmt(1,'X') - Y.Fmt(1,'Y') + print X.Fmt(1,'X') + print Y.Fmt(1,'Y') - (X*Y).Fmt(2,'X*Y') - (X^Y).Fmt(2,'X^Y') - (X|Y).Fmt(2,'X|Y') + print (X*Y).Fmt(2,'X*Y') + print (X^Y).Fmt(2,'X^Y') + print (X|Y).Fmt(2,'X|Y') + print cross(X,Y).Fmt(1,r'X\times Y') return def basic_multivector_operations_2D(): @@ -172,6 +173,7 @@ def rounding_numerical_components(): def noneuclidian_distance_calculation(): Print_Function() from sympy import solve,sqrt + Fmt(1) g = '0 # #,# 0 #,# # 1' nel = Ga('X Y e',g=g) @@ -278,6 +280,7 @@ def noneuclidian_distance_calculation(): def conformal_representations_of_circles_lines_spheres_and_planes(): Print_Function() global n,nbar + Fmt(1) g = '1 0 0 0 0,0 1 0 0 0,0 0 1 0 0,0 0 0 0 2,0 0 0 2 0' c3d = Ga('e_1 e_2 e_3 n \\bar{n}',g=g) @@ -319,6 +322,7 @@ def conformal_representations_of_circles_lines_spheres_and_planes(): def properties_of_geometric_objects(): Print_Function() global n, nbar + Fmt(1) g = '# # # 0 0,'+ \ '# # # 0 0,'+ \ '# # # 0 0,'+ \ @@ -350,6 +354,7 @@ def properties_of_geometric_objects(): def extracting_vectors_from_conformal_2_blade(): Print_Function() + Fmt(1) print r'B = P1\W P2' g = '0 -1 #,'+ \ @@ -382,6 +387,7 @@ def extracting_vectors_from_conformal_2_blade(): def reciprocal_frame_test(): Print_Function() + Fmt(1) g = '1 # #,'+ \ '# 1 #,'+ \ '# # 1' diff --git a/galgebra-master/examples/LaTeX/lin_tran_check.pdf b/galgebra-master/examples/LaTeX/lin_tran_check.pdf index 6b143748..3e02aca9 100644 Binary files a/galgebra-master/examples/LaTeX/lin_tran_check.pdf and b/galgebra-master/examples/LaTeX/lin_tran_check.pdf differ diff --git a/galgebra-master/examples/LaTeX/manifold.pdf b/galgebra-master/examples/LaTeX/manifold.pdf index e9bde76f..6d2afff7 100644 Binary files a/galgebra-master/examples/LaTeX/manifold.pdf and b/galgebra-master/examples/LaTeX/manifold.pdf differ diff --git a/galgebra-master/examples/LaTeX/manifold.py b/galgebra-master/examples/LaTeX/manifold.py index 284cbd68..2b55d074 100755 --- a/galgebra-master/examples/LaTeX/manifold.py +++ b/galgebra-master/examples/LaTeX/manifold.py @@ -57,31 +57,6 @@ a1 = sph2d.mv('a_1','vector') a2 = sph2d.mv('a_2','vector') -""" -V = Mlt('V',sph2d,(a1,),fct=True) -T = Mlt('T',sph2d,(a1,a2),fct=True) - -print '#Tensors on the Unit Sphere' - -print 'V =', V -#print 'T =', T -T.Fmt(5,'T') -print '#Tensor Contraction' -print r'T[1,2] =', T.contract(1,2) -print '#Tensor Evaluation' -print r'T(a,b) =', T(a,b) -print r'T(a,b+c) =', T(a,b+c).expand() -print r'T(a,\alpha b) =', T(a,alpha*b) -print '#Geometric Derivative With Respect To Slot' -print r'\nabla_{a_{1}}T =',T.pdiff(1) -print r'\nabla_{a_{2}}T =',T.pdiff(2) -print '#Covariant Derivatives' -print r'\mathcal{D}V =', V.cderiv() -DT = T.cderiv() -#print r'\mathcal{D}T =', DT -DT.Fmt(3,r'\mathcal{D}T') -print r'\mathcal{D}T[1,3](a) =', (DT.contract(1,3))(a) -""" #Define curve on unit sphere manifold us = Function('u__s')(s) diff --git a/galgebra-master/examples/LaTeX/matrix_latex.pdf b/galgebra-master/examples/LaTeX/matrix_latex.pdf index 60d91720..b4571566 100644 Binary files a/galgebra-master/examples/LaTeX/matrix_latex.pdf and b/galgebra-master/examples/LaTeX/matrix_latex.pdf differ diff --git a/galgebra-master/examples/LaTeX/new_bug_grad_exp.pdf b/galgebra-master/examples/LaTeX/new_bug_grad_exp.pdf index 191a735b..998ed5b5 100644 Binary files a/galgebra-master/examples/LaTeX/new_bug_grad_exp.pdf and b/galgebra-master/examples/LaTeX/new_bug_grad_exp.pdf differ diff --git a/galgebra-master/examples/LaTeX/physics_check_latex.pdf b/galgebra-master/examples/LaTeX/physics_check_latex.pdf index 4efcdcd2..5f3cb6e1 100755 Binary files a/galgebra-master/examples/LaTeX/physics_check_latex.pdf and b/galgebra-master/examples/LaTeX/physics_check_latex.pdf differ diff --git a/galgebra-master/examples/LaTeX/print_check_latex.pdf b/galgebra-master/examples/LaTeX/print_check_latex.pdf index 11cd190c..b10a4c22 100644 Binary files a/galgebra-master/examples/LaTeX/print_check_latex.pdf and b/galgebra-master/examples/LaTeX/print_check_latex.pdf differ diff --git a/galgebra-master/examples/LaTeX/products_latex.py b/galgebra-master/examples/LaTeX/products_latex.py index f48fc227..32ad367d 100755 --- a/galgebra-master/examples/LaTeX/products_latex.py +++ b/galgebra-master/examples/LaTeX/products_latex.py @@ -3,7 +3,7 @@ from printer import Format,xpdf def main(): - #Format() + Format() coords = (x,y,z) = symbols('x y z',real=True) @@ -27,12 +27,12 @@ def main(): for xi in X: print '' for yi in X: - print xi[1]+'*'+yi[1]+' =',xi[0]*yi[0] - print xi[1]+'^'+yi[1]+' =',xi[0]^yi[0] + print xi[1]+' * '+yi[1]+' =',xi[0]*yi[0] + print xi[1]+' ^ '+yi[1]+' =',xi[0]^yi[0] if xi[1] != 's' and yi[1] != 's': - print xi[1]+'|'+yi[1]+' =',xi[0]|yi[0] - print xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0] + print xi[1]+' | '+yi[1]+' =',xi[0]|yi[0] + print xi[1]+' < '+yi[1]+' =',xi[0] '+yi[1]+' =',xi[0]>yi[0] fs = o3d.mv('s','scalar',f=True) fv = o3d.mv('v','vector',f=True) @@ -54,12 +54,12 @@ def main(): if xi[1] == 'grad' and yi[1] == 'grad': pass else: - print xi[1]+'*'+yi[1]+' =',xi[0]*yi[0] - print xi[1]+'^'+yi[1]+' =',xi[0]^yi[0] + print xi[1]+' * '+yi[1]+' =',xi[0]*yi[0] + print xi[1]+' ^ '+yi[1]+' =',xi[0]^yi[0] if xi[1] != 's' and yi[1] != 's': - print xi[1]+'|'+yi[1]+' =',xi[0]|yi[0] - print xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0] + print xi[1]+' | '+yi[1]+' =',xi[0]|yi[0] + print xi[1]+' < '+yi[1]+' =' ,xi[0] '+yi[1]+' =' ,xi[0]>yi[0] (g2d,ex,ey) = Ga.build('e',coords=(x,y)) @@ -85,14 +85,16 @@ def main(): if xi[1] == 'grad' and yi[1] == 'grad': pass else: - print xi[1]+'*'+yi[1]+' =',xi[0]*yi[0] - print xi[1]+'^'+yi[1]+' =',xi[0]^yi[0] + print xi[1]+' * '+yi[1]+' =',xi[0]*yi[0] + print xi[1]+' ^ '+yi[1]+' =',xi[0]^yi[0] if xi[1] != 's' and yi[1] != 's': - print xi[1]+'|'+yi[1]+' =',xi[0]|yi[0] - print xi[1]+'<'+yi[1]+' =',xi[0]'+yi[1]+' =',xi[0]>yi[0] + print xi[1]+' | '+yi[1]+' =',xi[0]|yi[0] + else: + print xi[1]+' | '+yi[1]+' = Not Allowed' + print xi[1]+' < '+yi[1]+' =',xi[0] '+yi[1]+' =' ,xi[0]>yi[0] - #xpdf(paper='letter') + xpdf(paper='letter') return if __name__ == "__main__": diff --git a/galgebra-master/examples/LaTeX/reflect_test.pdf b/galgebra-master/examples/LaTeX/reflect_test.pdf index 9fc3bfb6..7edec2ca 100644 Binary files a/galgebra-master/examples/LaTeX/reflect_test.pdf and b/galgebra-master/examples/LaTeX/reflect_test.pdf differ diff --git a/galgebra-master/examples/LaTeX/simple_test_latex.pdf b/galgebra-master/examples/LaTeX/simple_test_latex.pdf index 2883a163..4397bb4b 100644 Binary files a/galgebra-master/examples/LaTeX/simple_test_latex.pdf and b/galgebra-master/examples/LaTeX/simple_test_latex.pdf differ diff --git a/galgebra-master/examples/Terminal/terminal_check.py b/galgebra-master/examples/Terminal/terminal_check.py index 92a05a93..5d8c3d5f 100755 --- a/galgebra-master/examples/Terminal/terminal_check.py +++ b/galgebra-master/examples/Terminal/terminal_check.py @@ -13,21 +13,21 @@ def basic_multivector_operations(): A = g3d.mv('A', 'mv') - A.Fmt(1, 'A') - A.Fmt(2, 'A') - A.Fmt(3, 'A') + print A.Fmt(1, 'A') + print A.Fmt(2, 'A') + print A.Fmt(3, 'A') X = g3d.mv('X', 'vector') Y = g3d.mv('Y', 'vector') print 'g_{ij} =\n', g3d.g - X.Fmt(1, 'X') - Y.Fmt(1, 'Y') + print X.Fmt(1, 'X') + print Y.Fmt(1, 'Y') - (X * Y).Fmt(2, 'X*Y') - (X ^ Y).Fmt(2, 'X^Y') - (X | Y).Fmt(2, 'X|Y') + print (X * Y).Fmt(2, 'X*Y') + print (X ^ Y).Fmt(2, 'X^Y') + print (X | Y).Fmt(2, 'X|Y') g2d = Ga('e*x|y') @@ -38,12 +38,12 @@ def basic_multivector_operations(): X = g2d.mv('X', 'vector') A = g2d.mv('A', 'spinor') - X.Fmt(1, 'X') - A.Fmt(1, 'A') + print X.Fmt(1, 'X') + print A.Fmt(1, 'A') - (X | A).Fmt(2, 'X|A') - (X < A).Fmt(2, 'X X).Fmt(2, 'A>X') + print (X | A).Fmt(2, 'X|A') + print (X < A).Fmt(2, 'X X).Fmt(2, 'A>X') o2d = Ga('e*x|y', g=[1, 1]) @@ -54,18 +54,18 @@ def basic_multivector_operations(): X = o2d.mv('X', 'vector') A = o2d.mv('A', 'spinor') - X.Fmt(1, 'X') - A.Fmt(1, 'A') + print X.Fmt(1, 'X') + print A.Fmt(1, 'A') - (X * A).Fmt(2, 'X*A') - (X | A).Fmt(2, 'X|A') - (X < A).Fmt(2, 'X A).Fmt(2, 'X>A') + print (X * A).Fmt(2, 'X*A') + print (X | A).Fmt(2, 'X|A') + print (X < A).Fmt(2, 'X A).Fmt(2, 'X>A') - (A * X).Fmt(2, 'A*X') - (A | X).Fmt(2, 'A|X') - (A < X).Fmt(2, 'A X).Fmt(2, 'A>X') + print (A * X).Fmt(2, 'A*X') + print (A | X).Fmt(2, 'A|X') + print (A < X).Fmt(2, 'A X).Fmt(2, 'A>X') return @@ -206,7 +206,7 @@ def noneuclidian_distance_calculation(): Z = R*X*R.rev() # D&L 10.155 Z.obj = expand(Z.obj) Z.obj = Z.obj.collect([Binv,s,c,XdotY]) - Z.Fmt(3,'R*X*R.rev()') + print Z.Fmt(3,'R*X*R.rev()') W = Z|Y # Extract scalar part of multivector # From this point forward all calculations are with sympy scalars print 'Objective is to determine value of C = cosh(alpha) such that W = 0' @@ -334,7 +334,7 @@ def conformal_representations_of_circles_lines_spheres_and_planes(): L = (A^B^e)^X - L.Fmt(3,'Hyperbolic Circle: (A^B^e)^X = 0 =') + print L.Fmt(3,'Hyperbolic Circle: (A^B^e)^X = 0 =') return @@ -512,8 +512,9 @@ def main(): Get_Program(True) #ga_print_on() Eprint() - """ + basic_multivector_operations() + """ check_generalized_BAC_CAB_formulas() derivatives_in_rectangular_coordinates() derivatives_in_spherical_coordinates() @@ -523,8 +524,8 @@ def main(): properties_of_geometric_objects() extracting_vectors_from_conformal_2_blade() reciprocal_frame_test() - """ signature_test() + """ #ga_print_off() return diff --git a/galgebra-master/examples/ipython/.ipynb_checkpoints/dop-checkpoint.ipynb b/galgebra-master/examples/ipython/.ipynb_checkpoints/dop-checkpoint.ipynb index 847dbbc7..b6e3f35e 100755 --- a/galgebra-master/examples/ipython/.ipynb_checkpoints/dop-checkpoint.ipynb +++ b/galgebra-master/examples/ipython/.ipynb_checkpoints/dop-checkpoint.ipynb @@ -1,422 +1,444 @@ { - "metadata": { - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from sympy import *\n", - "from ga import Ga\n", - "from printer import Format, Fmt\n", - "Format()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "xyz_coords = (x, y, z) = symbols('x y z', real=True)\n", - "(o3d, ex, ey, ez) = Ga.build('e', g=[1, 1, 1], coords=xyz_coords, norm=True)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = o3d.mv('f', 'scalar', f=True)\n", - "F = o3d.mv('F', 'vector', f=True)\n", - "lap = o3d.grad*o3d.grad" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 5 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "lap.Fmt(1,r'\\nabla^{2}')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2} = \\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "text": [ - "\\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}}" - ] - } - ], - "prompt_number": 6 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "(lap*f).Fmt(1,r'\\nabla^{2}f')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2}f = \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 7, - "text": [ - "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " - ] - } - ], - "prompt_number": 7 - }, + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from sympy import symbols, sin, cos\n", + "from ga import Ga\n", + "from printer import Format, Fmt\n", + "from IPython.display import Latex\n", + "Format()" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad | (o3d.grad * f)" - ], - "language": "python", + "data": { + "text/plain": [ + "'\\\\left[\\\\begin{matrix}1 & 0 & 0\\\\\\\\0 & 1 & 0\\\\\\\\0 & 0 & 1\\\\end{matrix}\\\\right]'" + ] + }, + "execution_count": 19, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " - ] - } - ], - "prompt_number": 8 - }, + "output_type": "execute_result" + } + ], + "source": [ + "xyz_coords = (x, y, z) = symbols('x y z', real=True)\n", + "(o3d, ex, ey, ez) = Ga.build('e', g=[1, 1, 1], coords=xyz_coords, norm=True)\n", + "str(o3d.g)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad|F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} f = f \\end{equation*}" + ], + "text/plain": [ + "f " + ] + }, + "execution_count": 3, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 9, - "text": [ - "\\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} " - ] - } - ], - "prompt_number": 9 - }, + "output_type": "execute_result" + } + ], + "source": [ + "f = o3d.mv('f', 'scalar', f=True)\n", + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "F = o3d.mv('F', 'vector', f=True)\n", + "lap = o3d.grad*o3d.grad" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad * F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} F = F^{x} \\boldsymbol{e}_{x} + F^{y} \\boldsymbol{e}_{y} + F^{z} \\boldsymbol{e}_{z} \\end{equation*}" + ], + "text/plain": [ + "F^{x} \\boldsymbol{e}_{x} + F^{y} \\boldsymbol{e}_{y} + F^{z} \\boldsymbol{e}_{z}" + ] + }, + "execution_count": 5, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "text": [ - "\\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z}" - ] - } - ], - "prompt_number": 10 - }, + "output_type": "execute_result" + } + ], + "source": [ + "F" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sph_coords = (r, th, phi) = symbols('r theta phi', real=True)\n", - "(sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2], coords=sph_coords, norm=True)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}} \\end{equation*}" + ], + "text/plain": [ + "\\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}}" + ] + }, + "execution_count": 6, "metadata": {}, - "outputs": [], - "prompt_number": 11 - }, + "output_type": "execute_result" + } + ], + "source": [ + "lap" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = sp3d.mv('f', 'scalar', f=True)\n", - "F = sp3d.mv('F', 'vector', f=True)\n", - "B = sp3d.mv('B', 'bivector', f=True)\n", - "lap = sp3d.grad*sp3d.grad\n", - "lap.Fmt(1,r'\\nabla^{2}')" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" + ], + "text/plain": [ + "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " + ] + }, + "execution_count": 7, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2} = \\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "text": [ - "\\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}}" - ] - } - ], - "prompt_number": 12 - }, + "output_type": "execute_result" + } + ], + "source": [ + "(lap*f)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "lap*f" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" + ], + "text/plain": [ + "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " + ] + }, + "execution_count": 8, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "text": [ - "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 13 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad | (o3d.grad * f)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad | (sp3d.grad * f)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\end{equation*}" + ], + "text/plain": [ + "\\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} " + ] + }, + "execution_count": 9, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 14 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad|F" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad | F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z} \\end{equation*}" + ], + "text/plain": [ + "\\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z}" + ] + }, + "execution_count": 10, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "text": [ - "\\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 15 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad * F" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "sph_coords = (r, th, phi) = symbols('r theta phi', real=True)\n", + "(sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2], coords=sph_coords, norm=True)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad ^ F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}} \\end{equation*}" + ], + "text/plain": [ + "\\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}}" + ] + }, + "execution_count": 12, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi } \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "text": [ - "\\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi }" - ] - } - ], - "prompt_number": 16 - }, + "output_type": "execute_result" + } + ], + "source": [ + "f = sp3d.mv('f', 'scalar', f=True)\n", + "F = sp3d.mv('F', 'vector', f=True)\n", + "B = sp3d.mv('B', 'bivector', f=True)\n", + "sp3d.grad.Fmt(1,r'\\nabla')\n", + "lap = sp3d.grad*sp3d.grad\n", + "lap" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "(sp3d.grad | B).Fmt(3)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 13, "metadata": {}, - "outputs": [ - { - "latex": [ - " \\begin{align*} & - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{align*} \n" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 17, - "text": [ - " \\begin{align*} & - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{align*} \n" - ] - } - ], - "prompt_number": 17 - }, + "output_type": "execute_result" + } + ], + "source": [ + "lap*f" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "F.Fmt(1)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 14, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} F = F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi } \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "text": [ - "F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }" - ] - } - ], - "prompt_number": 18 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad | (sp3d.grad * f)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt((F,F))" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 15, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left ( F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }, \\right. \\\\ \\left. F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }\\right ) \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 19, - "text": [ - "" - ] - } - ], - "prompt_number": 19 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad | F" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt([F,F])" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 16, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left [ F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }, \\right. \\\\ \\left. F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }\\right ] \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 24, - "text": [ - "" - ] - } - ], - "prompt_number": 24 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad ^ F" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt((o3d.grad,o3d.rgrad))" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "- \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 17, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left ( \\boldsymbol{e}_{x} \\frac{\\partial}{\\partial x} + \\boldsymbol{e}_{y} \\frac{\\partial}{\\partial y} + \\boldsymbol{e}_{z} \\frac{\\partial}{\\partial z}, \\right. \\\\ \\left. \\frac{\\partial}{\\partial x} \\boldsymbol{e}_{x} + \\frac{\\partial}{\\partial y} \\boldsymbol{e}_{y} + \\frac{\\partial}{\\partial z} \\boldsymbol{e}_{z}\\right ) \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 25, - "text": [ - "" - ] - } - ], - "prompt_number": 25 - }, + "output_type": "execute_result" + } + ], + "source": [ + "(sp3d.grad | B)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} F = F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 18, "metadata": {}, - "outputs": [] + "output_type": "execute_result" } ], - "metadata": {} + "source": [ + "F" + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/galgebra-master/examples/ipython/dop.ipynb b/galgebra-master/examples/ipython/dop.ipynb index d3be2447..55e8fdb9 100755 --- a/galgebra-master/examples/ipython/dop.ipynb +++ b/galgebra-master/examples/ipython/dop.ipynb @@ -1,443 +1,462 @@ { - "metadata": { - "name": "" - }, - "nbformat": 3, - "nbformat_minor": 0, - "worksheets": [ + "cells": [ { - "cells": [ - { - "cell_type": "code", - "collapsed": false, - "input": [ - "from sympy import *\n", - "from ga import Ga\n", - "from printer import Format, Fmt\n", - "Format()" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 1 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "xyz_coords = (x, y, z) = symbols('x y z', real=True)\n", - "(o3d, ex, ey, ez) = Ga.build('e', g=[1, 1, 1], coords=xyz_coords, norm=True)" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 2 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = o3d.mv('f', 'scalar', f=True)\n", - "F = o3d.mv('F', 'vector', f=True)\n", - "lap = o3d.grad*o3d.grad" - ], - "language": "python", - "metadata": {}, - "outputs": [], - "prompt_number": 3 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "lap.Fmt(1,r'\\nabla^{2}')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2} = \\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 4, - "text": [ - "\\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}}" - ] - } - ], - "prompt_number": 4 - }, - { - "cell_type": "code", - "collapsed": false, - "input": [ - "(lap*f).Fmt(1,r'\\nabla^{2}f')" - ], - "language": "python", - "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2}f = \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 5, - "text": [ - "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " - ] - } - ], - "prompt_number": 5 - }, + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "from sympy import symbols, sin, cos\n", + "from ga import Ga\n", + "from printer import Format, Fmt\n", + "from IPython.display import Latex\n", + "Format()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad | (o3d.grad * f)" - ], - "language": "python", + "data": { + "text/plain": [ + "Matrix([\n", + "[1, 0, 0],\n", + "[0, 1, 0],\n", + "[0, 0, 1]])" + ] + }, + "execution_count": 2, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 6, - "text": [ - "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " - ] - } - ], - "prompt_number": 6 - }, + "output_type": "execute_result" + } + ], + "source": [ + "xyz_coords = (x, y, z) = symbols('x y z', real=True)\n", + "(o3d, ex, ey, ez) = Ga.build('e', g=[1, 1, 1], coords=xyz_coords, norm=True)\n", + "o3d.g" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad|F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} f = f \\end{equation*}" + ], + "text/plain": [ + "f " + ] + }, + "execution_count": 3, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 7, - "text": [ - "\\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} " - ] - } - ], - "prompt_number": 7 - }, + "output_type": "execute_result" + } + ], + "source": [ + "f = o3d.mv('f', 'scalar', f=True)\n", + "f" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "F = o3d.mv('F', 'vector', f=True)\n", + "lap = o3d.grad*o3d.grad" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "o3d.grad * F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} F = F^{x} \\boldsymbol{e}_{x} + F^{y} \\boldsymbol{e}_{y} + F^{z} \\boldsymbol{e}_{z} \\end{equation*}" + ], + "text/plain": [ + "F^{x} \\boldsymbol{e}_{x} + F^{y} \\boldsymbol{e}_{y} + F^{z} \\boldsymbol{e}_{z}" + ] + }, + "execution_count": 5, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 8, - "text": [ - "\\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z}" - ] - } - ], - "prompt_number": 8 - }, + "output_type": "execute_result" + } + ], + "source": [ + "F" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sph_coords = (r, th, phi) = symbols('r theta phi', real=True)\n", - "(sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2], coords=sph_coords, norm=True)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}} \\end{equation*}" + ], + "text/plain": [ + "\\frac{\\partial^{2}}{\\partial x^{2}} + \\frac{\\partial^{2}}{\\partial y^{2}} + \\frac{\\partial^{2}}{\\partial z^{2}}" + ] + }, + "execution_count": 6, "metadata": {}, - "outputs": [], - "prompt_number": 9 - }, + "output_type": "execute_result" + } + ], + "source": [ + "lap" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "f = sp3d.mv('f', 'scalar', f=True)\n", - "F = sp3d.mv('F', 'vector', f=True)\n", - "B = sp3d.mv('B', 'bivector', f=True)\n", - "lap = sp3d.grad*sp3d.grad\n", - "lap.Fmt(1,r'\\nabla^{2}')" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" + ], + "text/plain": [ + "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " + ] + }, + "execution_count": 7, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\nabla^{2} = \\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}} \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 10, - "text": [ - "\\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}}" - ] - } - ], - "prompt_number": 10 - }, + "output_type": "execute_result" + } + ], + "source": [ + "(lap*f)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "lap*f" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f \\end{equation*}" + ], + "text/plain": [ + "\\partial^{2}_{x} f + \\partial^{2}_{y} f + \\partial^{2}_{z} f " + ] + }, + "execution_count": 8, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 11, - "text": [ - "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 11 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad | (o3d.grad * f)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad | (sp3d.grad * f)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\end{equation*}" + ], + "text/plain": [ + "\\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} " + ] + }, + "execution_count": 9, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 12, - "text": [ - "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 12 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad|F" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad | F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z} \\end{equation*}" + ], + "text/plain": [ + "\\left ( \\partial_{x} F^{x} + \\partial_{y} F^{y} + \\partial_{z} F^{z} \\right ) + \\left ( - \\partial_{y} F^{x} + \\partial_{x} F^{y} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{y} + \\left ( - \\partial_{z} F^{x} + \\partial_{x} F^{z} \\right ) \\boldsymbol{e}_{x}\\wedge \\boldsymbol{e}_{z} + \\left ( - \\partial_{z} F^{y} + \\partial_{y} F^{z} \\right ) \\boldsymbol{e}_{y}\\wedge \\boldsymbol{e}_{z}" + ] + }, + "execution_count": 10, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 13, - "text": [ - "\\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right)" - ] - } - ], - "prompt_number": 13 - }, + "output_type": "execute_result" + } + ], + "source": [ + "o3d.grad * F" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "sp3d.grad ^ F" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\boldsymbol{e}_{r} \\frac{\\partial}{\\partial r} + \\boldsymbol{e}_{\\theta } \\frac{1}{r} \\frac{\\partial}{\\partial \\theta } + \\boldsymbol{e}_{\\phi } \\frac{1}{r \\sin{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\phi } \\end{equation*}" + ], + "text/plain": [ + "\\boldsymbol{e}_{r} \\frac{\\partial}{\\partial r} + \\boldsymbol{e}_{\\theta } \\frac{1}{r} \\frac{\\partial}{\\partial \\theta } + \\boldsymbol{e}_{\\phi } \\frac{1}{r \\sin{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\phi }" + ] + }, + "execution_count": 11, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi } \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 14, - "text": [ - "\\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi }" - ] - } - ], - "prompt_number": 14 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sph_coords = (r, th, phi) = symbols('r theta phi', real=True)\n", + "(sp3d, er, eth, ephi) = Ga.build('e', g=[1, r**2, r**2 * sin(th)**2], coords=sph_coords, norm=True)\n", + "sp3d.grad" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "(sp3d.grad | B).Fmt(3)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}} \\end{equation*}" + ], + "text/plain": [ + "\\frac{2}{r} \\frac{\\partial}{\\partial r} + \\frac{1}{r^{2} \\tan{\\left (\\theta \\right )}} \\frac{\\partial}{\\partial \\theta } + \\frac{\\partial^{2}}{\\partial r^{2}} + r^{-2} \\frac{\\partial^{2}}{\\partial \\theta ^{2}} + \\frac{1}{r^{2} \\sin^{2}{\\left (\\theta \\right )}} \\frac{\\partial^{2}}{\\partial \\phi ^{2}}" + ] + }, + "execution_count": 12, "metadata": {}, - "outputs": [ - { - "latex": [ - " \\begin{align*} & - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{align*} \n" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 15, - "text": [ - " \\begin{align*} & - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } \\\\ & + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{align*} \n" - ] - } - ], - "prompt_number": 15 - }, + "output_type": "execute_result" + } + ], + "source": [ + "f = sp3d.mv('f', 'scalar', f=True)\n", + "F = sp3d.mv('F', 'vector', f=True)\n", + "B = sp3d.mv('B', 'bivector', f=True)\n", + "sp3d.grad.Fmt(1,r'\\nabla')\n", + "lap = sp3d.grad*sp3d.grad\n", + "lap" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "F.Fmt(1)" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 13, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} F = F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi } \\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 16, - "text": [ - "F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }" - ] - } - ], - "prompt_number": 16 - }, + "output_type": "execute_result" + } + ], + "source": [ + "lap*f" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt((F,F))" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r^{2}} \\left(r^{2} \\partial^{2}_{r} f + 2 r \\partial_{r} f + \\partial^{2}_{\\theta } f + \\frac{\\partial_{\\theta } f }{\\tan{\\left (\\theta \\right )}} + \\frac{\\partial^{2}_{\\phi } f }{\\sin^{2}{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 14, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left ( F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }, \\right. \\\\ \\left. F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }\\right ) \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 17, - "text": [ - "" - ] - } - ], - "prompt_number": 17 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad | (sp3d.grad * f)" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt([F,F])" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r} \\left(r \\partial_{r} F^{r} + 2 F^{r} + \\frac{F^{\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\theta } + \\frac{\\partial_{\\phi } F^{\\phi } }{\\sin{\\left (\\theta \\right )}}\\right)" + ] + }, + "execution_count": 15, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left [ F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }, \\right. \\\\ \\left. F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }\\right ] \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 18, - "text": [ - "" - ] - } - ], - "prompt_number": 18 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad | F" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "Fmt((o3d.grad,o3d.rgrad))" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} \\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "\\frac{1}{r} \\left(r \\partial_{r} F^{\\theta } + F^{\\theta } - \\partial_{\\theta } F^{r} \\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} F^{\\phi } + F^{\\phi } - \\frac{\\partial_{\\phi } F^{r} }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r}\\wedge \\boldsymbol{e}_{\\phi } + \\frac{1}{r} \\left(\\frac{F^{\\phi } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } F^{\\phi } - \\frac{\\partial_{\\phi } F^{\\theta } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta }\\wedge \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 16, "metadata": {}, - "outputs": [ - { - "latex": [ - "\\begin{equation*} \\begin{array}{c} \\left ( \\boldsymbol{e}_{x} \\frac{\\partial}{\\partial x} + \\boldsymbol{e}_{y} \\frac{\\partial}{\\partial y} + \\boldsymbol{e}_{z} \\frac{\\partial}{\\partial z}, \\right. \\\\ \\left. \\frac{\\partial}{\\partial x} \\boldsymbol{e}_{x} + \\frac{\\partial}{\\partial y} \\boldsymbol{e}_{y} + \\frac{\\partial}{\\partial z} \\boldsymbol{e}_{z}\\right ) \\\\ \\end{array}\\end{equation*}" - ], - "metadata": {}, - "output_type": "pyout", - "prompt_number": 19, - "text": [ - "" - ] - } - ], - "prompt_number": 19 - }, + "output_type": "execute_result" + } + ], + "source": [ + "sp3d.grad ^ F" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [ - "r'$\\alpha$'" - ], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} - \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "- \\frac{1}{r} \\left(\\frac{B^{r\\theta } }{\\tan{\\left (\\theta \\right )}} + \\partial_{\\theta } B^{r\\theta } + \\frac{\\partial_{\\phi } B^{r\\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{r} + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\theta } + B^{r\\theta } - \\frac{\\partial_{\\phi } B^{\\phi \\phi } }{\\sin{\\left (\\theta \\right )}}\\right) \\boldsymbol{e}_{\\theta } + \\frac{1}{r} \\left(r \\partial_{r} B^{r\\phi } + B^{r\\phi } + \\partial_{\\theta } B^{\\phi \\phi } \\right) \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 17, "metadata": {}, - "outputs": [ - { - "metadata": {}, - "output_type": "pyout", - "prompt_number": 20, - "text": [ - "'$\\\\alpha$'" - ] - } - ], - "prompt_number": 20 - }, + "output_type": "execute_result" + } + ], + "source": [ + "(sp3d.grad | B)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ { - "cell_type": "code", - "collapsed": false, - "input": [], - "language": "python", + "data": { + "text/latex": [ + "\\begin{equation*} F = F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi } \\end{equation*}" + ], + "text/plain": [ + "F^{r} \\boldsymbol{e}_{r} + F^{\\theta } \\boldsymbol{e}_{\\theta } + F^{\\phi } \\boldsymbol{e}_{\\phi }" + ] + }, + "execution_count": 18, "metadata": {}, - "outputs": [], - "prompt_number": 20 + "output_type": "execute_result" } ], - "metadata": {} + "source": [ + "F" + ] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": "Python 2", + "language": "python", + "name": "python2" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/galgebra-master/galgebra/ga.py b/galgebra-master/galgebra/ga.py index 4f88cc98..118dec16 100755 --- a/galgebra-master/galgebra/ga.py +++ b/galgebra-master/galgebra/ga.py @@ -344,10 +344,12 @@ def __init__(self, bases, **kwargs): self.e_sq = simplify(expand((self.e*self.e).scalar())) # Calculate normalized pseudo scalar (I**2 = +/-1) - if self.e_sq_sgn == '+': + if self.e_sq_sgn == '+': # I**2 = 1 self.i = self.e/sqrt(self.e_sq) - else: + self.i_inv = self.i + else: # I**2 = -1 self.i = self.e/sqrt(-self.e_sq) + self.i_inv = -self.i if Ga.restore: # restore printer to appropriate enhanced mode after ga is instantiated printer.GaLatexPrinter.redirect() @@ -899,7 +901,6 @@ def dot_product_basis_blades(self, blade12): if grade < 0: return 0 elif self.dot_mode == '>': - #print 'g,g1,g2 =', grade, grade1, grade2 grade = grade1 - grade2 if grade < 0: return 0 @@ -1114,6 +1115,14 @@ def wedge(self, A, B): return update_and_substitute(A, B, self.wedge_product_basis_blades, self.wedge_table_dict) def dot(self, A, B): # inner products |, <, and > + """ + Let A = a + A' and B = b + B' where a and b are the scalar parts of + A and B and A' and B' are the remaining parts of A and B. Then + we have: + (a+A')<(b+B') = a(b+B') + A'(b+B') = b(a+A') + A'>B' + We use these relations to reduce AB. + """ if A == 0 or B == 0: return 0 if self.is_ortho: @@ -1125,13 +1134,24 @@ def dot(self, A, B): # inner products |, <, and > A = self.remove_scalar_part(A) B = self.remove_scalar_part(B) return update_and_substitute(A, B, dot_product_basis_blades, self.dot_table_dict) - else: + elif self.dot_mode == '<' or self.dot_mode == '>': + (a, Ap) = self.split_multivector(A) # Ap = A' + (b, Bp) = self.split_multivector(B) # Bp = B' if self.dot_mode == '<': # Left contraction - return update_and_substitute(A, B, dot_product_basis_blades, self.left_contract_table_dict) + if Ap != 0 and Bp != 0: # Neither nc part of A or B is zero + prod = update_and_substitute(Ap, Bp, dot_product_basis_blades, self.left_contract_table_dict) + return prod + a * B + else: # Ap or Bp is zero + return a * B elif self.dot_mode == '>': # Right contraction - return update_and_substitute(A, B, dot_product_basis_blades, self.right_contract_table_dict) - else: - raise ValueError('"' + str(self.dot_mode) + '" not a legal mode in dot') + if Ap != 0 and Bp != 0: # Neither nc part of A or B is zero + prod = update_and_substitute(Ap, Bp, dot_product_basis_blades, self.right_contract_table_dict) + return prod + b * A + else: # Ap or Bp is zero + return b * A + else: + raise ValueError('"' + str(self.dot_mode) + '" not a legal mode in dot') + ######################## Helper Functions ########################## @@ -1170,12 +1190,35 @@ def grade_decomposition(self, A): grade_dict[grade] = self.mv(grade_dict[grade]) return grade_dict + def split_multivector(self, A): + """ + Split multivector A into commutative part a and non-commutative + part A' so that A = a+A' + """ + if isinstance(A, mv.Mv): + return self.split_multivector(A.obj) + else: + A = expand(A) + if isinstance(A, Add): + a = sum([x for x in A.args if x.is_commutative]) + Ap = sum([x for x in A.args if not x.is_commutative]) + return (a, Ap) + elif isinstance(A, Symbol): + if A.is_commutative: + return (A, 0) + else: + return (0, A) + else: + if A.is_commutative: + return (A, 0) + else: + return (0, A) + def remove_scalar_part(self, A): """ Return non-commutative part (sympy object) of A.obj. """ - if isinstance(A, mv.Mv): return self.remove_scalar_part(A.obj) else: @@ -1193,16 +1236,34 @@ def remove_scalar_part(self, A): else: return A + def scalar_part(self, A): - A = expand(A) - if isinstance(A, Add): - return(sum([x for x in A.args if x.is_commutative])) + + if isinstance(A, mv.Mv): + return self.scalar_part(A.obj) + else: + A = expand(A) + if isinstance(A, Add): + return(sum([x for x in A.args if x.is_commutative])) + elif isinstance(A, Symbol): + if A.is_commutative: + return A + else: + return 0 + else: + if A.is_commutative: + return A + else: + return 0 + + + """ else: if A.is_commutative: return A else: return zero - + """ def grades(self, A): # Return list of grades present in A A = self.base_to_blade_rep(A) diff --git a/galgebra-master/galgebra/lt.py b/galgebra-master/galgebra/lt.py index fcd9d94c..e45c223e 100755 --- a/galgebra-master/galgebra/lt.py +++ b/galgebra-master/galgebra/lt.py @@ -66,7 +66,11 @@ def __init__(self, *kargs, **kwargs): self.lt_dict = {} self.mv_dict = None - if isinstance(mat_rep, dict): # Dictionary input + if isinstance(mat_rep, tuple): # tuple input + for key in mat_rep: + self.lt_dict[key] = mat_rep[key] + + elif isinstance(mat_rep, dict): # Dictionary input for key in mat_rep: self.lt_dict[key] = mat_rep[key] diff --git a/galgebra-master/galgebra/metric.py b/galgebra-master/galgebra/metric.py index 72e91c0d..7cd4e02a 100755 --- a/galgebra-master/galgebra/metric.py +++ b/galgebra-master/galgebra/metric.py @@ -684,7 +684,7 @@ def __init__(self, basis, **kwargs): m[i, i] = g[i] self.g = m - self.g_raw = copy.copy(self.g) # save original metric tensor for use with submanifolds + self.g_raw = copy.deepcopy(self.g) # save original metric tensor for use with submanifolds if self.debug: printer.oprint('g', self.g) diff --git a/galgebra-master/galgebra/mv.py b/galgebra-master/galgebra/mv.py index 5e7e6668..8343f908 100755 --- a/galgebra-master/galgebra/mv.py +++ b/galgebra-master/galgebra/mv.py @@ -113,7 +113,6 @@ def Mul(A, B, op): elif op == '<': return A < B elif op == '>': - print 'A > B =', A, B return A > B else: raise ValeError('Operation ' + op + 'not allowed in Mv.Mul!') @@ -311,7 +310,10 @@ def __init__(self, *kargs, **kwargs): kargs = [kargs[0]] + list(kargs[2:]) Mv.init_dict[mode](self, *kargs, **kwargs) else: # kargs[1] = r (integer) Construct grade r multivector - Mv.init_dict['grade'](self, *kargs, **kwargs) + if kargs[1] == 0: + Mv.init_dict['scalar'](self, *kargs, **kwargs) + else: + Mv.init_dict['grade'](self, *kargs, **kwargs) if isinstance(kargs[0],str): self.title = kargs[0] @@ -320,6 +322,7 @@ def __init__(self, *kargs, **kwargs): ################# Multivector member functions ##################### def reflect_in_blade(self, blade): # Reflect mv in blade + # See Mv class functions documentation if blade.is_blade(): self.characterise_Mv() blade.characterise_Mv() @@ -337,6 +340,7 @@ def reflect_in_blade(self, blade): # Reflect mv in blade raise ValueError(str(blade) + 'is not a blade in reflect_in_blade(self, blade)') def project_in_blade(self,blade): + # See Mv class functions documentation if blade.is_blade(): blade.characterise_Mv() blade_inv = blade.rev() / blade.norm2() @@ -365,6 +369,34 @@ def blade_rep(self): self.is_blade_rep = True return self + def __ne__(self, A): + if isinstance(A, Mv): + diff = (self - A).expand() + if diff.obj == S(0): + return False + else: + return True + else: + if self.is_scalar() and self.obj == A: + return False + else: + return True + + def __eq__(self, A): + if isinstance(A, Mv): + diff = (self - A).expand() + if diff.obj == S(0): + return True + else: + return False + else: + if self.is_scalar() and self.obj == A: + return True + else: + return False + + + """ def __eq__(self, A): if not isinstance(A, Mv): if not self.is_scalar(): @@ -388,6 +420,7 @@ def __eq__(self, A): if expand(coefs[index]) != expand(Acoefs[index]): return False return True + """ def __neg__(self): return Mv(-self.obj, ga=self.Ga) @@ -504,15 +537,24 @@ def __mul_ab__(self, A): # self *= A self.characterise_Mv() return(self) + def __div_ab__(self,A): # self /= A + if isinstance(A,Mv): + self *= A.inv() + else: + self *= S(1)/A + return + def __div__(self, A): - self_div = Mv(self.obj, ga=self.Ga) - self_div.obj /= A - return(self_div) + if isinstance(A,Mv): + return self * A.inv() + else: + return self * (S(1)/A) def __truediv__(self, A): - self_div = Mv(self.obj, ga=self.Ga) - self_div.obj /= A - return(self_div) + if isinstance(A,Mv): + return self * A.inv() + else: + return self * (S(1)/A) def __str__(self): if printer.GaLatexPrinter.latex_flg: @@ -592,6 +634,9 @@ def Mv_str(self): return str(self.obj) def Mv_latex_str(self): + if self.obj == 0: + return ' 0 ' + self.first_line = True def append_plus(c_str): @@ -756,11 +801,13 @@ def __lt__(self, A): # left contraction (<) self = self.blade_rep() A = A.blade_rep() + """ if A.is_scalar(): if self.is_scalar(): return self.obj * A.obj else: return S(0) + """ self_lc_A = Mv(self.Ga.dot(self.obj, A.obj), ga=self.Ga) return self_lc_A @@ -780,11 +827,13 @@ def __gt__(self, A): # right contraction (>) self = self.blade_rep() A = A.blade_rep() + """ if self.is_scalar(): if A.is_scalar(): return self.obj * A.obj else: return S(0) + """ self_rc_A = Mv(self.Ga.dot(self.obj, A.obj), ga=self.Ga) return self_rc_A @@ -846,6 +895,13 @@ def is_blade(self): # True is self is blade, otherwise False self.blade_flg = False return self.blade_flg + def is_base(self): + (coefs,bases) = linear_expand(self.obj) + if len(coefs) > 1: + return False + else: + return True + def is_versor(self): # Test for versor (geometric product of vectors) """ This follows Leo Dorst's test for a versor. @@ -900,6 +956,10 @@ def get_coefs(self, grade): return coefs def proj(self, bases_lst): + """ + Project multivector onto a given list of bases. That is find the + part of multivector with the same bases as in the bases_lst. + """ bases_lst = [x.obj for x in bases_lst] (coefs, bases) = metric.linear_expand(self.obj) obj = 0 @@ -922,7 +982,6 @@ def dual(self): else: return sign * self * I - def even(self): # return even parts of multivector return Mv(self.Ga.even_odd(self.obj, True), ga=self.Ga) @@ -981,24 +1040,37 @@ def exp(self, hint='-'): # Calculate exponential of multivector """ self_sq = self * self if self_sq.is_scalar(): - sq = self_sq.obj - if sq.is_number: + sq = simplify(self_sq.obj) # sympy expression for self**2 + if sq == S(0): # sympy expression for self**2 = 0 + return self + S(1) + (coefs,bases) = metric.linear_expand(self.obj) + if len(coefs) == 1: # Exponential of scalar * base + base = bases[0] + base_Mv = self.Ga.mv(base) + base_sq = (base_Mv*base_Mv).scalar() + if hint == '-': # base^2 < 0 + base_n = sqrt(-base_sq) + return self.Ga.mv(cos(base_n*coefs[0]) + sin(base_n*coefs[0])*(bases[0]/base_n)) + else: # base^2 > 0 + base_n = sqrt(base_sq) + return self.Ga.mv(cosh(base_n*coefs[0]) + sinh(base_n*coefs[0])*(bases[0]/base_n)) + if sq.is_number: # Square is number, can test for sign if sq > S(0): norm = sqrt(sq) value = self.obj / norm return Mv(cosh(norm) + sinh(norm) * value, ga=self.Ga) - elif sq < S(0): + else: norm = sqrt(-sq) value = self.obj / norm return Mv(cos(norm) + sin(norm) * value, ga=self.Ga) - else: - return Mv(S(1), 'scalar', ga=self.Ga) else: - norm = metric.square_root_of_expr(sq) - value = self.obj / norm if hint == '+': + norm = simplify(sqrt(sq)) + value = self.obj / norm return Mv(cosh(norm) + sinh(norm) * value, ga=self.Ga) else: + norm = simplify(sqrt(-sq)) + value = self.obj / norm return Mv(cos(norm) + sin(norm) * value, ga=self.Ga) else: raise ValueError('"' + str(self) + '**2" is not a scalar in exp.') @@ -1126,12 +1198,16 @@ def norm(self, hint='+'): raise TypeError('"(' + str(product) + ')" is not a scalar in norm.') def inv(self): - reverse = self.rev() - product = self * reverse - if(product.is_scalar()): - return reverse.func(lambda coefficient: coefficient / product.obj) - else: - raise TypeError('"(' + str(product) + ')" is not a scalar.') + if self.is_scalar(): # self is a scalar + return self.ga.mv(S(1)/self.obj) + self_sq = self * self + if self_sq.is_scalar(): # self*self is a scalar + return (S(1)/self_sq.obj)*self + self_rev = self.rev() + self_self_rev = self * self_rev + if(self_self_rev.is_scalar()): # self*self.rev() is a scalar + return (S(1)/self_self_rev.obj) * self_rev + raise TypeError('In inv() for self =' + str(self) + 'self, or self*self or self*self.rev() is not a scalar') def func(self, fct): # Apply function, fct, to each coefficient of multivector (coefs, bases) = metric.linear_expand(self.obj) @@ -1783,7 +1859,7 @@ def __init__(self, *kargs, **kwargs): self.title = None if len(kargs[0]) == 0: # identity Dop - self.terms = [(S(1),self.Ga.pdop_identity)] + self.terms = [(S(1),self.Ga.Pdop_identity)] else: if len(kargs) == 2: if len(kargs[0]) != len(kargs[1]): @@ -1805,7 +1881,7 @@ def __init__(self, *kargs, **kwargs): coefs.append(coef * mv) self.terms = zip(coefs, pdiffs) else: - raise ValueError('In Dop.__init__ kargs[0] form not allowed.') + raise ValueError('In Dop.__init__ kargs[0] form not allowed. kargs = ' + str(kargs)) else: raise ValueError('In Dop.__init__ length of kargs must be 1 or 2.') @@ -2303,7 +2379,7 @@ def correlation(u, v, dec=3): # Compute the correlation coefficient of vectors def cross(v1, v2): if v1.is_vector() and v2.is_vector() and v1.Ga.name == v2.Ga.name and v1.Ga.n == 3: - return v1.Ga.I() * (v1 ^ v2) + return -v1.Ga.I() * (v1 ^ v2) else: raise ValueError(str(v1) + ' and ' + str(v2) + ' not compatible for cross product.') @@ -2321,6 +2397,12 @@ def even(A): return A.even() +def odd(A): + if not isinstance(A,Mv): + raise ValueError('A = ' + str(A) + ' not a multivector in even(A).') + return A.odd() + + def exp(A,hint='-'): if isinstance(A,Mv): return A.exp(hint) diff --git a/galgebra-master/galgebra/printer.py b/galgebra-master/galgebra/printer.py index ff7d9bde..d2e5aa2a 100755 --- a/galgebra-master/galgebra/printer.py +++ b/galgebra-master/galgebra/printer.py @@ -4,12 +4,17 @@ import sys import StringIO import re -from sympy import Matrix, Basic, S, C, Symbol, Function, Derivative +from sympy import Matrix, Basic, S, Symbol, Function, Derivative, Pow from itertools import islice from sympy.printing.str import StrPrinter from sympy.printing.latex import LatexPrinter, accepted_latex_functions from sympy.core.function import _coeff_isneg from sympy.core.operations import AssocOp +from sympy import init_printing + +from IPython.display import display, Latex, Math +from sympy.interactive import printing + from inspect import getouterframes, currentframe import ga import mv @@ -335,7 +340,6 @@ def _print_Mv(self, expr): if expr.obj == S(0): return '0' else: - #print 'expr.obj =',expr.obj return expr.Mv_str() def _print_Pdop(self, expr): @@ -638,7 +642,7 @@ def _print_Pow(self, expr): elif expr.exp.is_Rational and expr.exp.is_negative and expr.base.is_Function: # Things like 1/x return r"\frac{%s}{%s}" % \ - (1, self._print(C.Pow(expr.base, -expr.exp))) + (1, self._print(Pow(expr.base, -expr.exp))) else: if expr.base.is_Function: return self._print(expr.base, self._print(expr.exp)) @@ -938,6 +942,7 @@ def Format(Fmode=True, Dmode=True, dop=1): GaLatexPrinter.Fmode = Fmode if metric.in_ipynb(): GaLatexPrinter.ipy = True + else: GaLatexPrinter.ipy = False GaLatexPrinter.dop = dop @@ -945,8 +950,9 @@ def Format(Fmode=True, Dmode=True, dop=1): GaLatexPrinter.redirect() Basic.__str__ = lambda self: GaLatexPrinter().doprint(self) - Matrix.__str__ = lambda self: GaLatexPrinter().doprint(self) + #Matrix.__str__ = lambda self: GaLatexPrinter().doprint(self) Basic.__repr_ = lambda self: GaLatexPrinter().doprint(self) + #Matrix.__repr__ = lambda self: GaLatexPrinter().doprint(self) return @@ -1382,11 +1388,11 @@ def Fmt(obj,fmt=0): latex_str = r' \left ' + ldelim + r' \begin{array}{' + n*'c' + '} ' for cell in obj: if isinstance(obj,dict): - cell.title = None + #cell.title = None latex_cell = latex(cell) + ' : '+ latex(obj[cell]) else: - title = cell.title - cell.title = None + #title = cell.title + #cell.title = None latex_cell = latex(cell) latex_cell = latex_cell.replace('\n', ' ') latex_cell= latex_cell.replace(r'\begin{equation*}', ' ') @@ -1396,15 +1402,15 @@ def Fmt(obj,fmt=0): latex_cell= latex_cell.replace('&','') latex_cell= latex_cell.replace(r'\end{align*}', r'\\ \end{array} ') latex_str += latex_cell + ', & ' - cell.title = title + #cell.title = title latex_str = latex_str[:-4] latex_str += r'\\ \end{array} \right ' + rdelim + ' \n' else: latex_str = '' i = 1 for cell in obj: - title = cell.title - cell.title = None + #title = cell.title + #cell.title = None latex_cell = latex(cell) latex_cell = latex_cell.replace('\n', ' ') latex_cell= latex_cell.replace(r'\begin{equation*}', ' ') @@ -1413,7 +1419,7 @@ def Fmt(obj,fmt=0): latex_cell= latex_cell.replace(r'\begin{align*}', r'\begin{array}{c} ') latex_cell= latex_cell.replace('&','') latex_cell= latex_cell.replace(r'\end{align*}', r'\\ \end{array} ') - cell.title = title + #cell.title = title if i == 1: latex_str += r'\begin{array}{c} \left ' + ldelim + r' ' + latex_cell + r', \right. \\ ' elif i == n: @@ -1424,7 +1430,7 @@ def Fmt(obj,fmt=0): if metric.in_ipynb(): # For Ipython notebook if r'\begin{align*}' not in latex_str: latex_str = r'\begin{equation*} ' + latex_str + r'\end{equation*}' - return Latex(latex_str) + return Latex('$$ '+latex_str+' $$') else: return latex_str elif isinstance(obj,int):