00001 #ifdef CH_LANG_CC
00002
00003
00004
00005
00006
00007
00008
00009 #endif
00010
00011 #ifndef _NORMALDERIVATIVENEW_H_
00012 #define _NORMALDERIVATIVENEW_H_
00013
00014 #include "MayDay.H"
00015
00016 #include "Notation.H"
00017 #include "BoxIterator.H"
00018 #include "IFSlicer.H"
00019
00020 #include "NamespaceHeader.H"
00021
00022
00023
00024
00025
00026 template <int dim> class NormalDerivativeNew
00027 {
00028 public:
00029 typedef IndexTM<int,dim> IvDim;
00030 typedef IndexTM<Real,dim> RvDim;
00031
00032
00033
00034 typedef map<IvDim,Real,LexLT<IvDim> > ScalarPowerMap;
00035 typedef map<IvDim,RvDim,LexLT<IvDim> > NormalDerivativeMap;
00036
00037
00038
00039
00040
00041 NormalDerivativeNew();
00042
00043
00044
00045
00046
00047 virtual ~NormalDerivativeNew();
00048
00049
00050
00051
00052
00053
00054
00055
00056 Real normal(const int & a_direction,
00057 const RvDim & a_point,
00058 const IFSlicer<dim> * a_implicitFunction) const
00059 {
00060
00061 Real lenGradIF = 0.0;
00062 Real value = 0.0;
00063
00064 for (int idir = 0; idir < dim; idir++)
00065 {
00066 Real dxd = a_implicitFunction->
00067 value(BASISV_TM<int,dim>(idir), a_point);
00068 if (idir == a_direction)
00069 value = dxd;
00070 lenGradIF += dxd*dxd;
00071 }
00072
00073 return value / sqrt(lenGradIF);
00074 }
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 NormalDerivativeMap calculateAll(const int& a_maxP,
00085 const RvDim& a_point,
00086 const IFSlicer<dim>* a_implicitFunction)
00087 {
00088
00089
00090 ScalarPowerMap phiDerivs;
00091 ScalarPowerMap lDerivs;
00092 NormalDerivativeMap nDerivs;
00093
00094
00095
00096 Box b(IntVect::Zero, a_maxP*IntVect::Unit);
00097 BoxIterator bit(b);
00098 for (bit.begin(); bit.ok(); ++bit)
00099 {
00100 IvDim pow;
00101 for(int idir = 0; idir < dim; idir++)
00102 {
00103 pow[idir] = bit()[idir];
00104 }
00105 if (pow.sum() <= a_maxP)
00106 nDerivs[pow] = RvDim::Zero;
00107 }
00108
00109
00110 calculatePhiDerivs(phiDerivs, a_point, a_implicitFunction, a_maxP+1);
00111
00112
00113 typename NormalDerivativeMap::const_iterator it;
00114 for (it = nDerivs.begin(); it != nDerivs.end(); ++it)
00115 {
00116 IvDim p = it->first;
00117 addLDeriv(lDerivs, phiDerivs, nDerivs, p);
00118 addNDeriv(nDerivs, phiDerivs, lDerivs, p);
00119 }
00120
00121
00122
00123
00124
00125
00126 return nDerivs;
00127 }
00128
00129 protected:
00130
00131 void calculatePhiDerivs(
00132 ScalarPowerMap& a_phiDerivs,
00133 const RvDim& a_point,
00134 const IFSlicer<dim>* a_implicitFunction,
00135 const int& a_maxPartial)
00136 {
00137 Box b(IntVect::Zero, a_maxPartial*IntVect::Unit);
00138 BoxIterator bit(b);
00139
00140
00141 for (bit.begin(); bit.ok(); ++bit)
00142 {
00143 if (bit().sum() <= a_maxPartial)
00144 {
00145 IvDim deriv;
00146 for(int idir = 0; idir < dim; idir++)
00147 {
00148 deriv[idir]= bit()[idir];
00149 }
00150
00151 a_phiDerivs[deriv] = a_implicitFunction->value(deriv, a_point);
00152 }
00153 }
00154 }
00155
00156
00157 void addLDeriv(
00158 ScalarPowerMap& a_lDerivs,
00159 ScalarPowerMap& a_phiDerivs,
00160 NormalDerivativeMap& a_nDerivs,
00161 const IvDim& a_deriv)
00162 {
00163
00164 if (a_deriv == IvDim::Zero)
00165 {
00166 RvDim dphi;
00167 Real len = 0;
00168 for (int d=0; d < dim; ++d)
00169 {
00170 Real val = a_phiDerivs[BASISV_TM<int,dim>(d)];
00171 dphi[d] = val;
00172 len += val*val;
00173 }
00174 a_lDerivs[a_deriv] = sqrt(len);
00175 return;
00176 }
00177
00178
00179 int dir;
00180 for (dir=0; dir < dim-1; ++dir)
00181 if (a_deriv[dir] > 0)
00182 break;
00183
00184 Real dl = 0;
00185 IvDim q = a_deriv - BASISV_TM<int,dim>(dir);
00186 typename NormalDerivativeMap::const_iterator it;
00187 for (it = a_nDerivs.begin(); it != a_nDerivs.end(); ++it)
00188 {
00189 IvDim r = it->first;
00190 if (r <= q)
00191 {
00192 Real coef = nChoosek(q,r);
00193 RvDim dn = a_nDerivs[r];
00194 for (int d=0; d < dim; ++d)
00195 {
00196 IvDim dphip = q - r + BASISV_TM<int,dim>(d) +
00197 BASISV_TM<int,dim>(dir);
00198 dl += coef * dn[d] * a_phiDerivs[dphip];
00199 }
00200 }
00201 }
00202 a_lDerivs[a_deriv] = dl;
00203 }
00204
00205
00206 void addNDeriv(
00207 NormalDerivativeMap& a_nDerivs,
00208 ScalarPowerMap& a_phiDerivs,
00209 ScalarPowerMap& a_lDerivs,
00210 const IvDim& a_deriv)
00211 {
00212 RvDim dn = RvDim::Zero;
00213 typename NormalDerivativeMap::const_iterator it;
00214 for (it = a_nDerivs.begin(); it != a_nDerivs.end(); ++it)
00215 {
00216 IvDim q = it->first;
00217 if ((q <= a_deriv) && (q != a_deriv))
00218 {
00219 Real coef = nChoosek(a_deriv,q);
00220 dn += (coef * a_lDerivs[a_deriv-q]) * it->second;
00221 }
00222 }
00223
00224 Real l = a_lDerivs[IvDim::Zero];
00225 RvDim dphi;
00226 for (int d=0; d < dim; ++d)
00227 dphi[d] = a_phiDerivs[a_deriv + BASISV_TM<int,dim>(d)];
00228 a_nDerivs[a_deriv] = (dphi - dn) / l;
00229 }
00230
00231
00232
00233
00234 static int nChoosek(const IvDim& a_n, const IvDim& a_k)
00235 {
00236 int numer = 1;
00237 int denom = 1;
00238
00239 IvDim diff = a_n - a_k;
00240 CH_assert(diff >= IvDim::Zero);
00241 for (int d = 0; d < dim; ++d)
00242 {
00243 for (int i=diff[d]+1; i <= a_n[d]; ++i)
00244 numer *= i;
00245 for (int i=2; i <= a_k[d]; ++i)
00246 denom *= i;
00247 }
00248
00249 return numer / denom;
00250 }
00251
00252 private:
00253 NormalDerivativeNew(const NormalDerivativeNew& a_input)
00254 {
00255 MayDay::Abort("NormalDerivativeNew doesn't allow copy construction");
00256 }
00257
00258 void operator=(const NormalDerivativeNew& a_input)
00259 {
00260 MayDay::Abort("NormalDerivativeNew doesn't allow assignment");
00261 }
00262 };
00263
00264 #include "NamespaceFooter.H"
00265
00266 #include "NormalDerivativeNewImplem.H"
00267
00268 #endif