00001 #ifndef SYMBOLICUTILITIES_H
00002 #define SYMBOLICUTILITIES_H
00003
00004 #include "SundanceDefs.h"
00005
00006 #include "Expr.h"
00007 #include "Derivative.h"
00008
00009
00010 namespace Sundance
00011 {
00012
00013 using namespace TSF;
00014
00015 template<int dim> Expr nabla();
00016
00017 template<> inline Expr nabla<1>()
00018 {
00019 static Expr dx = new Derivative(0);
00020 return dx;
00021 }
00022
00023 template<> inline Expr nabla<2>()
00024 {
00025 static Expr dx = new Derivative(0);
00026 static Expr dy = new Derivative(1);
00027 return List(dx, dy);
00028 }
00029
00030 template<> inline Expr nabla<3>()
00031 {
00032 static Expr dx = new Derivative(0);
00033 static Expr dy = new Derivative(1);
00034 static Expr dz = new Derivative(2);
00035 return List(dx, dy, dz);
00036 }
00037
00038 template<int dim> Expr gradient(const Expr& f);
00039
00040 template<> inline Expr gradient<1>(const Expr& f)
00041 {
00042 return nabla<1>()*f;
00043 }
00044
00045 template<> inline Expr gradient<2>(const Expr& f)
00046 {
00047 return nabla<2>()*f;
00048 }
00049
00050 template<> inline Expr gradient<3>(const Expr& f)
00051 {
00052 return nabla<2>()*f;
00053 }
00054
00055 template<int dim> Expr divergence(const Expr& f);
00056
00057 template<> inline Expr divergence<1>(const Expr& f)
00058 {
00059 if (f.length() != 1)
00060 {
00061 TSFError::raise("1D divergence operator called on a vector "
00062 "of dimension " + TSF::toString(f.length())
00063 + ": " + f.toString());
00064 }
00065 return nabla<1>()*f;
00066 }
00067
00068 template<> inline Expr divergence<2>(const Expr& f)
00069 {
00070 if (f.length() != 2)
00071 {
00072 TSFError::raise("2D divergence operator called on a vector "
00073 "of dimension " + TSF::toString(f.length())
00074 + ": " + f.toString());
00075 }
00076 return nabla<2>() * f;
00077 }
00078
00079 template<> inline Expr divergence<3>(const Expr& f)
00080 {
00081 if (f.length() != 3)
00082 {
00083 TSFError::raise("3D divergence operator called on a vector "
00084 "of dimension " + TSF::toString(f.length())
00085 + ": " + f.toString());
00086 }
00087 return nabla<3>() * f;
00088 }
00089
00090 inline Expr cross(const Expr& a, const Expr& b)
00091 {
00092 if (a.length() != b.length())
00093 {
00094 TSFError::raise("Unequal vector lengths in cross product: "
00095 "first arg= " + a.toString()
00096 + " second arg= " + b.toString());
00097 }
00098 if (a.length()==2)
00099 {
00100 return a[0]*b[1] - a[1]*b[0];
00101 }
00102 else if (a.length() == 3)
00103 {
00104 return List(a[1]*b[2] - a[2]*b[1],
00105 -a[0]*b[2] + a[2]*b[0],
00106 a[0]*b[1] - a[1]*b[0]);
00107 }
00108 else
00109 {
00110 TSFError::raise("vector lengths in cross product must be 2 or 3: "
00111 "first arg= " + a.toString()
00112 + " second arg= " + b.toString());
00113 return 0.0;
00114 }
00115 }
00116
00117 template<int dim> Expr curl(const Expr& f);
00118
00119 template<> inline Expr curl<2>(const Expr& f)
00120 {
00121 return cross(nabla<2>(), f);
00122 }
00123
00124 template<> inline Expr curl<3>(const Expr& f)
00125 {
00126 return cross(nabla<3>(), f);
00127 }
00128
00129 template<int dim> Expr grad(const Expr& f);
00130
00131 template<> inline Expr grad<1>(const Expr& f) {return gradient<1>(f);}
00132 template<> inline Expr grad<2>(const Expr& f) {return gradient<2>(f);}
00133 template<> inline Expr grad<3>(const Expr& f) {return gradient<3>(f);}
00134
00135 template<int dim> Expr div(const Expr& f);
00136
00137 template<> inline Expr div<1>(const Expr& f) {return divergence<1>(f);}
00138 template<> inline Expr div<2>(const Expr& f) {return divergence<2>(f);}
00139 template<> inline Expr div<3>(const Expr& f) {return divergence<3>(f);}
00140 }
00141
00142
00143 #endif
00144
00145
00146
00147
00148