src/Meshes/UniformCartesian.cpp

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 /***************************************************************************
00003  *
00004  * The IPPL Framework
00005  * 
00006  * This program was prepared by PSI. 
00007  * All rights in the program are reserved by PSI.
00008  * Neither PSI nor the author(s)
00009  * makes any warranty, express or implied, or assumes any liability or
00010  * responsibility for the use of this software
00011  *
00012  * Visit http://www.acl.lanl.gov/POOMS for more details
00013  *
00014  ***************************************************************************/
00015 
00016 // -*- C++ -*-
00017 /***************************************************************************
00018  *
00019  * The IPPL Framework
00020  * 
00021  *
00022  * Visit http://people.web.psi.ch/adelmann/ for more details
00023  *
00024  ***************************************************************************/
00025 
00026 // UniformCartesian.cpp
00027 // Implementations for UniformCartesian mesh class (uniform spacings)
00028 
00029 // include files
00030 #include "Utility/PAssert.h"
00031 #include "Utility/IpplInfo.h"
00032 #include "Field/BareField.h"
00033 #include "Field/BrickExpression.h"
00034 #include "Field/LField.h"
00035 #include "Field/Field.h"
00036 #include "Field/Assign.h"
00037 #include "Field/AssignDefs.h"
00038 
00039 //-----------------------------------------------------------------------------
00040 // Setup chores common to all constructors:
00041 //-----------------------------------------------------------------------------
00042 template <unsigned Dim, class MFLOAT>
00043 void 
00044 UniformCartesian<Dim,MFLOAT>::
00045 setup()
00046 {
00047   hasSpacingFields = false;
00048   FlCell = 0;
00049   FlVert = 0;
00050   VertSpacings = 0;
00051   CellSpacings = 0;
00052   volume = 0.0;
00053 }
00054 
00055 //-----------------------------------------------------------------------------
00056 // Constructors from NDIndex object:
00057 //-----------------------------------------------------------------------------
00058 template <unsigned Dim, class MFLOAT>
00059 UniformCartesian<Dim,MFLOAT>::
00060 UniformCartesian(const NDIndex<Dim>& ndi)
00061 {
00062   setup();
00063   for (int d=0; d<Dim; d++) {
00064     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00065     meshSpacing[d] = ndi[d].stride();  // Default mesh spacing from stride()
00066     origin(d) = ndi[d].first();     // Default origin at ndi[d].first
00067   }
00068   volume = 1.0;               // Default mesh has unit cell volume.
00069   set_Dvc();                  // Set derivative coefficients from spacings.
00070 }
00071 // Also specify mesh spacings:
00072 template <unsigned Dim, class MFLOAT>
00073 UniformCartesian<Dim,MFLOAT>::
00074 UniformCartesian(const NDIndex<Dim>& ndi, MFLOAT* const delX)
00075 {
00076   setup();
00077   for (int d=0; d<Dim; d++) {
00078     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00079     origin(d) = ndi[d].first();     // Default origin at ndi[d].first
00080   }
00081   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00082 }
00083 // Also specify mesh spacings and origin:
00084 template <unsigned Dim, class MFLOAT>
00085 UniformCartesian<Dim,MFLOAT>::
00086 UniformCartesian(const NDIndex<Dim>& ndi, MFLOAT* const delX,
00087                  const Vektor<MFLOAT,Dim>& orig)
00088 {
00089   setup();
00090   for (int d=0; d<Dim; d++) {
00091     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00092   }
00093   set_origin(orig);           // Set origin.
00094   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00095 }
00096 //-----------------------------------------------------------------------------
00097 // Constructors from Index objects:
00098 //-----------------------------------------------------------------------------
00099 
00100 //===========1D============
00101 template <unsigned Dim, class MFLOAT>
00102 UniformCartesian<Dim,MFLOAT>::
00103 UniformCartesian(const Index& I)
00104 {
00105   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00106   setup();
00107   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00108   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00109   origin(0) = I.first();      // Default origin at I.first()
00110 
00111   volume = 1.0;               // Default mesh has unit cell volume.
00112   set_Dvc();                  // Set derivative coefficients from spacings.
00113 }
00114 // Also specify mesh spacings:
00115 template <unsigned Dim, class MFLOAT>
00116 UniformCartesian<Dim,MFLOAT>::
00117 UniformCartesian(const Index& I, MFLOAT* const delX)
00118 {
00119   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00120   setup();
00121   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00122   origin(0) = I.first();      // Default origin at I.first()
00123 
00124   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00125 }
00126 // Also specify mesh spacings and origin:
00127 template <unsigned Dim, class MFLOAT>
00128 UniformCartesian<Dim,MFLOAT>::
00129 UniformCartesian(const Index& I, MFLOAT* const delX,
00130                  const Vektor<MFLOAT,Dim>& orig)
00131 {
00132   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00133   setup();
00134   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00135   set_origin(orig);           // Set origin.
00136   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00137 }
00138 
00139 //===========2D============
00140 template <unsigned Dim, class MFLOAT>
00141 UniformCartesian<Dim,MFLOAT>::
00142 UniformCartesian(const Index& I, const Index& J)
00143 {
00144   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00145   setup();
00146   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00147   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00148   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00149   meshSpacing[1] = J.stride();
00150   origin(0) = I.first();      // Default origin at (I.first(),J.first())
00151   origin(1) = J.first();
00152 
00153   volume = 1.0;               // Default mesh has unit cell volume.
00154   set_Dvc();                  // Set derivative coefficients from spacings.
00155 }
00156 // Also specify mesh spacings:
00157 template <unsigned Dim, class MFLOAT>
00158 UniformCartesian<Dim,MFLOAT>::
00159 UniformCartesian(const Index& I, const Index& J, MFLOAT* const delX)
00160 {
00161   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00162   setup();
00163   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00164   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00165   origin(0) = I.first();      // Default origin at (I.first(),J.first())
00166   origin(1) = J.first();
00167   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00168 }
00169 // Also specify mesh spacings and origin:
00170 template <unsigned Dim, class MFLOAT>
00171 UniformCartesian<Dim,MFLOAT>::
00172 UniformCartesian(const Index& I, const Index& J, MFLOAT* const delX,
00173                  const Vektor<MFLOAT,Dim>& orig)
00174 {
00175   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00176   setup();
00177   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00178   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00179   set_origin(orig);           // Set origin.
00180   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00181 }
00182 
00183 //===========3D============
00184 template <unsigned Dim, class MFLOAT>
00185 UniformCartesian<Dim,MFLOAT>::
00186 UniformCartesian(const Index& I, const Index& J, const Index& K)
00187 {
00188   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00189   setup();
00190   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00191   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00192   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00193   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00194   meshSpacing[1] = J.stride();
00195   meshSpacing[2] = K.stride();
00196   origin(0) = I.first();   // Default origin at (I.first(),J.first(),K.first())
00197   origin(1) = J.first();
00198   origin(2) = K.first();
00199 
00200   volume = 1.0;               // Default mesh has unit cell volume.
00201   set_Dvc();                  // Set derivative coefficients from spacings.
00202 }
00203 // Also specify mesh spacings:
00204 template <unsigned Dim, class MFLOAT>
00205 UniformCartesian<Dim,MFLOAT>::
00206 UniformCartesian(const Index& I, const Index& J, const Index& K,
00207                  MFLOAT* const delX)
00208 {
00209   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00210   setup();
00211   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00212   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00213   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00214   origin(0) = I.first();   // Default origin at (I.first(),J.first(),K.first())
00215   origin(1) = J.first();
00216   origin(2) = K.first();
00217   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00218 }
00219 // Also specify mesh spacings and origin:
00220 template <unsigned Dim, class MFLOAT>
00221 UniformCartesian<Dim,MFLOAT>::
00222 UniformCartesian(const Index& I, const Index& J, const Index& K,
00223                  MFLOAT* const delX, const Vektor<MFLOAT,Dim>& orig)
00224 {
00225   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00226   setup();
00227   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00228   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00229   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00230   set_origin(orig);           // Set origin.
00231   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00232 }
00233 
00234 //-----------------------------------------------------------------------------
00235 // initialize with NDIndex object:
00236 //-----------------------------------------------------------------------------
00237 template <unsigned Dim, class MFLOAT>
00238 void
00239 UniformCartesian<Dim,MFLOAT>::
00240 initialize(const NDIndex<Dim>& ndi)
00241 {
00242   setup();
00243   for (int d=0; d<Dim; d++) {
00244     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00245     meshSpacing[d] = ndi[d].stride();  // Default mesh spacing from stride()
00246     origin(d) = ndi[d].first();     // Default origin at ndi[d].first
00247   }
00248   volume = 1.0;               // Default mesh has unit cell volume.
00249   set_Dvc();                  // Set derivative coefficients from spacings.
00250 }
00251 // Also specify mesh spacings:
00252 template <unsigned Dim, class MFLOAT>
00253 void
00254 UniformCartesian<Dim,MFLOAT>::
00255 initialize(const NDIndex<Dim>& ndi, MFLOAT* const delX)
00256 {
00257   setup();
00258   for (int d=0; d<Dim; d++) {
00259     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00260     origin(d) = ndi[d].first();     // Default origin at ndi[d].first
00261   }
00262   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00263 }
00264 // Also specify mesh spacings and origin:
00265 template <unsigned Dim, class MFLOAT>
00266 void
00267 UniformCartesian<Dim,MFLOAT>::
00268 initialize(const NDIndex<Dim>& ndi, MFLOAT* const delX,
00269            const Vektor<MFLOAT,Dim>& orig)
00270 {
00271   setup();
00272   for (int d=0; d<Dim; d++) {
00273     gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
00274   }
00275   set_origin(orig);           // Set origin.
00276   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00277 }
00278 //-----------------------------------------------------------------------------
00279 // initialize from Index objects:
00280 //-----------------------------------------------------------------------------
00281 
00282 //===========1D============
00283 template <unsigned Dim, class MFLOAT>
00284 void
00285 UniformCartesian<Dim,MFLOAT>::
00286 initialize(const Index& I)
00287 {
00288   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00289   setup();
00290   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00291   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00292   origin(0) = I.first();      // Default origin at I.first()
00293 
00294   volume = 1.0;               // Default mesh has unit cell volume.
00295   set_Dvc();                  // Set derivative coefficients from spacings.
00296 }
00297 // Also specify mesh spacings:
00298 template <unsigned Dim, class MFLOAT>
00299 void
00300 UniformCartesian<Dim,MFLOAT>::
00301 initialize(const Index& I, MFLOAT* const delX)
00302 {
00303   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00304   setup();
00305   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00306   origin(0) = I.first();      // Default origin at I.first()
00307 
00308   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00309 }
00310 // Also specify mesh spacings and origin:
00311 template <unsigned Dim, class MFLOAT>
00312 void
00313 UniformCartesian<Dim,MFLOAT>::
00314 initialize(const Index& I, MFLOAT* const delX,
00315            const Vektor<MFLOAT,Dim>& orig)
00316 {
00317   PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
00318   setup();
00319   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00320   set_origin(orig);           // Set origin.
00321   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00322 }
00323 
00324 //===========2D============
00325 template <unsigned Dim, class MFLOAT>
00326 void
00327 UniformCartesian<Dim,MFLOAT>::
00328 initialize(const Index& I, const Index& J)
00329 {
00330   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00331   setup();
00332   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00333   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00334   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00335   meshSpacing[1] = J.stride();
00336   origin(0) = I.first();      // Default origin at (I.first(),J.first())
00337   origin(1) = J.first();
00338 
00339   volume = 1.0;               // Default mesh has unit cell volume.
00340   set_Dvc();                  // Set derivative coefficients from spacings.
00341 }
00342 // Also specify mesh spacings:
00343 template <unsigned Dim, class MFLOAT>
00344 void
00345 UniformCartesian<Dim,MFLOAT>::
00346 initialize(const Index& I, const Index& J, MFLOAT* const delX)
00347 {
00348   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00349   setup();
00350   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00351   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00352   origin(0) = I.first();      // Default origin at (I.first(),J.first())
00353   origin(1) = J.first();
00354   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00355 }
00356 // Also specify mesh spacings and origin:
00357 template <unsigned Dim, class MFLOAT>
00358 void
00359 UniformCartesian<Dim,MFLOAT>::
00360 initialize(const Index& I, const Index& J, MFLOAT* const delX,
00361            const Vektor<MFLOAT,Dim>& orig)
00362 {
00363   PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
00364   setup();
00365   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00366   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00367   set_origin(orig);           // Set origin.
00368   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00369 }
00370 
00371 //===========3D============
00372 template <unsigned Dim, class MFLOAT>
00373 void
00374 UniformCartesian<Dim,MFLOAT>::
00375 initialize(const Index& I, const Index& J, const Index& K)
00376 {
00377   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00378   setup();
00379   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00380   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00381   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00382   meshSpacing[0] = I.stride();       // Default mesh spacing from stride()
00383   meshSpacing[1] = J.stride();
00384   meshSpacing[2] = K.stride();
00385   origin(0) = I.first();   // Default origin at (I.first(),J.first(),K.first())
00386   origin(1) = J.first();
00387   origin(2) = K.first();
00388 
00389   volume = 1.0;               // Default mesh has unit cell volume.
00390   set_Dvc();                  // Set derivative coefficients from spacings.
00391 }
00392 // Also specify mesh spacings:
00393 template <unsigned Dim, class MFLOAT>
00394 void
00395 UniformCartesian<Dim,MFLOAT>::
00396 initialize(const Index& I, const Index& J, const Index& K,
00397            MFLOAT* const delX)
00398 {
00399   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00400   setup();
00401   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00402   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00403   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00404   origin(0) = I.first();   // Default origin at (I.first(),J.first(),K.first())
00405   origin(1) = J.first();
00406   origin(2) = K.first();
00407   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00408 }
00409 // Also specify mesh spacings and origin:
00410 template <unsigned Dim, class MFLOAT>
00411 void
00412 UniformCartesian<Dim,MFLOAT>::
00413 initialize(const Index& I, const Index& J, const Index& K,
00414            MFLOAT* const delX, const Vektor<MFLOAT,Dim>& orig)
00415 {
00416   PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
00417   setup();
00418   gridSizes[0] = I.length();  // Number of vertices along this dimension.
00419   gridSizes[1] = J.length();  // Number of vertices along this dimension.
00420   gridSizes[2] = K.length();  // Number of vertices along this dimension.
00421   set_origin(orig);           // Set origin.
00422   set_meshSpacing(delX);      // Set mesh spacings and compute cell volume
00423 }
00424 
00425 //-----------------------------------------------------------------------------
00426 // Set/accessor functions for member data:
00427 //-----------------------------------------------------------------------------
00428 // Set the origin of mesh vertex positions:
00429 template<unsigned Dim, class MFLOAT>
00430 void UniformCartesian<Dim,MFLOAT>::
00431 set_origin(const Vektor<MFLOAT,Dim>& o)
00432 {
00433   origin = o;
00434   this->notifyOfChange();
00435 }
00436 // Get the origin of mesh vertex positions:
00437 template<unsigned Dim, class MFLOAT>
00438 Vektor<MFLOAT,Dim> UniformCartesian<Dim,MFLOAT>::
00439 get_origin() const
00440 {
00441   return origin;
00442 }
00443 
00444 // Set the spacings of mesh vertex positions (recompute Dvc, cell volume):
00445 template<unsigned Dim, class MFLOAT>
00446 void UniformCartesian<Dim,MFLOAT>::
00447 set_meshSpacing(MFLOAT* const del)
00448 {
00449   unsigned d;
00450   volume = 1.0;
00451   for (d=0; d<Dim; ++d) {
00452     meshSpacing[d] = del[d];
00453     volume *= del[d];
00454   }
00455   set_Dvc();
00456   // if spacing fields exist, we must recompute values
00457   if (hasSpacingFields) storeSpacingFields();
00458   this->notifyOfChange();
00459 }
00460 // Set only the derivative constants, using pre-set spacings:
00461 template<unsigned Dim, class MFLOAT>
00462 void UniformCartesian<Dim,MFLOAT>::
00463 set_Dvc()
00464 {
00465   unsigned d;
00466   MFLOAT coef = 1.0;
00467   for (d=1;d<Dim;++d) coef *= 0.5;
00468 
00469   for (d=0;d<Dim;++d) {
00470     MFLOAT dvc = coef/meshSpacing[d];
00471     for (unsigned b=0; b<(1<<Dim); ++b) {
00472       int s = ( b&(1<<d) ) ? 1 : -1;
00473       Dvc[b][d] = s*dvc;
00474     }
00475   }
00476 }
00477 // Get the spacings of mesh vertex positions along specified direction:
00478 template<unsigned Dim, class MFLOAT>
00479 MFLOAT UniformCartesian<Dim,MFLOAT>::
00480 get_meshSpacing(unsigned d) const
00481 {
00482   PAssert(d<Dim);
00483   MFLOAT ms = meshSpacing[d]; 
00484   return ms;
00485 }
00486 
00487 // Get the cell volume:
00488 template<unsigned Dim, class MFLOAT>
00489 MFLOAT UniformCartesian<Dim,MFLOAT>::
00490 get_volume() const
00491 {
00492   return volume;
00493 }
00494 
00496 
00497 // Applicative templates for Mesh BC PETE_apply() functions, used
00498 // by BrickExpression in storeSpacingFields()
00499 
00500 // Reflective/None (all are the same for uniform, incl. Periodic).
00501 template<class T>
00502 struct OpUMeshExtrapolate
00503 {
00504   OpUMeshExtrapolate(T& o, T& s) : Offset(o), Slope(s) {}
00505   T Offset, Slope;
00506 };
00507 
00508 template<class T>
00509 void PETE_apply(OpUMeshExtrapolate<T> e, T& a, T b) 
00510 { 
00511   a = b*e.Slope+e.Offset;
00512 }
00513 
00515 
00516 // Create BareField's of vertex and cell spacings
00517 // Special prototypes taking no args or FieldLayout ctor args:
00518 // No-arg case:
00519 template<unsigned Dim, class MFLOAT>
00520 void UniformCartesian<Dim,MFLOAT>::
00521 storeSpacingFields()
00522 {
00523   // Set up default FieldLayout parameters:
00524   e_dim_tag et[Dim];
00525   for (int d=0; d<Dim; d++) et[d] = PARALLEL;
00526   storeSpacingFields(et, -1);
00527 }
00528 // 1D
00529 template<unsigned Dim, class MFLOAT>
00530 void UniformCartesian<Dim,MFLOAT>::
00531 storeSpacingFields(e_dim_tag p1, int vnodes)
00532 {
00533   e_dim_tag et[1];
00534   et[0] = p1;
00535   storeSpacingFields(et, vnodes);
00536 }
00537 // 2D
00538 template<unsigned Dim, class MFLOAT>
00539 void UniformCartesian<Dim,MFLOAT>::
00540 storeSpacingFields(e_dim_tag p1, e_dim_tag p2, int vnodes)
00541 {
00542   e_dim_tag et[2];
00543   et[0] = p1;
00544   et[1] = p2;
00545   storeSpacingFields(et, vnodes);
00546 }
00547 // 3D
00548 template<unsigned Dim, class MFLOAT>
00549 void UniformCartesian<Dim,MFLOAT>::
00550 storeSpacingFields(e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, int vnodes)
00551 {
00552   e_dim_tag et[3];
00553   et[0] = p1;
00554   et[1] = p2;
00555   et[2] = p3;
00556   storeSpacingFields(et, vnodes);
00557 }
00558 // The general storeSpacingfields() function; others invoke this internally:
00559 template<unsigned Dim, class MFLOAT>
00560 void UniformCartesian<Dim,MFLOAT>::
00561 storeSpacingFields(e_dim_tag* et, int vnodes)
00562 {
00563   // VERTEX-VERTEX SPACINGS (same as CELL-CELL SPACINGS for uniform):
00564   NDIndex<Dim> cells, verts;
00565   int d;
00566   for (d=0; d<Dim; d++) {
00567     cells[d] = Index(gridSizes[d]-1);
00568     verts[d] = Index(gridSizes[d]);
00569   }
00570   if (!hasSpacingFields) {
00571     // allocate layout and spacing field
00572     FlCell = new FieldLayout<Dim>(cells, et, vnodes);
00573     // Note: enough guard cells only for existing Div(), etc. implementations:
00574     // (not really used by Div() etc for UniformCartesian); someday should make
00575     // this user-settable.
00576     VertSpacings = 
00577       new BareField<Vektor<MFLOAT,Dim>,Dim>(*FlCell,GuardCellSizes<Dim>(1));
00578     // Added 12/8/98 --TJW:
00579     FlVert = 
00580       new FieldLayout<Dim>(verts, et, vnodes);
00581     // Note: enough guard cells only for existing Div(), etc. implementations:
00582     CellSpacings = 
00583       new BareField<Vektor<MFLOAT,Dim>,Dim>(*FlVert,GuardCellSizes<Dim>(1));
00584   }
00585   BareField<Vektor<MFLOAT,Dim>,Dim>& vertSpacings = *VertSpacings;
00586   Vektor<MFLOAT,Dim> vertexSpacing;
00587   for (d=0; d<Dim; d++) 
00588     vertexSpacing[d] = meshSpacing[d];
00589   vertSpacings = vertexSpacing;
00590   //-------------------------------------------------
00591   // Now the hard part, filling in the guard cells:
00592   //-------------------------------------------------
00593   // The easy part of the hard part is filling so that all the internal
00594   // guard layers are right:
00595   vertSpacings.fillGuardCells();
00596   // The hard part of the hard part is filling the external guard layers,
00597   // using the mesh BC to figure out how:
00598   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00599   // Temporaries used in loop over faces
00600   Vektor<MFLOAT,Dim> v0,v1; v0 = 0.0; v1 = 1.0; // Used for Reflective mesh BC
00601   int face;
00602   typedef Vektor<MFLOAT,Dim> T;          // Used multipple places in loop below
00603   typename BareField<T,Dim>::iterator_if vfill_i; // Iterator used below
00604   int voffset;             // Pointer offsets used with LField::iterator below
00605   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00606   for (face=0; face < 2*Dim; face++) {
00607     // NDIndex's spanning elements and guard elements:
00608     NDIndex<Dim> vSlab = AddGuardCells(cells,vertSpacings.getGuardCellSizes());
00609     // Shrink it down to be the guards along the active face:
00610     d = face/2;
00611     // The following bitwise AND logical test returns true if face is odd
00612     // (meaning the "high" or "right" face in the numbering convention) and 
00613     // returns false if face is even (meaning the "low" or "left" face in 
00614     // the numbering convention):
00615     if ( face & 1 ) {
00616       vSlab[d] = Index(cells[d].max() + 1, 
00617                        cells[d].max() + vertSpacings.rightGuard(d));
00618     } else {
00619       vSlab[d] = Index(cells[d].min() - vertSpacings.leftGuard(d), 
00620                        cells[d].min() - 1);
00621     }
00622     // Compute pointer offsets used with LField::iterator below:
00623     // Treat all as Reflective BC (see Cartesian for comparison); for
00624     // uniform cartesian mesh, all mesh BC's equivalent for this purpose:
00625     if ( face & 1 ) {
00626       voffset = 2*cells[d].max() + 1 - 1;
00627     } else {
00628       voffset = 2*cells[d].min() - 1 + 1;
00629     }   
00630 
00631     // +++++++++++++++vertSpacings++++++++++++++
00632     for (vfill_i=vertSpacings.begin_if(); 
00633          vfill_i!=vertSpacings.end_if(); ++vfill_i)
00634       {
00635         // Cache some things we will use often below.
00636         // Pointer to the data for the current LField (right????):
00637         LField<T,Dim> &fill = *(*vfill_i).second;
00638         // NDIndex spanning all elements in the LField, including the guards:
00639         const NDIndex<Dim> &fill_alloc = fill.getAllocated();
00640         // If the previously-created boundary guard-layer NDIndex "cSlab" 
00641         // contains any of the elements in this LField (they will be guard
00642         // elements if it does), assign the values into them here by applying
00643         // the boundary condition:
00644         if ( vSlab.touches( fill_alloc ) )
00645           {
00646             // Find what it touches in this LField.
00647             NDIndex<Dim> dest = vSlab.intersect( fill_alloc );
00648 
00649             // For exrapolation boundary conditions, the boundary guard-layer
00650             // elements are typically copied from interior values; the "src"
00651             // NDIndex specifies the interior elements to be copied into the
00652             // "dest" boundary guard-layer elements (possibly after some 
00653             // mathematical operations like multipplying by minus 1 later):
00654             NDIndex<Dim> src = dest; // Create dest equal to src
00655             // Now calculate the interior elements; the voffset variable 
00656             // computed above makes this right for "low" or "high" face cases:
00657             src[d] = voffset - src[d];
00658 
00659             // TJW: Why is there another loop over LField's here??????????
00660             // Loop over the ones that src touches.
00661             typename BareField<T,Dim>::iterator_if from_i;
00662             for (from_i=vertSpacings.begin_if(); 
00663                  from_i!=vertSpacings.end_if(); ++from_i)
00664               {
00665                 // Cache a few things.
00666                 LField<T,Dim> &from = *(*from_i).second;
00667                 const NDIndex<Dim> &from_owned = from.getOwned();
00668                 const NDIndex<Dim> &from_alloc = from.getAllocated();
00669                 // If src touches this LField...
00670                 if ( src.touches( from_owned ) )
00671                   {
00672                     NDIndex<Dim> from_it = src.intersect( from_alloc );
00673                     NDIndex<Dim> vfill_it = dest.plugBase( from_it );
00674                     // Build iterators for the copy...
00675                     typedef typename LField<T,Dim>::iterator LFI;
00676                     LFI lhs = fill.begin(vfill_it);
00677                     LFI rhs = from.begin(from_it);
00678                     // And do the assignment (reflective BC hardwired):
00679                     BrickExpression<Dim,LFI,LFI,OpUMeshExtrapolate<T> >
00680                       (lhs,rhs,OpUMeshExtrapolate<T>(v0,v1)).apply();
00681                   }
00682               }
00683           }
00684       }
00685     
00686   }
00687 
00688   // For uniform cartesian mesh, cell-cell spacings are identical to
00689   // vert-vert spacings:
00690   //12/8/98  CellSpacings = VertSpacings;
00691   // Added 12/8/98 --TJW:
00692   BareField<Vektor<MFLOAT,Dim>,Dim>& cellSpacings = *CellSpacings;
00693   cellSpacings = vertexSpacing;
00694   
00695   hasSpacingFields = true; // Flag this as having been done to this object.
00696 }
00697 
00698 // These specify both the total number of vnodes and the numbers of vnodes
00699 // along each dimension for the partitioning of the index space. Obviously
00700 // this restricts the number of vnodes to be a product of the numbers along
00701 // each dimension (the constructor implementation checks this): Special
00702 // cases for 1-3 dimensions, ala FieldLayout ctors (see FieldLayout.h for
00703 // more relevant comments, including definition of recurse):
00704 
00705 // 1D
00706 template<unsigned Dim, class MFLOAT>
00707 void UniformCartesian<Dim,MFLOAT>::
00708 storeSpacingFields(e_dim_tag p1,
00709                         unsigned vnodes1,
00710                         bool recurse,
00711                         int vnodes) {
00712   e_dim_tag et[1];
00713   et[0] = p1;
00714   unsigned vnodesPerDirection[Dim];
00715   vnodesPerDirection[0] = vnodes1;
00716   storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
00717 }
00718 // 2D
00719 template<unsigned Dim, class MFLOAT>
00720 void UniformCartesian<Dim,MFLOAT>::
00721 storeSpacingFields(e_dim_tag p1, e_dim_tag p2,
00722                         unsigned vnodes1, unsigned vnodes2,
00723                         bool recurse,int vnodes) {
00724   e_dim_tag et[2];
00725   et[0] = p1;
00726   et[1] = p2;
00727   unsigned vnodesPerDirection[Dim];
00728   vnodesPerDirection[0] = vnodes1;
00729   vnodesPerDirection[1] = vnodes2;
00730   storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
00731 }
00732 // 3D
00733 template<unsigned Dim, class MFLOAT>
00734 void UniformCartesian<Dim,MFLOAT>::
00735 storeSpacingFields(e_dim_tag p1, e_dim_tag p2, e_dim_tag p3,
00736                         unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
00737                         bool recurse, int vnodes) {
00738   e_dim_tag et[3];
00739   et[0] = p1;
00740   et[1] = p2;
00741   et[2] = p3;
00742   unsigned vnodesPerDirection[Dim];
00743   vnodesPerDirection[0] = vnodes1;
00744   vnodesPerDirection[1] = vnodes2;
00745   vnodesPerDirection[2] = vnodes3;
00746   storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
00747 }
00748 
00749 // TJW: Note: should clean up here eventually, and put redundant code from
00750 // this and the other general storeSpacingFields() implementation into one
00751 // function. Need to check this in quickly for Blanca right now --12/8/98
00752 // The general storeSpacingfields() function; others invoke this internally:
00753 template<unsigned Dim, class MFLOAT>
00754 void UniformCartesian<Dim,MFLOAT>::
00755 storeSpacingFields(e_dim_tag *p, 
00756                    unsigned* vnodesPerDirection, 
00757                    bool recurse, int vnodes)
00758 {
00759   // VERTEX-VERTEX SPACINGS (same as CELL-CELL SPACINGS for uniform):
00760   NDIndex<Dim> cells, verts;
00761   int d;
00762   for (d=0; d<Dim; d++) {
00763     cells[d] = Index(gridSizes[d]-1);
00764     verts[d] = Index(gridSizes[d]);
00765   }
00766   if (!hasSpacingFields) {
00767     // allocate layout and spacing field
00768     FlCell = 
00769       new FieldLayout<Dim>(cells, p, vnodesPerDirection, recurse, vnodes);
00770     // Note: enough guard cells only for existing Div(), etc. implementations:
00771     // (not really used by Div() etc for UniformCartesian); someday should make
00772     // this user-settable.
00773     VertSpacings = 
00774       new BareField<Vektor<MFLOAT,Dim>,Dim>(*FlCell,GuardCellSizes<Dim>(1));
00775     // Added 12/8/98 --TJW:
00776     FlVert = 
00777       new FieldLayout<Dim>(verts, p, vnodesPerDirection, recurse, vnodes);
00778     // Note: enough guard cells only for existing Div(), etc. implementations:
00779     CellSpacings = 
00780       new BareField<Vektor<MFLOAT,Dim>,Dim>(*FlVert,GuardCellSizes<Dim>(1));
00781   }
00782   BareField<Vektor<MFLOAT,Dim>,Dim>& vertSpacings = *VertSpacings;
00783   Vektor<MFLOAT,Dim> vertexSpacing;
00784   for (d=0; d<Dim; d++) 
00785     vertexSpacing[d] = meshSpacing[d];
00786   vertSpacings = vertexSpacing;
00787   //-------------------------------------------------
00788   // Now the hard part, filling in the guard cells:
00789   //-------------------------------------------------
00790   // The easy part of the hard part is filling so that all the internal
00791   // guard layers are right:
00792   vertSpacings.fillGuardCells();
00793   // The hard part of the hard part is filling the external guard layers,
00794   // using the mesh BC to figure out how:
00795   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00796   // Temporaries used in loop over faces
00797   Vektor<MFLOAT,Dim> v0,v1; v0 = 0.0; v1 = 1.0; // Used for Reflective mesh BC
00798   int face;
00799   typedef Vektor<MFLOAT,Dim> T;          // Used multipple places in loop below
00800   typename BareField<T,Dim>::iterator_if vfill_i; // Iterator used below
00801   int voffset;             // Pointer offsets used with LField::iterator below
00802   // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
00803   for (face=0; face < 2*Dim; face++) {
00804     // NDIndex's spanning elements and guard elements:
00805     NDIndex<Dim> vSlab = AddGuardCells(cells,vertSpacings.getGuardCellSizes());
00806     // Shrink it down to be the guards along the active face:
00807     d = face/2;
00808     // The following bitwise AND logical test returns true if face is odd
00809     // (meaning the "high" or "right" face in the numbering convention) and 
00810     // returns false if face is even (meaning the "low" or "left" face in 
00811     // the numbering convention):
00812     if ( face & 1 ) {
00813       vSlab[d] = Index(cells[d].max() + 1, 
00814                        cells[d].max() + vertSpacings.rightGuard(d));
00815     } else {
00816       vSlab[d] = Index(cells[d].min() - vertSpacings.leftGuard(d), 
00817                        cells[d].min() - 1);
00818     }
00819     // Compute pointer offsets used with LField::iterator below:
00820     // Treat all as Reflective BC (see Cartesian for comparison); for
00821     // uniform cartesian mesh, all mesh BC's equivalent for this purpose:
00822     if ( face & 1 ) {
00823       voffset = 2*cells[d].max() + 1 - 1;
00824     } else {
00825       voffset = 2*cells[d].min() - 1 + 1;
00826     }   
00827 
00828     // +++++++++++++++vertSpacings++++++++++++++
00829     for (vfill_i=vertSpacings.begin_if(); 
00830          vfill_i!=vertSpacings.end_if(); ++vfill_i)
00831       {
00832         // Cache some things we will use often below.
00833         // Pointer to the data for the current LField (right????):
00834         LField<T,Dim> &fill = *(*vfill_i).second;
00835         // NDIndex spanning all elements in the LField, including the guards:
00836         const NDIndex<Dim> &fill_alloc = fill.getAllocated();
00837         // If the previously-created boundary guard-layer NDIndex "cSlab" 
00838         // contains any of the elements in this LField (they will be guard
00839         // elements if it does), assign the values into them here by applying
00840         // the boundary condition:
00841         if ( vSlab.touches( fill_alloc ) )
00842           {
00843             // Find what it touches in this LField.
00844             NDIndex<Dim> dest = vSlab.intersect( fill_alloc );
00845 
00846             // For exrapolation boundary conditions, the boundary guard-layer
00847             // elements are typically copied from interior values; the "src"
00848             // NDIndex specifies the interior elements to be copied into the
00849             // "dest" boundary guard-layer elements (possibly after some 
00850             // mathematical operations like multipplying by minus 1 later):
00851             NDIndex<Dim> src = dest; // Create dest equal to src
00852             // Now calculate the interior elements; the voffset variable 
00853             // computed above makes this right for "low" or "high" face cases:
00854             src[d] = voffset - src[d];
00855 
00856             // TJW: Why is there another loop over LField's here??????????
00857             // Loop over the ones that src touches.
00858             typename BareField<T,Dim>::iterator_if from_i;
00859             for (from_i=vertSpacings.begin_if(); 
00860                  from_i!=vertSpacings.end_if(); ++from_i)
00861               {
00862                 // Cache a few things.
00863                 LField<T,Dim> &from = *(*from_i).second;
00864                 const NDIndex<Dim> &from_owned = from.getOwned();
00865                 const NDIndex<Dim> &from_alloc = from.getAllocated();
00866                 // If src touches this LField...
00867                 if ( src.touches( from_owned ) )
00868                   {
00869                     NDIndex<Dim> from_it = src.intersect( from_alloc );
00870                     NDIndex<Dim> vfill_it = dest.plugBase( from_it );
00871                     // Build iterators for the copy...
00872                     typedef typename LField<T,Dim>::iterator LFI;
00873                     LFI lhs = fill.begin(vfill_it);
00874                     LFI rhs = from.begin(from_it);
00875                     // And do the assignment (reflective BC hardwired):
00876                     BrickExpression<Dim,LFI,LFI,OpUMeshExtrapolate<T> >
00877                       (lhs,rhs,OpUMeshExtrapolate<T>(v0,v1)).apply();
00878                   }
00879               }
00880           }
00881       }
00882     
00883   }
00884 
00885   // For uniform cartesian mesh, cell-cell spacings are identical to
00886   // vert-vert spacings:
00887   //12/8/98  CellSpacings = VertSpacings;
00888   // Added 12/8/98 --TJW:
00889   BareField<Vektor<MFLOAT,Dim>,Dim>& cellSpacings = *CellSpacings;
00890   cellSpacings = vertexSpacing;
00891   
00892   hasSpacingFields = true; // Flag this as having been done to this object.
00893 }
00894 
00895 //-----------------------------------------------------------------------------
00896 // I/O:
00897 //-----------------------------------------------------------------------------
00898 // Formatted output of UniformCartesian object:
00899 template< unsigned Dim, class MFLOAT >
00900 void 
00901 UniformCartesian<Dim,MFLOAT>::
00902 print(ostream& out)
00903 {
00904   out << "======UniformCartesian<" << Dim << ",MFLOAT>==begin======" << endl;
00905   int d;
00906   for (d=0; d < Dim; d++) 
00907     out << "gridSizes[" << d << "] = " << gridSizes[d] << endl;
00908   out << "origin = " << origin << endl;
00909   for (d=0; d < Dim; d++) 
00910     out << "meshSpacing[" << d << "] = " << meshSpacing[d] << endl;
00911   for (d=0; d < (1<<Dim); d++) 
00912     out << "Dvc[" << d << "] = " << Dvc[d] << endl;
00913   out << "cell volume = " << volume << endl;
00914   out << "======UniformCartesian<" << Dim << ",MFLOAT>==end========" << endl;
00915 }
00916 
00917 //--------------------------------------------------------------------------
00918 // Various (UniformCartesian) mesh mechanisms:
00919 //--------------------------------------------------------------------------
00920 
00921 // Volume of single cell indexed by NDIndex:
00922 template <unsigned Dim, class MFLOAT>
00923 MFLOAT 
00924 UniformCartesian<Dim,MFLOAT>::
00925 getCellVolume(const NDIndex<Dim>& ndi) const
00926 {
00927   int d;
00928   for (d=0; d<Dim; d++) 
00929     if (ndi[d].length() != 1) 
00930       ERRORMSG("UniformCartesian::getCellVolume() error: arg is not a NDIndex" 
00931                << "specifying a single element" << endl);
00932   return volume;
00933 }
00934 // Field of volumes of all cells:
00935 template <unsigned Dim, class MFLOAT>
00936 Field<MFLOAT,Dim,UniformCartesian<Dim,MFLOAT>,Cell>&
00937 UniformCartesian<Dim,MFLOAT>::
00938 getCellVolumeField(Field<MFLOAT,Dim,UniformCartesian<Dim,MFLOAT>,Cell>& 
00939                    volumes) const
00940 {
00941   volumes = volume;
00942   return volumes;
00943 }
00944 // Volume of range of cells bounded by verticies specified by input NDIndex;
00945 template <unsigned Dim, class MFLOAT>
00946 MFLOAT
00947 UniformCartesian<Dim,MFLOAT>::
00948 getVertRangeVolume(const NDIndex<Dim>& ndi) const
00949 {
00950   // Get vertex positions of extremal cells:
00951   Vektor<MFLOAT,Dim> v0, v1;
00952   NDIndex<Dim> ndi0, ndi1;
00953   int d, i0, i1;
00954   for (d=0; d<Dim; d++) {
00955     i0 = ndi[d].first();
00956     i1 = ndi[d].last();
00957     ndi0[d] = Index(i0,i0,1); // Bounding vertex (from below)
00958     ndi1[d] = Index(i1,i1,1); // Bounding vertex (from above)
00959   }
00960   v0 = getVertexPosition(ndi0);
00961   v1 = getVertexPosition(ndi1);
00962   // Compute volume of rectangular solid beweeen these extremal vertices:
00963   MFLOAT volume = 1.0;
00964   for (d=0; d<Dim; d++) volume *= abs(v1(d) - v0(d));
00965   return volume;
00966 }
00967 // Volume of range of cells spanned by input NDIndex (index of cells):
00968 template <unsigned Dim, class MFLOAT>
00969 MFLOAT
00970 UniformCartesian<Dim,MFLOAT>::
00971 getCellRangeVolume(const NDIndex<Dim>& ndi) const
00972 {
00973   // Get vertex positions bounding extremal cells:
00974   Vektor<MFLOAT,Dim> v0, v1;
00975   NDIndex<Dim> ndi0, ndi1;
00976   int d, i0, i1;
00977   for (d=0; d<Dim; d++) {
00978     i0 = ndi[d].first();
00979     i1 = ndi[d].last() + 1;
00980     ndi0[d] = Index(i0,i0,1); // Bounding vertex (from below)
00981     ndi1[d] = Index(i1,i1,1); // Bounding vertex (from above)
00982   }
00983   v0 = getVertexPosition(ndi0);
00984   v1 = getVertexPosition(ndi1);
00985   // Compute volume of rectangular solid beweeen these extremal vertices:
00986   MFLOAT volume = 1.0;
00987   for (d=0; d<Dim; d++) volume *= abs(v1(d) - v0(d));
00988   return volume;
00989 }
00990 
00991 // Nearest vertex index to (x,y,z):
00992 template <unsigned Dim, class MFLOAT>
00993 NDIndex<Dim> 
00994 UniformCartesian<Dim,MFLOAT>::
00995 getNearestVertex(const Vektor<MFLOAT,Dim>& x) const
00996 {
00997   // Find coordinate vectors of the vertices just above and just below the 
00998   // input point (extremal vertices on cell containing point):
00999   NDIndex<Dim> ndi;
01000   int d, i;
01001   for (d=0; d<Dim; d++) {
01002     i = (int)((x(d) - origin(d))/meshSpacing[d] + 0.5);
01003     if (x(d) >= origin(d))
01004       ndi[d] = Index(i,i);
01005     else
01006       ndi[d] = Index(i-1,i-1);
01007   }
01008   return ndi;
01009 }
01010 // Nearest vertex index with all vertex coordinates below (x,y,z):
01011 template <unsigned Dim, class MFLOAT>
01012 NDIndex<Dim>
01013 UniformCartesian<Dim,MFLOAT>::
01014 getVertexBelow(const Vektor<MFLOAT,Dim>& x) const
01015 {
01016   // Find coordinate vectors of the vertices just above and just below the 
01017   // input point (extremal vertices on cell containing point):
01018   NDIndex<Dim> ndi;
01019   int d, i;
01020   for (d=0; d<Dim; d++) {
01021     i = (int)((x(d) - origin(d))/meshSpacing[d]);
01022     if (x(d) >= origin(d))
01023       ndi[d] = Index(i,i);
01024     else
01025       ndi[d] = Index(i-1,i-1);
01026   }
01027   return ndi;
01028 }
01029 // (x,y,z) coordinates of indexed vertex:
01030 template <unsigned Dim, class MFLOAT>
01031 Vektor<MFLOAT,Dim> 
01032 UniformCartesian<Dim,MFLOAT>::
01033 getVertexPosition(const NDIndex<Dim>& ndi) const
01034 {
01035   int d;
01036   for (d=0; d<Dim; d++) {
01037     if (ndi[d].length() != 1) 
01038       ERRORMSG("UniformCartesian::getVertexPosition() error: arg is not a"
01039                << " NDIndex specifying a single element" << endl);
01040   }
01041   // N.B.: following may need modification to be right for periodic Mesh BC:
01042   Vektor<MFLOAT,Dim> vertexPosition;
01043   for (d=0; d<Dim; d++) 
01044     vertexPosition(d) = ndi[d].first()*meshSpacing[d] + origin(d);
01045   return vertexPosition;
01046 }
01047 // Field of (x,y,z) coordinates of all vertices:
01048 template <unsigned Dim, class MFLOAT>
01049 Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Vert>& 
01050 UniformCartesian<Dim,MFLOAT>::
01051 getVertexPositionField(Field<Vektor<MFLOAT,Dim>,Dim,
01052   UniformCartesian<Dim,MFLOAT>,Vert>& vertexPositions) const
01053 {
01054   int d;
01055   int currentLocation[Dim];
01056   Vektor<MFLOAT,Dim> vertexPosition;
01057   vertexPositions.Uncompress();  // uncompress field before entering values!
01058   typename Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Vert>::iterator fi,
01059     fi_end = vertexPositions.end();
01060   for (fi = vertexPositions.begin(); fi != fi_end; ++fi) {
01061     fi.GetCurrentLocation(currentLocation);
01062     for (d=0; d<Dim; d++)
01063       vertexPosition(d) = origin(d) + currentLocation[d]*meshSpacing[d];
01064     *fi = vertexPosition;
01065   }
01066   return vertexPositions;
01067 }
01068 
01069 // (x,y,z) coordinates of indexed cell:
01070 template <unsigned Dim, class MFLOAT>
01071 Vektor<MFLOAT,Dim> 
01072 UniformCartesian<Dim,MFLOAT>::
01073 getCellPosition(const NDIndex<Dim>& ndi) const
01074 {
01075   int d;
01076   for (d=0; d<Dim; d++) {
01077     if (ndi[d].length() != 1) 
01078       ERRORMSG("UniformCartesian::getCellPosition() error: arg is not a"
01079                << " NDIndex specifying a single element" << endl);
01080   }
01081   // N.B.: following may need modification to be right for periodic Mesh BC:
01082   Vektor<MFLOAT,Dim> cellPosition;
01083   for (d=0; d<Dim; d++) 
01084     cellPosition(d) = (ndi[d].first()+0.5)*meshSpacing[d] + origin(d);
01085   return cellPosition;
01086 }
01087 // Field of (x,y,z) coordinates of all cells:
01088 template <unsigned Dim, class MFLOAT>
01089 Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Cell>& 
01090 UniformCartesian<Dim,MFLOAT>::
01091 getCellPositionField(Field<Vektor<MFLOAT,Dim>,Dim,
01092   UniformCartesian<Dim,MFLOAT>,Cell>& cellPositions) const
01093 {
01094   int d;
01095   int currentLocation[Dim];
01096   Vektor<MFLOAT,Dim> cellPosition;
01097   cellPositions.Uncompress();  // uncompress field before entering values!
01098   typename Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Cell>::iterator fi,
01099     fi_end = cellPositions.end();
01100   for (fi = cellPositions.begin(); fi != fi_end; ++fi) {
01101     fi.GetCurrentLocation(currentLocation);
01102     for (d=0; d<Dim; d++)
01103       cellPosition(d) = origin(d) + (currentLocation[d]+0.5)*meshSpacing[d];
01104     *fi = cellPosition;
01105   }
01106   return cellPositions;
01107 }
01108 
01109 // Vertex-vertex grid spacing of indexed cell:
01110 template <unsigned Dim, class MFLOAT>
01111 Vektor<MFLOAT,Dim>
01112 UniformCartesian<Dim,MFLOAT>::
01113 getDeltaVertex(const NDIndex<Dim>& ndi) const
01114 {
01115   // bfh: updated to compute interval for a whole index range
01116   Vektor<MFLOAT,Dim> vertexVertexSpacing;
01117   for (int d=0; d<Dim; d++)
01118     vertexVertexSpacing[d] = meshSpacing[d] * ndi[d].length();
01119   return vertexVertexSpacing;
01120 }
01121 
01122 // Field of vertex-vertex grid spacings of all cells:
01123 template <unsigned Dim, class MFLOAT>
01124 Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Cell>&
01125 UniformCartesian<Dim,MFLOAT>::
01126 getDeltaVertexField(Field<Vektor<MFLOAT,Dim>,Dim,
01127                     UniformCartesian<Dim,MFLOAT>,Cell>& vertexSpacings) const
01128 {
01129   Vektor<MFLOAT,Dim> vertexVertexSpacing;
01130   int d;
01131   for (d=0; d<Dim; d++) vertexVertexSpacing(d) = meshSpacing[d];
01132   vertexSpacings = vertexVertexSpacing;
01133   return vertexSpacings;
01134 }
01135 
01136 // Cell-cell grid spacing of indexed vertex:
01137 template <unsigned Dim, class MFLOAT>
01138 Vektor<MFLOAT,Dim> 
01139 UniformCartesian<Dim,MFLOAT>::
01140 getDeltaCell(const NDIndex<Dim>& ndi) const
01141 {
01142   // bfh: updated to compute interval for a whole index range
01143   Vektor<MFLOAT,Dim> cellCellSpacing;
01144   for (int d=0; d<Dim; d++)
01145     cellCellSpacing[d] = meshSpacing[d] * ndi[d].length();
01146   return cellCellSpacing;
01147 }
01148 
01149 // Field of cell-cell grid spacings of all vertices:
01150 template <unsigned Dim, class MFLOAT>
01151 Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Vert>&
01152 UniformCartesian<Dim,MFLOAT>::
01153 getDeltaCellField(Field<Vektor<MFLOAT,Dim>,Dim,
01154                   UniformCartesian<Dim,MFLOAT>,Vert>& cellSpacings) const
01155 {
01156   Vektor<MFLOAT,Dim> cellCellSpacing;
01157   int d;
01158   for (d=0; d<Dim; d++) cellCellSpacing(d) = meshSpacing[d];
01159   cellSpacings = cellCellSpacing;
01160   return cellSpacings;
01161 }
01162 // Array of surface normals to cells adjoining indexed cell:
01163 template <unsigned Dim, class MFLOAT>
01164 Vektor<MFLOAT,Dim>* 
01165 UniformCartesian<Dim,MFLOAT>::
01166 getSurfaceNormals(const NDIndex<Dim>& ndi) const
01167 {
01168   Vektor<MFLOAT,Dim>* surfaceNormals = new Vektor<MFLOAT,Dim>[2*Dim];
01169   int d, i;
01170   for (d=0; d<Dim; d++) {
01171     for (i=0; i<Dim; i++) {
01172       surfaceNormals[2*d](i)   = 0.0;
01173       surfaceNormals[2*d+1](i) = 0.0;
01174     }
01175     surfaceNormals[2*d](d)   = -1.0;
01176     surfaceNormals[2*d+1](d) =  1.0;
01177   }
01178   return surfaceNormals;
01179 }
01180 // Array of (pointers to) Fields of surface normals to all cells:
01181 template <unsigned Dim, class MFLOAT>
01182 void
01183 UniformCartesian<Dim,MFLOAT>::
01184 getSurfaceNormalFields(Field<Vektor<MFLOAT,Dim>, Dim,
01185                        UniformCartesian<Dim,MFLOAT>,Cell>** 
01186                        surfaceNormalsFields ) const
01187 {
01188   Vektor<MFLOAT,Dim>* surfaceNormals = new Vektor<MFLOAT,Dim>[2*Dim];
01189   int d, i;
01190   for (d=0; d<Dim; d++) {
01191     for (i=0; i<Dim; i++) {
01192       surfaceNormals[2*d](i)   = 0.0;
01193       surfaceNormals[2*d+1](i) = 0.0;
01194     }
01195     surfaceNormals[2*d](d)   = -1.0;
01196     surfaceNormals[2*d+1](d) =  1.0;
01197   }
01198   for (d=0; d<2*Dim; d++) assign((*(surfaceNormalsFields[d])), 
01199                                  surfaceNormals[d]);
01200   //  return surfaceNormalsFields;
01201 }
01202 // Similar functions, but specify the surface normal to a single face, using
01203 // the following numbering convention: 0 means low face of 1st dim, 1 means
01204 // high face of 1st dim, 2 means low face of 2nd dim, 3 means high face of 
01205 // 2nd dim, and so on:
01206 // Surface normal to face on indexed cell:
01207 template <unsigned Dim, class MFLOAT>
01208 Vektor<MFLOAT,Dim>
01209 UniformCartesian<Dim,MFLOAT>::
01210 getSurfaceNormal(const NDIndex<Dim>& ndi, unsigned face) const
01211 {
01212   Vektor<MFLOAT,Dim> surfaceNormal;
01213   unsigned int d;
01214   // The following bitwise AND logical test returns true if face is odd
01215   // (meaning the "high" or "right" face in the numbering convention) and 
01216   // returns false if face is even (meaning the "low" or "left" face in the
01217   // numbering convention):
01218   if ( face & 1 ) {
01219     for (d=0; d<Dim; d++) {
01220       if ((face/2) == d) {
01221         surfaceNormal(face) = -1.0;
01222       } else {
01223         surfaceNormal(face) =  0.0;
01224       }
01225     }
01226   } else {
01227     for (d=0; d<Dim; d++) {
01228       if ((face/2) == d) {
01229         surfaceNormal(face) =  1.0;
01230       } else {
01231         surfaceNormal(face) =  0.0;
01232       }
01233     }
01234   }
01235   return surfaceNormal;
01236 }
01237 // Field of surface normals to face on all cells:
01238 template <unsigned Dim, class MFLOAT>
01239 Field<Vektor<MFLOAT,Dim>,Dim,UniformCartesian<Dim,MFLOAT>,Cell>& 
01240 UniformCartesian<Dim,MFLOAT>::
01241 getSurfaceNormalField(Field<Vektor<MFLOAT,Dim>, Dim,
01242                       UniformCartesian<Dim,MFLOAT>,Cell>& surfaceNormalField,
01243                       unsigned face) const
01244 {
01245   Vektor<MFLOAT,Dim> surfaceNormal;
01246   unsigned int d;
01247   // The following bitwise AND logical test returns true if face is odd
01248   // (meaning the "high" or "right" face in the numbering convention) and 
01249   // returns false if face is even (meaning the "low" or "left" face in the
01250   // numbering convention):
01251   if ( face & 1 ) {
01252     for (d=0; d<Dim; d++) {
01253       if ((face/2) == d) {
01254         surfaceNormal(face) = -1.0;
01255       } else {
01256         surfaceNormal(face) =  0.0;
01257       }
01258     }
01259   } else {
01260     for (d=0; d<Dim; d++) {
01261       if ((face/2) == d) {
01262         surfaceNormal(face) =  1.0;
01263       } else {
01264         surfaceNormal(face) =  0.0;
01265       }
01266     }
01267   }
01268   surfaceNormalField = surfaceNormal;
01269   return surfaceNormalField;
01270 }
01271 
01272 
01273 //--------------------------------------------------------------------------
01274 // Global functions
01275 //--------------------------------------------------------------------------
01276 
01277 
01278 //*****************************************************************************
01279 // Stuff taken from old Cartesian.h, which now applies to UniformCartesian:
01280 //*****************************************************************************
01281 
01282 //----------------------------------------------------------------------
01283 // Divergence Vektor/Vert -> Scalar/Cell
01284 //----------------------------------------------------------------------
01285 template < class T, class MFLOAT >
01286 Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01287 Div(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01288     Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01289 {
01290   const NDIndex<1U>& domain = r.getDomain();
01291   Index I = domain[0];
01292 
01293   assign( r[I] , 
01294           dot(x[I  ], x.get_mesh().Dvc[0]) +
01295           dot(x[I+1], x.get_mesh().Dvc[1]));
01296   return r;
01297 }
01298 //----------------------------------------------------------------------
01299 template < class T, class MFLOAT >
01300 Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01301 Div(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01302     Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01303 {
01304   const NDIndex<2U>& domain = r.getDomain();
01305   Index I = domain[0];
01306   Index J = domain[1];
01307 
01308   assign( r[I][J] , 
01309           dot(x[I  ][J  ], x.get_mesh().Dvc[0]) +
01310           dot(x[I+1][J  ], x.get_mesh().Dvc[1]) +
01311           dot(x[I  ][J+1], x.get_mesh().Dvc[2]) +
01312           dot(x[I+1][J+1], x.get_mesh().Dvc[3]));
01313   return r;
01314 }
01315 //----------------------------------------------------------------------
01316 template < class T, class MFLOAT >
01317 Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01318 Div(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01319     Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01320 {
01321   const NDIndex<3U>& domain = r.getDomain();
01322   Index I = domain[0];
01323   Index J = domain[1];
01324   Index K = domain[2];
01325 
01326   assign( r[I][J][K] , 
01327           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[0]) +
01328           dot(x[I+1][J  ][K  ], x.get_mesh().Dvc[1]) +
01329           dot(x[I  ][J+1][K  ], x.get_mesh().Dvc[2]) +
01330           dot(x[I+1][J+1][K  ], x.get_mesh().Dvc[3]) +
01331           dot(x[I  ][J  ][K+1], x.get_mesh().Dvc[4]) +
01332           dot(x[I+1][J  ][K+1], x.get_mesh().Dvc[5]) +
01333           dot(x[I  ][J+1][K+1], x.get_mesh().Dvc[6]) +
01334           dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]));
01335   return r;
01336 }
01337 //----------------------------------------------------------------------
01338 // Divergence Vektor/Cell -> Scalar/Vert
01339 //----------------------------------------------------------------------
01340 template < class T, class MFLOAT >
01341 Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01342 Div(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01343     Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01344 {
01345   const NDIndex<1U>& domain = r.getDomain();
01346   Index I = domain[0];
01347 
01348   assign( r[I] , 
01349           dot(x[I-1], x.get_mesh().Dvc[0]) +
01350           dot(x[I  ], x.get_mesh().Dvc[1]));
01351   return r;
01352 }
01353 //----------------------------------------------------------------------
01354 // (tjw: the one in cv.cpp)
01355 template < class T, class MFLOAT >
01356 Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01357 Div(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01358     Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01359 {
01360   const NDIndex<2U>& domain = r.getDomain();
01361   Index I = domain[0];
01362   Index J = domain[1];
01363 
01364   assign( r[I][J] , 
01365           dot(x[I-1][J-1], x.get_mesh().Dvc[0]) +
01366           dot(x[I  ][J-1], x.get_mesh().Dvc[1]) +
01367           dot(x[I-1][J  ], x.get_mesh().Dvc[2]) +
01368           dot(x[I  ][J  ], x.get_mesh().Dvc[3]));
01369   return r;
01370 }
01371 //----------------------------------------------------------------------
01372 template < class T, class MFLOAT >
01373 Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01374 Div(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01375     Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01376 {
01377   const NDIndex<3U>& domain = r.getDomain();
01378   Index I = domain[0];
01379   Index J = domain[1];
01380   Index K = domain[2];
01381 
01382   assign( r[I][J][K] , 
01383           dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]) +
01384           dot(x[I  ][J-1][K-1], x.get_mesh().Dvc[1]) +
01385           dot(x[I-1][J  ][K-1], x.get_mesh().Dvc[2]) +
01386           dot(x[I  ][J  ][K-1], x.get_mesh().Dvc[3]) +
01387           dot(x[I-1][J-1][K  ], x.get_mesh().Dvc[4]) +
01388           dot(x[I  ][J-1][K  ], x.get_mesh().Dvc[5]) +
01389           dot(x[I-1][J  ][K  ], x.get_mesh().Dvc[6]) +
01390           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[7]));
01391   return r;
01392 }
01393 //----------------------------------------------------------------------
01394 // Divergence Vektor/Vert -> Scalar/Vert
01395 //----------------------------------------------------------------------
01396 template < class T, class MFLOAT >
01397 Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01398 Div(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01399     Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01400 {
01401   const NDIndex<1U>& domain = r.getDomain();
01402   Index I = domain[0];
01403   Vektor<T,1U> idx;
01404   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01405 
01406   assign( r[I] , dot( idx , (x[I+1] - x[I-1]) ) );
01407   return r;
01408 }
01409 //----------------------------------------------------------------------
01410 template < class T, class MFLOAT >
01411 Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01412 Div(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01413     Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01414 {
01415   const NDIndex<2U>& domain = r.getDomain();
01416   Index I = domain[0];
01417   Index J = domain[1];
01418   Vektor<T,2U> idx,idy;
01419   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01420   idx[1] = 0.0;
01421   idy[0] = 0.0;
01422   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01423 
01424   assign( r[I][J] , 
01425           dot( idx , (x[I+1][J  ] - x[I-1][J  ])) +
01426           dot( idy , (x[I  ][J+1] - x[I  ][J-1])) );
01427   return r;
01428 }
01429 //----------------------------------------------------------------------
01430 template < class T, class MFLOAT >
01431 Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01432 Div(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01433     Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01434 {
01435   const NDIndex<3U>& domain = r.getDomain();
01436   Index I = domain[0];
01437   Index J = domain[1];
01438   Index K = domain[2];
01439   Vektor<T,3U> idx,idy,idz;
01440   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01441   idx[1] = 0.0;
01442   idx[2] = 0.0;
01443   idy[0] = 0.0;
01444   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01445   idy[2] = 0.0;
01446   idz[0] = 0.0;
01447   idz[1] = 0.0;
01448   idz[2] = 0.5/x.get_mesh().get_meshSpacing(2);
01449 
01450   assign( r[I][J][K] , 
01451           dot(idx , (x[I+1][J  ][K  ] - x[I-1][J  ][K  ] )) +
01452           dot(idy , (x[I  ][J+1][K  ] - x[I  ][J-1][K  ] )) +
01453           dot(idz , (x[I  ][J  ][K+1] - x[I  ][J  ][K-1] )) );
01454   return r;
01455 }
01456 //----------------------------------------------------------------------
01457 // Divergence Vektor/Cell -> Scalar/Cell
01458 //----------------------------------------------------------------------
01459 template < class T, class MFLOAT >
01460 Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01461 Div(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01462     Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01463 {
01464   const NDIndex<1U>& domain = r.getDomain();
01465   Index I = domain[0];
01466   Vektor<T,1U> idx;
01467   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01468 
01469   assign( r[I] , dot( idx , (x[I+1] - x[I-1]) ) );
01470   return r;
01471 }
01472 //----------------------------------------------------------------------
01473 template < class T, class MFLOAT >
01474 Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01475 Div(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01476     Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01477 {
01478   const NDIndex<2U>& domain = r.getDomain();
01479   Index I = domain[0];
01480   Index J = domain[1];
01481   Vektor<T,2U> idx,idy;
01482   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01483   idx[1] = 0.0;
01484   idy[0] = 0.0;
01485   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01486 
01487   assign( r[I][J] , 
01488           dot( idx , (x[I+1][J  ] - x[I-1][J  ])) +
01489           dot( idy , (x[I  ][J+1] - x[I  ][J-1])) );
01490   return r;
01491 }
01492 //----------------------------------------------------------------------
01493 template < class T, class MFLOAT >
01494 Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01495 Div(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01496     Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01497 {
01498   const NDIndex<3U>& domain = r.getDomain();
01499   Index I = domain[0];
01500   Index J = domain[1];
01501   Index K = domain[2];
01502   Vektor<T,3U> idx,idy,idz;
01503   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01504   idx[1] = 0.0;
01505   idx[2] = 0.0;
01506   idy[0] = 0.0;
01507   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01508   idy[2] = 0.0;
01509   idz[0] = 0.0;
01510   idz[1] = 0.0;
01511   idz[2] = 0.5/x.get_mesh().get_meshSpacing(2);
01512 
01513   assign( r[I][J][K] , 
01514           dot(idx , (x[I+1][J  ][K  ] - x[I-1][J  ][K  ] )) +
01515           dot(idy , (x[I  ][J+1][K  ] - x[I  ][J-1][K  ] )) +
01516           dot(idz , (x[I  ][J  ][K+1] - x[I  ][J  ][K-1] )) );
01517   return r;
01518 }
01519 //----------------------------------------------------------------------
01520 // Divergence Tenzor/Vert -> Vektor/Cell
01521 //----------------------------------------------------------------------
01522 template < class T, class MFLOAT >
01523 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01524 Div(Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01525     Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01526 {
01527   const NDIndex<1U>& domain = r.getDomain();
01528   Index I = domain[0];
01529 
01530   assign( r[I] , 
01531           dot(x[I  ], x.get_mesh().Dvc[0]) +
01532           dot(x[I+1], x.get_mesh().Dvc[1]));
01533   return r;
01534 }
01535 //----------------------------------------------------------------------
01536 template < class T, class MFLOAT >
01537 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01538 Div(Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01539     Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01540 {
01541   const NDIndex<2U>& domain = r.getDomain();
01542   Index I = domain[0];
01543   Index J = domain[1];
01544 
01545   assign( r[I][J] , 
01546           dot(x[I  ][J  ], x.get_mesh().Dvc[0]) +
01547           dot(x[I+1][J  ], x.get_mesh().Dvc[1]) +
01548           dot(x[I  ][J+1], x.get_mesh().Dvc[2]) +
01549           dot(x[I+1][J+1], x.get_mesh().Dvc[3]));
01550 
01551   return r;
01552 }
01553 //----------------------------------------------------------------------
01554 template < class T, class MFLOAT >
01555 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01556 Div(Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01557     Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01558 {
01559   const NDIndex<3U>& domain = r.getDomain();
01560   Index I = domain[0];
01561   Index J = domain[1];
01562   Index K = domain[2];
01563 
01564   assign( r[I][J][K] , 
01565           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[0]) +
01566           dot(x[I+1][J  ][K  ], x.get_mesh().Dvc[1]) +
01567           dot(x[I  ][J+1][K  ], x.get_mesh().Dvc[2]) +
01568           dot(x[I+1][J+1][K  ], x.get_mesh().Dvc[3]) +
01569           dot(x[I  ][J  ][K+1], x.get_mesh().Dvc[4]) +
01570           dot(x[I+1][J  ][K+1], x.get_mesh().Dvc[5]) +
01571           dot(x[I  ][J+1][K+1], x.get_mesh().Dvc[6]) +
01572           dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]));
01573 
01574   return r;
01575 }
01576 //----------------------------------------------------------------------
01577 // Divergence SymTenzor/Vert -> Vektor/Cell
01578 //----------------------------------------------------------------------
01579 template < class T, class MFLOAT >
01580 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01581 Div(Field<SymTenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01582     Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01583 {
01584   const NDIndex<1U>& domain = r.getDomain();
01585   Index I = domain[0];
01586 
01587   assign( r[I] , 
01588           dot(x[I  ], x.get_mesh().Dvc[0]) +
01589           dot(x[I+1], x.get_mesh().Dvc[1]));
01590   return r;
01591 }
01592 //----------------------------------------------------------------------
01593 template < class T, class MFLOAT >
01594 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01595 Div(Field<SymTenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01596     Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01597 {
01598   const NDIndex<2U>& domain = r.getDomain();
01599   Index I = domain[0];
01600   Index J = domain[1];
01601 
01602   assign( r[I][J] , 
01603           dot(x[I  ][J  ], x.get_mesh().Dvc[0]) +
01604           dot(x[I+1][J  ], x.get_mesh().Dvc[1]) +
01605           dot(x[I  ][J+1], x.get_mesh().Dvc[2]) +
01606           dot(x[I+1][J+1], x.get_mesh().Dvc[3]));
01607   return r;
01608 }
01609 //----------------------------------------------------------------------
01610 template < class T, class MFLOAT >
01611 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01612 Div(Field<SymTenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01613     Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01614 {
01615   const NDIndex<3U>& domain = r.getDomain();
01616   Index I = domain[0];
01617   Index J = domain[1];
01618   Index K = domain[2];
01619 
01620   assign( r[I][J][K] , 
01621           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[0]) +
01622           dot(x[I+1][J  ][K  ], x.get_mesh().Dvc[1]) +
01623           dot(x[I  ][J+1][K  ], x.get_mesh().Dvc[2]) +
01624           dot(x[I+1][J+1][K  ], x.get_mesh().Dvc[3]) +
01625           dot(x[I  ][J  ][K+1], x.get_mesh().Dvc[4]) +
01626           dot(x[I+1][J  ][K+1], x.get_mesh().Dvc[5]) +
01627           dot(x[I  ][J+1][K+1], x.get_mesh().Dvc[6]) +
01628           dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]));
01629   return r;
01630 }
01631 
01632 //----------------------------------------------------------------------
01633 // Divergence Tenzor/Cell -> Vektor/Vert
01634 //----------------------------------------------------------------------
01635 template < class T, class MFLOAT >
01636 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01637 Div(Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01638     Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01639 {
01640   const NDIndex<1U>& domain = r.getDomain();
01641   Index I = domain[0];
01642 
01643   assign( r[I] , 
01644           dot(x[I-1], x.get_mesh().Dvc[0]) +
01645           dot(x[I  ], x.get_mesh().Dvc[1]));
01646   return r;
01647 }
01648 //----------------------------------------------------------------------
01649 template < class T, class MFLOAT >
01650 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01651 Div(Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01652     Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01653 {
01654   const NDIndex<2U>& domain = r.getDomain();
01655   Index I = domain[0];
01656   Index J = domain[1];
01657 
01658   assign( r[I][J] , 
01659           dot(x[I-1][J-1], x.get_mesh().Dvc[0]) +
01660           dot(x[I  ][J-1], x.get_mesh().Dvc[1]) +
01661           dot(x[I-1][J  ], x.get_mesh().Dvc[2]) +
01662           dot(x[I  ][J  ], x.get_mesh().Dvc[3]));
01663   return r;
01664 }
01665 //----------------------------------------------------------------------
01666 template < class T, class MFLOAT >
01667 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01668 Div(Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01669     Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01670 {
01671   const NDIndex<3U>& domain = r.getDomain();
01672   Index I = domain[0];
01673   Index J = domain[1];
01674   Index K = domain[2];
01675 
01676   assign( r[I][J][K] , 
01677           dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]) +
01678           dot(x[I  ][J-1][K-1], x.get_mesh().Dvc[1]) +
01679           dot(x[I-1][J  ][K-1], x.get_mesh().Dvc[2]) +
01680           dot(x[I  ][J  ][K-1], x.get_mesh().Dvc[3]) +
01681           dot(x[I-1][J-1][K  ], x.get_mesh().Dvc[4]) +
01682           dot(x[I  ][J-1][K  ], x.get_mesh().Dvc[5]) +
01683           dot(x[I-1][J  ][K  ], x.get_mesh().Dvc[6]) +
01684           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[7]));
01685   return r;
01686 }
01687 
01688 //----------------------------------------------------------------------
01689 // Divergence SymTenzor/Cell -> Vektor/Vert
01690 //----------------------------------------------------------------------
01691 template < class T, class MFLOAT >
01692 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01693 Div(Field<SymTenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01694     Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01695 {
01696   const NDIndex<1U>& domain = r.getDomain();
01697   Index I = domain[0];
01698 
01699   assign( r[I] , 
01700           dot(x[I-1], x.get_mesh().Dvc[0]) +
01701           dot(x[I  ], x.get_mesh().Dvc[1]));
01702   return r;
01703 }
01704 //----------------------------------------------------------------------
01705 template < class T, class MFLOAT >
01706 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01707 Div(Field<SymTenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01708     Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01709 {
01710   const NDIndex<2U>& domain = r.getDomain();
01711   Index I = domain[0];
01712   Index J = domain[1];
01713 
01714   assign( r[I][J] , 
01715           dot(x[I-1][J-1], x.get_mesh().Dvc[0]) +
01716           dot(x[I  ][J-1], x.get_mesh().Dvc[1]) +
01717           dot(x[I-1][J  ], x.get_mesh().Dvc[2]) +
01718           dot(x[I  ][J  ], x.get_mesh().Dvc[3]));
01719   return r;
01720 }
01721 //----------------------------------------------------------------------
01722 template < class T, class MFLOAT >
01723 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01724 Div(Field<SymTenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01725     Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01726 {
01727   const NDIndex<3U>& domain = r.getDomain();
01728   Index I = domain[0];
01729   Index J = domain[1];
01730   Index K = domain[2];
01731 
01732   assign( r[I][J][K] , 
01733           dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]) +
01734           dot(x[I  ][J-1][K-1], x.get_mesh().Dvc[1]) +
01735           dot(x[I-1][J  ][K-1], x.get_mesh().Dvc[2]) +
01736           dot(x[I  ][J  ][K-1], x.get_mesh().Dvc[3]) +
01737           dot(x[I-1][J-1][K  ], x.get_mesh().Dvc[4]) +
01738           dot(x[I  ][J-1][K  ], x.get_mesh().Dvc[5]) +
01739           dot(x[I-1][J  ][K  ], x.get_mesh().Dvc[6]) +
01740           dot(x[I  ][J  ][K  ], x.get_mesh().Dvc[7]));
01741   return r;
01742 }
01743 
01744 //----------------------------------------------------------------------
01745 // Grad Scalar/Vert -> Vektor/Cell
01746 //----------------------------------------------------------------------
01747 template < class T, class MFLOAT >
01748 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01749 Grad(Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01750      Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01751 {
01752   const NDIndex<1U>& domain = r.getDomain();
01753   Index I = domain[0];
01754 
01755   assign( r[I] , 
01756           x[I  ] * x.get_mesh().Dvc[0] +
01757           x[I+1] * x.get_mesh().Dvc[1]);
01758   return r;
01759 }
01760 //----------------------------------------------------------------------
01761 template < class T, class MFLOAT >
01762 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01763 Grad(Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01764      Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01765 {
01766   const NDIndex<2U>& domain = r.getDomain();
01767   Index I = domain[0];
01768   Index J = domain[1];
01769 
01770   assign( r[I][J] , 
01771           x[I  ][J  ] * x.get_mesh().Dvc[0] +
01772           x[I+1][J  ] * x.get_mesh().Dvc[1] +
01773           x[I  ][J+1] * x.get_mesh().Dvc[2] +
01774           x[I+1][J+1] * x.get_mesh().Dvc[3]);
01775   return r;
01776 }
01777 //----------------------------------------------------------------------
01778 template < class T, class MFLOAT >
01779 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01780 Grad(Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01781      Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01782 {
01783   const NDIndex<3U>& domain = r.getDomain();
01784   Index I = domain[0];
01785   Index J = domain[1];
01786   Index K = domain[2];
01787 
01788   assign( r[I][J][K] , 
01789           x[I  ][J  ][K  ] * x.get_mesh().Dvc[0] +
01790           x[I+1][J  ][K  ] * x.get_mesh().Dvc[1] +
01791           x[I  ][J+1][K  ] * x.get_mesh().Dvc[2] +
01792           x[I+1][J+1][K  ] * x.get_mesh().Dvc[3] +
01793           x[I  ][J  ][K+1] * x.get_mesh().Dvc[4] +
01794           x[I+1][J  ][K+1] * x.get_mesh().Dvc[5] +
01795           x[I  ][J+1][K+1] * x.get_mesh().Dvc[6] +
01796           x[I+1][J+1][K+1] * x.get_mesh().Dvc[7]);
01797 
01798   return r;
01799 }
01800 //----------------------------------------------------------------------
01801 // Grad Scalar/Cell -> Vektor/Vert
01802 //----------------------------------------------------------------------
01803 template < class T, class MFLOAT >
01804 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01805 Grad(Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01806      Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01807 {
01808   const NDIndex<1U>& domain = r.getDomain();
01809   Index I = domain[0];
01810 
01811   assign( r[I] ,
01812           x[I-1] * x.get_mesh().Dvc[0] +
01813           x[I  ] * x.get_mesh().Dvc[1]);
01814   return r;
01815 }
01816 //----------------------------------------------------------------------
01817 template < class T, class MFLOAT >
01818 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01819 Grad(Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01820      Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01821 {
01822   const NDIndex<2U>& domain = r.getDomain();
01823   Index I = domain[0];
01824   Index J = domain[1];
01825 
01826   assign( r[I][J] , 
01827           x[I-1][J-1] * x.get_mesh().Dvc[0] +
01828           x[I  ][J-1] * x.get_mesh().Dvc[1] +
01829           x[I-1][J  ] * x.get_mesh().Dvc[2] +
01830           x[I  ][J  ] * x.get_mesh().Dvc[3]);
01831   return r;
01832 }
01833 //----------------------------------------------------------------------
01834 template < class T, class MFLOAT >
01835 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01836 Grad(Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01837      Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01838 {
01839   const NDIndex<3U>& domain = r.getDomain();
01840   Index I = domain[0];
01841   Index J = domain[1];
01842   Index K = domain[2];
01843 
01844   assign( r[I][J][K] , 
01845           x[I-1][J-1][K-1] * x.get_mesh().Dvc[0] +
01846           x[I  ][J-1][K-1] * x.get_mesh().Dvc[1] +
01847           x[I-1][J  ][K-1] * x.get_mesh().Dvc[2] +
01848           x[I  ][J  ][K-1] * x.get_mesh().Dvc[3] +
01849           x[I-1][J-1][K  ] * x.get_mesh().Dvc[4] +
01850           x[I  ][J-1][K  ] * x.get_mesh().Dvc[5] +
01851           x[I-1][J  ][K  ] * x.get_mesh().Dvc[6] +
01852           x[I  ][J  ][K  ] * x.get_mesh().Dvc[7]);
01853   return r;
01854 }
01855 //----------------------------------------------------------------------
01856 // Grad Scalar/Vert -> Vektor/Vert
01857 //----------------------------------------------------------------------
01858 template < class T, class MFLOAT >
01859 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>&
01860 Grad(Field<T,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01861      Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
01862 {
01863   const NDIndex<1U>& domain = r.getDomain();
01864   Index I = domain[0];
01865 
01866   Vektor<T,1U> idx;
01867   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01868 
01869   assign( r[I] ,  idx * (x[I+1] - x[I-1] ) );
01870   return r;
01871 }
01872 //----------------------------------------------------------------------
01873 template < class T, class MFLOAT >
01874 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>&
01875 Grad(Field<T,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
01876      Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
01877 {
01878   const NDIndex<2U>& domain = r.getDomain();
01879   Index I = domain[0];
01880   Index J = domain[1];
01881 
01882   Vektor<T,2U> idx,idy;
01883   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01884   idx[1] = 0.0;
01885   idy[0] = 0.0;
01886   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01887 
01888   assign( r[I][J] , 
01889           idx * (x[I+1][J  ] - x[I-1][J  ]) +
01890           idy * (x[I  ][J+1] - x[I  ][J-1]) );
01891   return r;
01892 }
01893 //----------------------------------------------------------------------
01894 template < class T, class MFLOAT >
01895 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>&
01896 Grad(Field<T,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
01897      Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
01898 {
01899   const NDIndex<3U>& domain = r.getDomain();
01900   Index I = domain[0];
01901   Index J = domain[1];
01902   Index K = domain[2];
01903 
01904   Vektor<T,3U> idx,idy,idz;
01905   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01906   idx[1] = 0.0;
01907   idx[2] = 0.0;
01908   idy[0] = 0.0;
01909   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01910   idy[2] = 0.0;
01911   idz[0] = 0.0;
01912   idz[1] = 0.0;
01913   idz[2] = 0.5/x.get_mesh().get_meshSpacing(2);
01914 
01915   assign(r[I][J][K] , 
01916          idx * (x[I+1][J  ][K  ] - x[I-1][J  ][K  ]) +
01917          idy * (x[I  ][J+1][K  ] - x[I  ][J-1][K  ]) +
01918          idz * (x[I  ][J  ][K+1] - x[I  ][J  ][K-1]));
01919   return r;
01920 }
01921 //----------------------------------------------------------------------
01922 // Grad Scalar/Cell -> Vektor/Cell
01923 //----------------------------------------------------------------------
01924 template < class T, class MFLOAT >
01925 Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01926 Grad(Field<T,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
01927      Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01928 {
01929   const NDIndex<1U>& domain = r.getDomain();
01930   Index I = domain[0];
01931 
01932   Vektor<T,1U> idx;
01933   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01934 
01935   assign( r[I] , idx * (x[I+1] - x[I-1] ) );
01936   return r;
01937 }
01938 //----------------------------------------------------------------------
01939 template < class T, class MFLOAT >
01940 Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>&
01941 Grad(Field<T,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
01942      Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
01943 {
01944   const NDIndex<2U>& domain = r.getDomain();
01945   Index I = domain[0];
01946   Index J = domain[1];
01947 
01948   Vektor<T,2U> idx,idy;
01949   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01950   idx[1] = 0.0;
01951   idy[0] = 0.0;
01952   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01953 
01954   assign( r[I][J] , 
01955           idx * (x[I+1][J  ] - x[I-1][J  ]) +
01956           idy * (x[I  ][J+1] - x[I  ][J-1]) );
01957 
01958   return r;
01959 }
01960 //----------------------------------------------------------------------
01961 template < class T, class MFLOAT >
01962 Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>&
01963 Grad(Field<T,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
01964      Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
01965 {
01966   const NDIndex<3U>& domain = r.getDomain();
01967   Index I = domain[0];
01968   Index J = domain[1];
01969   Index K = domain[2];
01970 
01971   Vektor<T,3U> idx,idy,idz;
01972   idx[0] = 0.5/x.get_mesh().get_meshSpacing(0);
01973   idx[1] = 0.0;
01974   idx[2] = 0.0;
01975   idy[0] = 0.0;
01976   idy[1] = 0.5/x.get_mesh().get_meshSpacing(1);
01977   idy[2] = 0.0;
01978   idz[0] = 0.0;
01979   idz[1] = 0.0;
01980   idz[2] = 0.5/x.get_mesh().get_meshSpacing(2);
01981 
01982   assign(r[I][J][K] , 
01983          idx * (x[I+1][J  ][K  ] - x[I-1][J  ][K  ]) +
01984          idy * (x[I  ][J+1][K  ] - x[I  ][J-1][K  ]) +
01985          idz * (x[I  ][J  ][K+1] - x[I  ][J  ][K-1]));
01986   return r;
01987 }
01988 //----------------------------------------------------------------------
01989 // Grad Vektor/Vert -> Tenzor/Cell
01990 //----------------------------------------------------------------------
01991 template < class T, class MFLOAT >
01992 Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>&
01993 Grad(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
01994      Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& r)
01995 {
01996   const NDIndex<1U>& domain = r.getDomain();
01997   Index I = domain[0];
01998 
01999   assign( r[I] , 
02000           outerProduct( x[I  ] , x.get_mesh().Dvc[0] ) +
02001           outerProduct( x[I+1] , x.get_mesh().Dvc[1])) ;
02002   return r;
02003 }
02004 //----------------------------------------------------------------------
02005 template < class T, class MFLOAT >
02006 Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>&
02007 Grad(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
02008      Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
02009 {
02010   const NDIndex<2U>& domain = r.getDomain();
02011   Index I = domain[0];
02012   Index J = domain[1];
02013 
02014   assign( r[I][J] , 
02015           outerProduct( x[I  ][J  ] , x.get_mesh().Dvc[0] ) +
02016           outerProduct( x[I+1][J  ] , x.get_mesh().Dvc[1] ) +
02017           outerProduct( x[I  ][J+1] , x.get_mesh().Dvc[2] ) +
02018           outerProduct( x[I+1][J+1] , x.get_mesh().Dvc[3] )) ;
02019   return r;
02020 }
02021 //----------------------------------------------------------------------
02022 template < class T, class MFLOAT >
02023 Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>&
02024 Grad(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
02025      Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
02026 {
02027   const NDIndex<3U>& domain = r.getDomain();
02028   Index I = domain[0];
02029   Index J = domain[1];
02030   Index K = domain[2];
02031 
02032   assign( r[I][J][K] , 
02033           outerProduct( x[I  ][J  ][K  ] , x.get_mesh().Dvc[0] ) +
02034           outerProduct( x[I+1][J  ][K  ] , x.get_mesh().Dvc[1] ) +
02035           outerProduct( x[I  ][J+1][K  ] , x.get_mesh().Dvc[2] ) +
02036           outerProduct( x[I+1][J+1][K  ] , x.get_mesh().Dvc[3] ) +
02037           outerProduct( x[I  ][J  ][K+1] , x.get_mesh().Dvc[4] ) +
02038           outerProduct( x[I+1][J  ][K+1] , x.get_mesh().Dvc[5] ) +
02039           outerProduct( x[I  ][J+1][K+1] , x.get_mesh().Dvc[6] ) +
02040           outerProduct( x[I+1][J+1][K+1] , x.get_mesh().Dvc[7] ));
02041 
02042   return r;
02043 }
02044 //----------------------------------------------------------------------
02045 // Grad Vektor/Cell -> Tenzor/Vert
02046 //----------------------------------------------------------------------
02047 template < class T, class MFLOAT >
02048 Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>&
02049 Grad(Field<Vektor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
02050      Field<Tenzor<T,1U>,1U,UniformCartesian<1U,MFLOAT>,Vert>& r)
02051 {
02052   const NDIndex<1U>& domain = r.getDomain();
02053   Index I = domain[0];
02054 
02055   assign( r[I] ,
02056           outerProduct( x[I-1] , x.get_mesh().Dvc[0] ) +
02057           outerProduct( x[I  ] , x.get_mesh().Dvc[1] ));
02058   return r;
02059 }
02060 //----------------------------------------------------------------------
02061 template < class T, class MFLOAT >
02062 Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>&
02063 Grad(Field<Vektor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
02064      Field<Tenzor<T,2U>,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
02065 {
02066   const NDIndex<2U>& domain = r.getDomain();
02067   Index I = domain[0];
02068   Index J = domain[1];
02069 
02070   assign( r[I][J] , 
02071           outerProduct( x[I-1][J-1] , x.get_mesh().Dvc[0] ) +
02072           outerProduct( x[I  ][J-1] , x.get_mesh().Dvc[1] ) +
02073           outerProduct( x[I-1][J  ] , x.get_mesh().Dvc[2] ) +
02074           outerProduct( x[I  ][J  ] , x.get_mesh().Dvc[3] ));
02075   return r;
02076 }
02077 //----------------------------------------------------------------------
02078 template < class T, class MFLOAT >
02079 Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>&
02080 Grad(Field<Vektor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
02081      Field<Tenzor<T,3U>,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
02082 {
02083   const NDIndex<3U>& domain = r.getDomain();
02084   Index I = domain[0];
02085   Index J = domain[1];
02086   Index K = domain[2];
02087 
02088   assign( r[I][J][K] , 
02089           outerProduct( x[I-1][J-1][K-1] , x.get_mesh().Dvc[0] ) +
02090           outerProduct( x[I  ][J-1][K-1] , x.get_mesh().Dvc[1] ) +
02091           outerProduct( x[I-1][J  ][K-1] , x.get_mesh().Dvc[2] ) +
02092           outerProduct( x[I  ][J  ][K-1] , x.get_mesh().Dvc[3] ) +
02093           outerProduct( x[I-1][J-1][K  ] , x.get_mesh().Dvc[4] ) +
02094           outerProduct( x[I  ][J-1][K  ] , x.get_mesh().Dvc[5] ) +
02095           outerProduct( x[I-1][J  ][K  ] , x.get_mesh().Dvc[6] ) +
02096           outerProduct( x[I  ][J  ][K  ] , x.get_mesh().Dvc[7] ));
02097   return r;
02098 }
02099 //----------------------------------------------------------------------
02100 // Weighted average Cell to Vert
02101 //----------------------------------------------------------------------
02102 template < class T1, class T2, class MFLOAT >
02103 Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>&
02104 Average(Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
02105         Field<T2,1U,UniformCartesian<1U,MFLOAT>,Cell>& w, 
02106         Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>& r) 
02107 {
02108   const NDIndex<1U>& domain = r.getDomain();
02109   Index I = domain[0];
02110   assign( r[I] , 
02111           ( x[I-1] * w[I-1] + x[I  ] * w[I  ] )/
02112           ( w[I-1] + w[I  ] ) );
02113   return r;
02114 }
02115 //----------------------------------------------------------------------
02116 template < class T1, class T2, class MFLOAT >
02117 Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>&
02118 Average(Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
02119         Field<T2,2U,UniformCartesian<2U,MFLOAT>,Cell>& w, 
02120         Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
02121 {
02122   const NDIndex<2U>& domain = r.getDomain();
02123   Index I = domain[0];
02124   Index J = domain[1];
02125 
02126   assign( r[I][J] , 
02127           ( x[I-1][J-1] * w[I-1][J-1] + 
02128             x[I  ][J-1] * w[I  ][J-1] +
02129             x[I-1][J  ] * w[I-1][J  ] +
02130             x[I  ][J  ] * w[I  ][J  ] )/
02131           ( w[I-1][J-1] + 
02132             w[I  ][J-1] +
02133             w[I-1][J  ] +
02134             w[I  ][J  ] ) );
02135   return r;
02136 }
02137 //----------------------------------------------------------------------
02138 template < class T1, class T2, class MFLOAT >
02139 Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>&
02140 Average(Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
02141         Field<T2,3U,UniformCartesian<3U,MFLOAT>,Cell>& w, 
02142         Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
02143 {
02144   const NDIndex<3U>& domain = r.getDomain();
02145   Index I = domain[0];
02146   Index J = domain[1];
02147   Index K = domain[2];
02148 
02149   assign( r[I][J][K] ,
02150           ( x[I-1][J-1][K-1] * w[I-1][J-1][K-1] + 
02151             x[I  ][J-1][K-1] * w[I  ][J-1][K-1] +
02152             x[I-1][J  ][K-1] * w[I-1][J  ][K-1] +
02153             x[I  ][J  ][K-1] * w[I  ][J  ][K-1] +
02154             x[I-1][J-1][K  ] * w[I-1][J-1][K  ] +
02155             x[I  ][J-1][K  ] * w[I  ][J-1][K  ] +
02156             x[I-1][J  ][K  ] * w[I-1][J  ][K  ] +
02157             x[I  ][J  ][K  ] * w[I  ][J  ][K  ] )/
02158           ( w[I-1][J-1][K-1] + 
02159             w[I  ][J-1][K-1] +
02160             w[I-1][J  ][K-1] +
02161             w[I  ][J  ][K-1] +
02162             w[I-1][J-1][K  ] +
02163             w[I  ][J-1][K  ] +
02164             w[I-1][J  ][K  ] +
02165             w[I  ][J  ][K  ] ) );
02166   return r;
02167 }
02168 //----------------------------------------------------------------------
02169 // Weighted average Vert to Cell 
02170 // N.B.: won't work except for unit-stride (& zero-base?) Field's.
02171 //----------------------------------------------------------------------
02172 template < class T1, class T2, class MFLOAT >
02173 Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>&
02174 Average(Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
02175         Field<T2,1U,UniformCartesian<1U,MFLOAT>,Vert>& w, 
02176         Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>& r) 
02177 {
02178   const NDIndex<1U>& domain = r.getDomain();
02179   Index I = domain[0];
02180   assign( r[I] , 
02181           ( x[I+1] * w[I+1] + x[I  ] * w[I  ] )/
02182           ( w[I+1] + w[I  ] ) );
02183   return r;
02184 }
02185 //----------------------------------------------------------------------
02186 template < class T1, class T2, class MFLOAT >
02187 Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>&
02188 Average(Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
02189         Field<T2,2U,UniformCartesian<2U,MFLOAT>,Vert>& w, 
02190         Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
02191 {
02192   const NDIndex<2U>& domain = r.getDomain();
02193   Index I = domain[0];
02194   Index J = domain[1];
02195 
02196   assign( r[I][J] , 
02197           ( x[I+1][J+1] * w[I+1][J+1] + 
02198             x[I  ][J+1] * w[I  ][J+1] +
02199             x[I+1][J  ] * w[I+1][J  ] +
02200             x[I  ][J  ] * w[I  ][J  ] )/
02201           ( w[I+1][J+1] + 
02202             w[I  ][J+1] +
02203             w[I+1][J  ] +
02204             w[I  ][J  ] ) );
02205   return r;
02206 }
02207 //----------------------------------------------------------------------
02208 template < class T1, class T2, class MFLOAT >
02209 Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>&
02210 Average(Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
02211         Field<T2,3U,UniformCartesian<3U,MFLOAT>,Vert>& w, 
02212         Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
02213 {
02214   const NDIndex<3U>& domain = r.getDomain();
02215   Index I = domain[0];
02216   Index J = domain[1];
02217   Index K = domain[2];
02218 
02219   assign( r[I][J][K] ,
02220           ( x[I+1][J+1][K+1] * w[I+1][J+1][K+1] + 
02221             x[I  ][J+1][K+1] * w[I  ][J+1][K+1] +
02222             x[I+1][J  ][K+1] * w[I+1][J  ][K+1] +
02223             x[I  ][J  ][K+1] * w[I  ][J  ][K+1] +
02224             x[I+1][J+1][K  ] * w[I+1][J+1][K  ] +
02225             x[I  ][J+1][K  ] * w[I  ][J+1][K  ] +
02226             x[I+1][J  ][K  ] * w[I+1][J  ][K  ] +
02227             x[I  ][J  ][K  ] * w[I  ][J  ][K  ] )/
02228           ( w[I+1][J+1][K+1] + 
02229             w[I  ][J+1][K+1] +
02230             w[I+1][J  ][K+1] +
02231             w[I  ][J  ][K+1] +
02232             w[I+1][J+1][K  ] +
02233             w[I  ][J+1][K  ] +
02234             w[I+1][J  ][K  ] +
02235             w[I  ][J  ][K  ] ) );
02236   return r;
02237 }
02238 
02239 //----------------------------------------------------------------------
02240 // Unweighted average Cell to Vert
02241 //----------------------------------------------------------------------
02242 template < class T1, class MFLOAT >
02243 Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>&
02244 Average(Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>& x, 
02245         Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>& r) 
02246 {
02247   const NDIndex<1U>& domain = r.getDomain();
02248   Index I = domain[0];
02249   r[I] = 0.5*(x[I-1] + x[I  ]);
02250   return r;
02251 }
02252 //----------------------------------------------------------------------
02253 template < class T1, class MFLOAT >
02254 Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>&
02255 Average(Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>& x, 
02256         Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>& r)
02257 {
02258   const NDIndex<2U>& domain = r.getDomain();
02259   Index I = domain[0];
02260   Index J = domain[1];
02261   r[I][J] = 0.25*(x[I-1][J-1] + x[I  ][J-1] + x[I-1][J  ] + x[I  ][J  ]);
02262   return r;
02263 }
02264 //----------------------------------------------------------------------
02265 template < class T1, class MFLOAT >
02266 Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>&
02267 Average(Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>& x, 
02268         Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>& r)
02269 {
02270   const NDIndex<3U>& domain = r.getDomain();
02271   Index I = domain[0];
02272   Index J = domain[1];
02273   Index K = domain[2];
02274   r[I][J][K] = 0.125*(x[I-1][J-1][K-1] + x[I  ][J-1][K-1] + x[I-1][J  ][K-1] +
02275                       x[I  ][J  ][K-1] + x[I-1][J-1][K  ] + x[I  ][J-1][K  ] +
02276                       x[I-1][J  ][K  ] + x[I  ][J  ][K  ]);
02277   return r;
02278 }
02279 //----------------------------------------------------------------------
02280 // Unweighted average Vert to Cell 
02281 // N.B.: won't work except for unit-stride (& zero-base?) Field's.
02282 //----------------------------------------------------------------------
02283 template < class T1, class MFLOAT >
02284 Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>&
02285 Average(Field<T1,1U,UniformCartesian<1U,MFLOAT>,Vert>& x, 
02286 
02287         Field<T1,1U,UniformCartesian<1U,MFLOAT>,Cell>& r) 
02288 {
02289   const NDIndex<1U>& domain = r.getDomain();
02290   Index I = domain[0];
02291   r[I] = 0.5*(x[I+1] + x[I  ]);
02292   return r;
02293 }
02294 //----------------------------------------------------------------------
02295 template < class T1, class MFLOAT >
02296 Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>&
02297 Average(Field<T1,2U,UniformCartesian<2U,MFLOAT>,Vert>& x, 
02298         Field<T1,2U,UniformCartesian<2U,MFLOAT>,Cell>& r)
02299 {
02300   const NDIndex<2U>& domain = r.getDomain();
02301   Index I = domain[0];
02302   Index J = domain[1];
02303   r[I][J] = 0.25*(x[I+1][J+1] + x[I  ][J+1] + x[I+1][J  ] + x[I  ][J  ]);
02304   return r;
02305 }
02306 //----------------------------------------------------------------------
02307 template < class T1, class MFLOAT >
02308 Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>&
02309 Average(Field<T1,3U,UniformCartesian<3U,MFLOAT>,Vert>& x, 
02310         Field<T1,3U,UniformCartesian<3U,MFLOAT>,Cell>& r)
02311 {
02312   const NDIndex<3U>& domain = r.getDomain();
02313   Index I = domain[0];
02314   Index J = domain[1];
02315   Index K = domain[2];
02316   r[I][J][K] = 0.125*(x[I+1][J+1][K+1] + x[I  ][J+1][K+1] + x[I+1][J  ][K+1] +
02317                       x[I  ][J  ][K+1] + x[I+1][J+1][K  ] + x[I  ][J+1][K  ] +
02318                       x[I+1][J  ][K  ] + x[I  ][J  ][K  ]);
02319   return r;
02320 }
02321 /***************************************************************************
02322  * $RCSfile: UniformCartesian.cpp,v $   $Author: adelmann $
02323  * $Revision: 1.1.1.1 $   $Date: 2003/01/23 07:40:28 $
02324  * IPPL_VERSION_ID: $Id: UniformCartesian.cpp,v 1.1.1.1 2003/01/23 07:40:28 adelmann Exp $ 
02325  ***************************************************************************/

Generated on Mon Jan 16 13:23:51 2006 for IPPL by  doxygen 1.4.6