Basic vector arithmetic

Mathematica

In Mathematica, curly braces denote a list or vector. Simple computations, like addition of two vectors or multiplying a vector by a scalar, are easy. Operations like multiplication and division work component by component.

In[1]:= {1,2,3} + {7,1,0}

Out[1]= {8, 3, 3}

In[2]:= 2*%

Out[2]= {16, 6, 6}

In[3]:= {1,2,3} * {7,1,0}

Out[3]= {7, 2, 0}

Maxima

In Maxima, square brackets denote a list or vector. Simple computations, like addition of two vectors or multiplying a vector by a scalar, are easy. Operations like multiplication and division work component by component.

(%i1) [1,2,3] + [7,1,0];

(%o1)                              [8, 3, 3]
(%i2) 2*%;

(%o2)                             [16, 6, 6]
(%i3) [1,2,3] * [7,1,0];

(%o3)                              [7, 2, 0]

Axiom

In Axiom, a vector is simply a list (given with square bracket notation) that has been given a Vector type via the

operator or coerced to a vector type by context. Simple computations, like addition of two vectors or multiplying a vector by a scalar, are easy.

(1) -> [1,2,3]::Vector Expression Float + [7,1,0]
(1) ->
   (1)  [8.0,3.0,3.0]
                                                Type: Vector Expression Float
(2) -> 2*%
(2) ->
   (2)  [16.0,6.0,6.0]
                                                Type: Vector Expression Float

Dot and cross products

Mathematica

Mathematica contains functions for computing dot products and cross products. They are Dot[] and Cross[], respectively. It can also use the "." operator for dot products.

In[3]:= {1,2,3} . {7,1,0}

Out[3]= 9

In[4]:= Dot[ {1,2,3}, {7,1,0} ]

Out[4]= 9

In[5]:= Cross[ {1,1,0}, {0,1,1} ]

Out[5]= {1, -1, 1}

Maxima

A special operator "." calculates dot products.

(%i4) [1,2,3] . [7,1,0];

(%o4)                                  9

Unfortunately, Maxima contains no useful cross product operator. Luckily it is an easy matter to define a function that returns the cross product of two vectors.

(%i5) cross(a,b) := [ a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1] ];

(%o5)    cross(a, b) := [a  b  - a  b , a  b  - a  b , a  b  - a  b ]
                          2  3    3  2   3  1    1  3   1  2    2  1
(%i6) cross( [1,1,0], [0,1,1] );

(%o6)                             [1, - 1, 1]

Axiom

Axiom contains functions for computing dot products and cross products. They are dot() and cross(), respectively.

(1) -> dot( [1,2,3], [7,1,0] )
(1) ->
   (1)  9
                                                        Type: PositiveInteger
(2) -> cross( [1,1,0], [0,1,1] )
(2) ->
   (2)  [1,- 1,1]
                                                         Type: Vector Integer

Other functions

Mathematica

It is often convenient to know the length, or magnitude, of a vector. In Mathematica, the Norm[] function provides this.

In[7]:= Norm[ {1,-1,1} ]

Out[7]= Sqrt[3]

Maxima

It is often convenient to know the length, or magnitude, of a vector. In Maxima, there are a few functions you might consider using for this. One is norm(), but it doesn’t return what we expect. The abs() function applies componentwise, returning a vector whose entries have all been made positive; not what we want. The easiest way to get the magnitude of a vector is to write a small function for that.

(%i7) mag(a) := sqrt( a . a );

(%o7)                        mag(a) := SQRT(a . a)
(%i8) mag( [1, -1, 1] );

(%o8)                               SQRT(3)

Axiom

It is often convenient to know the length, or magnitude, of a vector. Axiom uses the length() function for this.

(1) -> length([1,-1,1] :: Vector Float )
(1) ->
   (1)  1.7320508075 688772935
                                                                  Type: Float

An alternative method is to imitate the mag functions, above, using the dot() operator that exists in Axiom already. One advantage of this is that dot() coerces its argument into Vector type, so it doesn’t have to be done explicitly.

(1) ->
(1) -> mag(a) == sqrt(dot(a,a))
                                                                   Type: Void
(2) ->  mag([1,-1,1])
   Compiling function mag with type List Integer -> AlgebraicNumber

         +-+
   (2)  \|3
                                                        Type: AlgebraicNumber

One feature that is missing from Axiom that both Maxima and Mathematica have is the ability to take the derivative of a vector or list (and have the derivative apply to each component). It is easy to add such a function, for example, the following DV().

(1) -> macro DV(vec,var) == map( f +-> D(f,var), vec )
                                                                   Type: Void
(2) -> a := [ t^2, t^3 ]
(2) ->
          2  3
   (2)  [t ,t ]
                                                Type: List Polynomial Integer
(3) -> DV(a,t)
(3) ->
              2
   (3)  [2t,3t ]
                                                Type: List Polynomial Integer

Curl and Div

Mathematica

To use Curl[] and Div[] in Mathematica, the Calculus`VectorAnalysis` package must be loaded first.

In[1]:= <<Calculus`VectorAnalysis`

Curl[] and Div[] both accept a vector-valued function as the first argument, and the coordinate system as the second argument.

In[2]:= Div[ {x^2,x*y,x*y*z}, Cartesian[x,y,z] ]

Out[2]= 3 x + x y

In[3]:= Curl[ {x^2,x*y,x*y*z}, Cartesian[x,y,z] ]

Out[3]= {x z, -(y z), y}

Maxima

To use curl and div in Maxima, define these two functions.

(%i1) div(a) := diff(a[1],'x) + diff(a[2],'y) + diff(a[3],'z);

(%o1)        div(a) := DIFF(a , 'x) + DIFF(a , 'y) + DIFF(a , 'z)
                             1              2              3
(%i2) curl(a) := [
  diff(a[3],'y)-diff(a[2],'z),
  diff(a[1],'z)-diff(a[3],'x),
  diff(a[2],'x)-diff(a[1],'y) ];

(%o2) curl(a) := [DIFF(a , 'y) - DIFF(a , 'z), DIFF(a , 'z) - DIFF(a , 'x),
                        3              2             1              3

                                                   DIFF(a , 'x) - DIFF(a , 'y)]
                                                         2              1

Then, calculating a divergence or curl is simply a matter of passing a vector of functions based on the usual coordinate variables (x,y,z).

(%i3) div( [x^2,x*y,x*y*z] );

(%o3)                              x y + 3 x
(%i4) curl( [x^2,x*y,x*y*z] );

(%o4)                           [x z, - y z, y]

Axiom

To use curl and div in Axiom, define these two functions.

(1) -> div(a) == D(a(1),x) + D(a(2),y) + D(a(3),z)
                                                                   Type: Void

(2) -> curl(a) == vector [ D(a(3),y)-D(a(2),z) , D(a(1),z)-D(a(3),x) , D(a(2),x)-D(a(1),y) ]
                                                                   Type: Void

Then, calculating a divergence or curl is simply a matter of passing a vector of functions based on the usual coordinate variables (x,y,z).

(3) -> div( [x^2,x*y,x*y*z] )
   Compiling function div with type List Polynomial Integer ->
      Polynomial Integer

   (3)  x y + 3x
                                                     Type: Polynomial Integer
(4) -> curl( [x^2,x*y,x*y*z] )

   (4)  [x z,- y z,y]
                                                Type: Vector Polynomial Integer

Computing the Jacobian

Mathematica

Computing a Jacobian in Mathematica is not built in, but it can be done. The key to the process is the Outer[] function.

In[1]:= x = r*Cos[t]

Out[1]= r Cos[t]

In[2]:= y = r*Sin[t]

Out[2]= r Sin[t]

In[3]:= jmat = Outer[ D, {x,y}, {r,t} ]

Out[3]= {{Cos[t], -(r Sin[t])}, {Sin[t], r Cos[t]}}

The Outer[] function has created what we want, applying the Mathematica’s D[] function to our two lists.

For calculus work, it is usually the determinant that we need, and we can compute that as well.

In[4]:= Det[ jmat ]

                2           2
Out[4]= r Cos[t]  + r Sin[t]

In[5]:= Simplify[ % ]

Out[5]= r

For future convenience, we could define new functions to do this process automatically.

In[1]:= Jac[f_List?VectorQ, x_List] := Outer[D, f, x] /; Equal@@(Dimensions/@{f,x})

In[2]:= JDet[f_List?VectorQ, x_List] := Det[Jac[f, x]] /; Equal @@ (Dimensions /@ {f, x})

And we can check that these work:

In[3]:= x = r*Cos[t]; y = r*Sin[t];

In[4]:= Jac[ {x,y}, {r,t} ]

Out[4]= {{Cos[t], -(r Sin[t])}, {Sin[t], r Cos[t]}}

In[5]:= JDet[ {x,y}, {r,t} ]

                2           2
Out[5]= r Cos[t]  + r Sin[t]

Maxima

Computing a Jacobian in Maxima is not particularly straightforward, but it can be done. The keys to the process are the outermap() and apply() functions.

(%i1) x : r*cos(t); y : r*sin(t);
(%o1)                              r cos(t)
(%o2)                              r sin(t)
(%i3) jlist : outermap( diff, [x,y], [r,t] );
(%o3)             [[cos(t), - r sin(t)], [sin(t), r cos(t)]]

The outermap() function has created what we want, applying the Maxima’s diff() function to our two lists. Unfortunately, it doesn’t return a matrix, but rather a "list of lists." We can readily convert it to a matrix however by applying the matrix() function to the lists of lists.

(%i4) jmat : apply( matrix, jlist );
                            [ cos(t)  - r sin(t) ]
(%o4)                       [                    ]
                            [ sin(t)   r cos(t)  ]

For calculus work, it is usually the determinant that we need, and we can compute that as well.

(%i5) determinant( jmat );
                                  2           2
(%o5)                        r sin (t) + r cos (t)
(%i6) trigsimp(%);
(%o6)                                  r

For future convenience, we could define new functions to do this process automatically.

(%i1) jac(a,b) := apply( 'matrix, outermap( 'diff, a,b ));
(%o1)   jac(a, b) := apply('matrix, outermap('diff, a, b))
(%i2) jdet(a,b) := determinant( apply( 'matrix, outermap( 'diff, a,b )));
(%o2)   jdet(a, b) := determinant(apply('matrix, outermap('diff, a, b)))

And we can check that these work:

(%i3) x : r*cos(t); y:r*sin(t);
(%o3)                              r cos(t)
(%o4)                              r sin(t)
(%i5) jac( [x,y], [r,t] );
                            [ cos(t)  - r sin(t) ]
(%o5)                       [                    ]
                            [ sin(t)   r cos(t)  ]
(%i6) jdet( [x,y], [r,t] );
                                  2           2
(%o6)                        r sin (t) + r cos (t)

Saved macros

Maxima

The functions on this page can be stored once and automatically loaded in later Maxima sessions. To do so, we need only make a macro file.

Note: these commands happen outside Maxima. First we create a subdirectory of our home to put our macros in, called .maxima. Then we create a file in it called maxima-init.mac and put the function definitions in it.

$ mkdir ~/.maxima
$ cat > ~/.maxima/maxima-init.mac
cross(a,b) := [ a[2]*b[3]-a[3]*b[2], a[3]*b[1]-a[1]*b[3], a[1]*b[2]-a[2]*b[1] ];

mag(a) := sqrt( a . a );

div(a) := [ diff(a[1],'x), diff(a[2],'y), diff(a[3],'z) ];

curl(a) := [
  diff(a[3],'y)-diff(a[2],'z),
  diff(a[1],'z)-diff(a[3],'x),
  diff(a[2],'x)-diff(a[1],'y) ];

Press Ctrl-D after the last line, to end the file.

At the beginning of new maxima sessions, the macros will automatically be loaded.