OPAL (Object Oriented Parallel Accelerator Library)  2021.1.99
OPAL
Cartesian.hpp
Go to the documentation of this file.
1 // -*- C++ -*-
2 /***************************************************************************
3  *
4  * The IPPL Framework
5  *
6  * This program was prepared by PSI.
7  * All rights in the program are reserved by PSI.
8  * Neither PSI nor the author(s)
9  * makes any warranty, express or implied, or assumes any liability or
10  * responsibility for the use of this software
11  *
12  * Visit www.amas.web.psi for more details
13  *
14  ***************************************************************************/
15 
16 // -*- C++ -*-
17 /***************************************************************************
18  *
19  * The IPPL Framework
20  *
21  *
22  * Visit http://people.web.psi.ch/adelmann/ for more details
23  *
24  ***************************************************************************/
25 
26 // Cartesian.cpp
27 // Implementations for Cartesian mesh class (nonuniform spacings)
28 
29 // include files
30 #include "Utility/PAssert.h"
31 #include "Utility/IpplException.h"
32 #include "Utility/IpplInfo.h"
33 #include "Field/BareField.h"
34 #include "Field/BrickExpression.h"
35 #include "Field/LField.h"
36 #include "Field/Field.h"
37 #include "Field/Assign.h"
38 #include "Field/AssignDefs.h"
39 
40 //-----------------------------------------------------------------------------
41 // Setup chores common to all constructors:
42 //-----------------------------------------------------------------------------
43 template <unsigned Dim, class MFLOAT>
44 void
46 setup()
47 {
48  hasSpacingFields = false;
49 }
50 
51 //-----------------------------------------------------------------------------
52 // Constructors from NDIndex object:
53 //-----------------------------------------------------------------------------
54 template <unsigned Dim, class MFLOAT>
56 Cartesian(const NDIndex<Dim>& ndi)
57 {
58  unsigned int d,i;
59  for (d=0; d<Dim; d++)
60  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
61  setup(); // Setup chores, such as array allocations
62  for (d=0; d<Dim; d++) {
63  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
64  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
65  origin(d) = ndi[d].first(); // Default origin at ndi[d].first()
66  // default mesh spacing from stride()
67  for (i=0; i < gridSizes[d]-1; i++) {
68  (meshSpacing[d])[i] = ndi[d].stride();
69  (meshPosition[d])[i] = MFLOAT(i);
70  }
71  (meshPosition[d])[gridSizes[d]-1] = MFLOAT(gridSizes[d]-1);
72  }
73  set_Dvc(); // Set derivative coefficients from spacings.
74 }
75 // Also specify mesh spacings:
76 template <unsigned Dim, class MFLOAT>
78 Cartesian(const NDIndex<Dim>& ndi, MFLOAT** const delX)
79 {
80  unsigned int d;
81  for (d=0; d<Dim; d++)
82  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
83  setup(); // Setup chores, such as array allocations
84  for (d=0; d<Dim; d++) {
85  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
86  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
87  origin(d) = ndi[d].first(); // Default origin at ndi[d].first()
88  }
89  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
90  set_Dvc(); // Set derivative coefficients from spacings.
91 }
92 // Also specify mesh spacings and origin:
93 template <unsigned Dim, class MFLOAT>
95 Cartesian(const NDIndex<Dim>& ndi, MFLOAT** const delX,
96  const Vektor<MFLOAT,Dim>& orig)
97 {
98  int d;
99  for (d=0; d<Dim; d++)
100  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
101  setup(); // Setup chores, such as array allocations
102  for (d=0; d<Dim; d++) {
103  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
104  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
105  }
106  set_origin(orig); // Set origin.
107  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
108  set_Dvc(); // Set derivative coefficients from spacings.
109 }
110 // Also specify a MeshBC_E array for mesh boundary conditions:
111 template <unsigned Dim, class MFLOAT>
113 Cartesian(const NDIndex<Dim>& ndi, MFLOAT** const delX,
114  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
115 {
116  int d;
117  for (d=0; d<Dim; d++)
118  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
119  setup(); // Setup chores, such as array allocations
120  set_origin(orig); // Set origin.
121  set_MeshBC(mbc); // Set up mesh boundary conditions
122  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
123  set_Dvc(); // Set derivative coefficients from spacings.
124 }
125 //-----------------------------------------------------------------------------
126 // Constructors from Index objects:
127 //-----------------------------------------------------------------------------
128 
129 //===========1D============
130 template <unsigned Dim, class MFLOAT>
132 Cartesian(const Index& I)
133 {
134  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
135  gridSizes[0] = I.length(); // Number of vertices along this dimension.
136  setup(); // Setup chores, such as array allocations
137  origin(0) = I.first(); // Default origin at I.first()
138  unsigned int i;
139  // Default mesh spacing from stride()
140  for (i=0; i < gridSizes[0]-1; i++) {
141  (meshSpacing[0])[i] = I.stride();
142  (meshPosition[0])[i] = MFLOAT(i);
143  }
144  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
145  for (unsigned int d=0; d<Dim; d++) {
146  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
147  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
148  }
149  set_Dvc(); // Set derivative coefficients from spacings.
150 }
151 // Also specify mesh spacings:
152 template <unsigned Dim, class MFLOAT>
154 Cartesian(const Index& I, MFLOAT** const delX)
155 {
156  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
157  gridSizes[0] = I.length(); // Number of vertices along this dimension.
158  setup(); // Setup chores, such as array allocations
159  origin(0) = I.first(); // Default origin at I.first()
160  for (unsigned int d=0; d<Dim; d++) {
161  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
162  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
163  }
164  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
165  set_Dvc(); // Set derivative coefficients from spacings.
166 }
167 // Also specify mesh spacings and origin:
168 template <unsigned Dim, class MFLOAT>
170 Cartesian(const Index& I, MFLOAT** const delX,
171  const Vektor<MFLOAT,Dim>& orig)
172 {
173  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
174  setup();
175  gridSizes[0] = I.length(); // Number of vertices along this dimension.
176  for (unsigned int d=0; d<Dim; d++) {
177  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
178  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
179  }
180  set_origin(orig); // Set origin.
181  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
182  set_Dvc(); // Set derivative coefficients from spacings.
183 }
184 // Also specify a MeshBC_E array for mesh boundary conditions:
185 template <unsigned Dim, class MFLOAT>
187 Cartesian(const Index& I, MFLOAT** const delX,
188  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
189 {
190  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
191  setup();
192  gridSizes[0] = I.length(); // Number of vertices along this dimension.
193  set_origin(orig); // Set origin.
194  set_MeshBC(mbc); // Set up mesh boundary conditions
195  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
196  set_Dvc(); // Set derivative coefficients from spacings.
197 }
198 
199 //===========2D============
200 template <unsigned Dim, class MFLOAT>
202 Cartesian(const Index& I, const Index& J)
203 {
204  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
205  gridSizes[0] = I.length(); // Number of vertices along this dimension.
206  gridSizes[1] = J.length(); // Number of vertices along this dimension.
207  setup(); // Setup chores, such as array allocations
208  origin(0) = I.first(); // Default origin at I.first(),J.first()
209  origin(1) = J.first();
210  unsigned int i;
211  // Default mesh spacing from stride()
212  for (i=0; i < gridSizes[0]-1; i++) {
213  (meshSpacing[0])[i] = I.stride();
214  (meshPosition[0])[i] = MFLOAT(i);
215  }
216  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
217  for (i=0; i < gridSizes[1]-1; i++) {
218  (meshSpacing[1])[i] = J.stride();
219  (meshPosition[1])[i] = MFLOAT(i);
220  }
221  (meshPosition[1])[gridSizes[1]-1] = MFLOAT(gridSizes[1]-1);
222  for (unsigned int d=0; d<Dim; d++) {
223  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
224  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
225  }
226  set_Dvc(); // Set derivative coefficients from spacings.
227 }
228 // Also specify mesh spacings:
229 template <unsigned Dim, class MFLOAT>
231 Cartesian(const Index& I, const Index& J, MFLOAT** const delX)
232 {
233  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
234  gridSizes[0] = I.length(); // Number of vertices along this dimension.
235  gridSizes[1] = J.length(); // Number of vertices along this dimension.
236  setup(); // Setup chores, such as array allocations
237  origin(0) = I.first(); // Default origin at I.first(),J.first()
238  origin(1) = J.first();
239  for (unsigned int d=0; d<Dim; d++) {
240  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
241  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
242  }
243  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
244  set_Dvc(); // Set derivative coefficients from spacings.
245 }
246 // Also specify mesh spacings and origin:
247 template <unsigned Dim, class MFLOAT>
249 Cartesian(const Index& I, const Index& J, MFLOAT** const delX,
250  const Vektor<MFLOAT,Dim>& orig)
251 {
252  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
253  gridSizes[0] = I.length(); // Number of vertices along this dimension.
254  gridSizes[1] = J.length(); // Number of vertices along this dimension.
255  setup(); // Setup chores, such as array allocations
256  for (unsigned int d=0; d<Dim; d++) {
257  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
258  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
259  }
260  set_origin(orig); // Set origin.
261  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
262  set_Dvc(); // Set derivative coefficients from spacings.
263 }
264 // Also specify a MeshBC_E array for mesh boundary conditions:
265 template <unsigned Dim, class MFLOAT>
267 Cartesian(const Index& I, const Index& J, MFLOAT** const delX,
268  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
269 {
270  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
271  gridSizes[0] = I.length(); // Number of vertices along this dimension.
272  gridSizes[1] = J.length(); // Number of vertices along this dimension.
273  setup(); // Setup chores, such as array allocations
274  set_origin(orig); // Set origin.
275  set_MeshBC(mbc); // Set up mesh boundary conditions
276  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
277  set_Dvc(); // Set derivative coefficients from spacings.
278 }
279 
280 //===========3D============
281 template <unsigned Dim, class MFLOAT>
283 Cartesian(const Index& I, const Index& J, const Index& K)
284 {
285  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
286  gridSizes[0] = I.length(); // Number of vertices along this dimension.
287  gridSizes[1] = J.length(); // Number of vertices along this dimension.
288  gridSizes[2] = K.length(); // Number of vertices along this dimension.
289  // Setup chores, such as array allocations
290  setup();
291  origin(0) = I.first(); // Default origin at I.first(),J.first(),K.first()
292  origin(1) = J.first();
293  origin(2) = K.first();
294  unsigned int i;
295  // Default mesh spacing from stride()
296  for (i=0; i < gridSizes[0]-1; i++) {
297  (meshSpacing[0])[i] = I.stride();
298  (meshPosition[0])[i] = MFLOAT(i);
299  }
300  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
301  for (i=0; i < gridSizes[1]-1; i++) {
302  (meshSpacing[1])[i] = J.stride();
303  (meshPosition[1])[i] = MFLOAT(i);
304  }
305  (meshPosition[1])[gridSizes[1]-1] = MFLOAT(gridSizes[1]-1);
306  for (i=0; i < gridSizes[2]-1; i++) {
307  (meshSpacing[2])[i] = K.stride();
308  (meshPosition[2])[i] = MFLOAT(i);
309  }
310  (meshPosition[2])[gridSizes[2]-1] = MFLOAT(gridSizes[2]-1);
311 
312  for (unsigned int d=0; d<Dim; d++) {
313  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
314  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
315  }
316  set_Dvc(); // Set derivative coefficients from spacings.
317 }
318 // Also specify mesh spacings:
319 template <unsigned Dim, class MFLOAT>
321 Cartesian(const Index& I, const Index& J, const Index& K,
322  MFLOAT** const delX)
323 {
324  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
325  gridSizes[0] = I.length(); // Number of vertices along this dimension.
326  gridSizes[1] = J.length(); // Number of vertices along this dimension.
327  gridSizes[2] = K.length(); // Number of vertices along this dimension.
328  setup(); // Setup chores, such as array allocations
329  origin(0) = I.first(); // Default origin at I.first(),J.first(),K.first()
330  origin(1) = J.first();
331  origin(2) = K.first();
332  for (unsigned int d=0; d<Dim; d++) {
333  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
334  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
335  }
336  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
337  set_Dvc(); // Set derivative coefficients from spacings.
338 }
339 // Also specify mesh spacings and origin:
340 template <unsigned Dim, class MFLOAT>
342 Cartesian(const Index& I, const Index& J, const Index& K,
343  MFLOAT** const delX, const Vektor<MFLOAT,Dim>& orig)
344 {
345  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
346  gridSizes[0] = I.length(); // Number of vertices along this dimension.
347  gridSizes[1] = J.length(); // Number of vertices along this dimension.
348  gridSizes[2] = K.length(); // Number of vertices along this dimension.
349  setup(); // Setup chores, such as array allocations
350  for (unsigned int d=0; d<Dim; d++) {
351  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
352  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
353  }
354  set_origin(orig); // Set origin.
355  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
356  set_Dvc(); // Set derivative coefficients from spacings.
357 }
358 // Also specify a MeshBC_E array for mesh boundary conditions:
359 template <unsigned Dim, class MFLOAT>
361 Cartesian(const Index& I, const Index& J, const Index& K,
362  MFLOAT** const delX, const Vektor<MFLOAT,Dim>& orig,
363  MeshBC_E* const mbc)
364 {
365  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
366  gridSizes[0] = I.length(); // Number of vertices along this dimension.
367  gridSizes[1] = J.length(); // Number of vertices along this dimension.
368  gridSizes[2] = K.length(); // Number of vertices along this dimension.
369  setup(); // Setup chores, such as array allocations
370  set_origin(orig); // Set origin.
371  set_MeshBC(mbc); // Set up mesh boundary conditions
372  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
373  set_Dvc(); // Set derivative coefficients from spacings.
374 }
375 
376 //-----------------------------------------------------------------------------
377 // initialize using NDIndex object:
378 //-----------------------------------------------------------------------------
379 template <unsigned Dim, class MFLOAT>
380 void
382 initialize(const NDIndex<Dim>& ndi)
383 {
384  unsigned int d,i;
385  for (d=0; d<Dim; d++)
386  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
387  setup(); // Setup chores, such as array allocations
388  for (d=0; d<Dim; d++) {
389  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
390  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
391  origin(d) = ndi[d].first(); // Default origin at ndi[d].first()
392  // default mesh spacing from stride()
393  for (i=0; i < gridSizes[d]-1; i++) {
394  (meshSpacing[d])[i] = ndi[d].stride();
395  (meshPosition[d])[i] = MFLOAT(i);
396  }
397  (meshPosition[d])[gridSizes[d]-1] = MFLOAT(gridSizes[d]-1);
398  }
399  set_Dvc(); // Set derivative coefficients from spacings.
400 }
401 // Also specify mesh spacings:
402 template <unsigned Dim, class MFLOAT>
403 void
405 initialize(const NDIndex<Dim>& ndi, MFLOAT** const delX)
406 {
407  unsigned int d;
408  for (d=0; d<Dim; d++)
409  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
410  setup(); // Setup chores, such as array allocations
411  for (d=0; d<Dim; d++) {
412  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
413  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
414  origin(d) = ndi[d].first(); // Default origin at ndi[d].first()
415  }
416  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
417  set_Dvc(); // Set derivative coefficients from spacings.
418 }
419 // Also specify mesh spacings and origin:
420 template <unsigned Dim, class MFLOAT>
421 void
423 initialize(const NDIndex<Dim>& ndi, MFLOAT** const delX,
424  const Vektor<MFLOAT,Dim>& orig)
425 {
426  int d;
427  for (d=0; d<Dim; d++)
428  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
429  setup(); // Setup chores, such as array allocations
430  for (d=0; d<Dim; d++) {
431  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
432  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
433  }
434  set_origin(orig); // Set origin.
435  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
436  set_Dvc(); // Set derivative coefficients from spacings.
437 }
438 // Also specify a MeshBC_E array for mesh boundary conditions:
439 template <unsigned Dim, class MFLOAT>
440 void
442 initialize(const NDIndex<Dim>& ndi, MFLOAT** const delX,
443  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
444 {
445  int d;
446  for (d=0; d<Dim; d++)
447  gridSizes[d] = ndi[d].length(); // Number of vertices along this dimension.
448  setup(); // Setup chores, such as array allocations
449  set_origin(orig); // Set origin.
450  set_MeshBC(mbc); // Set up mesh boundary conditions
451  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
452  set_Dvc(); // Set derivative coefficients from spacings.
453 }
454 //-----------------------------------------------------------------------------
455 // initialize using Index objects:
456 //-----------------------------------------------------------------------------
457 
458 //===========1D============
459 template <unsigned Dim, class MFLOAT>
460 void
462 initialize(const Index& I)
463 {
464  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
465  gridSizes[0] = I.length(); // Number of vertices along this dimension.
466  setup(); // Setup chores, such as array allocations
467  origin(0) = I.first(); // Default origin at I.first()
468  unsigned int i;
469  // Default mesh spacing from stride()
470  for (i=0; i < gridSizes[0]-1; i++) {
471  (meshSpacing[0])[i] = I.stride();
472  (meshPosition[0])[i] = MFLOAT(i);
473  }
474  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
475  for (unsigned int d=0; d<Dim; d++) {
476  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
477  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
478  }
479  set_Dvc(); // Set derivative coefficients from spacings.
480 }
481 // Also specify mesh spacings:
482 template <unsigned Dim, class MFLOAT>
483 void
485 initialize(const Index& I, MFLOAT** const delX)
486 {
487  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
488  gridSizes[0] = I.length(); // Number of vertices along this dimension.
489  setup(); // Setup chores, such as array allocations
490  origin(0) = I.first(); // Default origin at I.first()
491  for (unsigned int d=0; d<Dim; d++) {
492  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
493  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
494  }
495  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
496  set_Dvc(); // Set derivative coefficients from spacings.
497 }
498 // Also specify mesh spacings and origin:
499 template <unsigned Dim, class MFLOAT>
500 void
502 initialize(const Index& I, MFLOAT** const delX,
503  const Vektor<MFLOAT,Dim>& orig)
504 {
505  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
506  setup();
507  gridSizes[0] = I.length(); // Number of vertices along this dimension.
508  for (unsigned int d=0; d<Dim; d++) {
509  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
510  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
511  }
512  set_origin(orig); // Set origin.
513  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
514  set_Dvc(); // Set derivative coefficients from spacings.
515 }
516 // Also specify a MeshBC_E array for mesh boundary conditions:
517 template <unsigned Dim, class MFLOAT>
518 void
520 initialize(const Index& I, MFLOAT** const delX,
521  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
522 {
523  PInsist(Dim==1,"Number of Index arguments does not match mesh dimension!!");
524  setup();
525  gridSizes[0] = I.length(); // Number of vertices along this dimension.
526  set_origin(orig); // Set origin.
527  set_MeshBC(mbc); // Set up mesh boundary conditions
528  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
529  set_Dvc(); // Set derivative coefficients from spacings.
530 }
531 
532 //===========2D============
533 template <unsigned Dim, class MFLOAT>
534 void
536 initialize(const Index& I, const Index& J)
537 {
538  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
539  gridSizes[0] = I.length(); // Number of vertices along this dimension.
540  gridSizes[1] = J.length(); // Number of vertices along this dimension.
541  setup(); // Setup chores, such as array allocations
542  origin(0) = I.first(); // Default origin at I.first(),J.first()
543  origin(1) = J.first();
544  unsigned int i;
545  // Default mesh spacing from stride()
546  for (i=0; i < gridSizes[0]-1; i++) {
547  (meshSpacing[0])[i] = I.stride();
548  (meshPosition[0])[i] = MFLOAT(i);
549  }
550  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
551  for (i=0; i < gridSizes[1]-1; i++) {
552  (meshSpacing[1])[i] = J.stride();
553  (meshPosition[1])[i] = MFLOAT(i);
554  }
555  (meshPosition[1])[gridSizes[1]-1] = MFLOAT(gridSizes[1]-1);
556  for (unsigned int d=0; d<Dim; d++) {
557  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
558  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
559  }
560  set_Dvc(); // Set derivative coefficients from spacings.
561 }
562 // Also specify mesh spacings:
563 template <unsigned Dim, class MFLOAT>
564 void
566 initialize(const Index& I, const Index& J, MFLOAT** const delX)
567 {
568  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
569  gridSizes[0] = I.length(); // Number of vertices along this dimension.
570  gridSizes[1] = J.length(); // Number of vertices along this dimension.
571  setup(); // Setup chores, such as array allocations
572  origin(0) = I.first(); // Default origin at I.first(),J.first()
573  origin(1) = J.first();
574  for (unsigned int d=0; d<Dim; d++) {
575  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
576  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
577  }
578  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
579  set_Dvc(); // Set derivative coefficients from spacings.
580 }
581 // Also specify mesh spacings and origin:
582 template <unsigned Dim, class MFLOAT>
583 void
585 initialize(const Index& I, const Index& J, MFLOAT** const delX,
586  const Vektor<MFLOAT,Dim>& orig)
587 {
588  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
589  gridSizes[0] = I.length(); // Number of vertices along this dimension.
590  gridSizes[1] = J.length(); // Number of vertices along this dimension.
591  setup(); // Setup chores, such as array allocations
592  for (unsigned int d=0; d<Dim; d++) {
593  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
594  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
595  }
596  set_origin(orig); // Set origin.
597  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
598  set_Dvc(); // Set derivative coefficients from spacings.
599 }
600 // Also specify a MeshBC_E array for mesh boundary conditions:
601 template <unsigned Dim, class MFLOAT>
602 void
604 initialize(const Index& I, const Index& J, MFLOAT** const delX,
605  const Vektor<MFLOAT,Dim>& orig, MeshBC_E* const mbc)
606 {
607  PInsist(Dim==2,"Number of Index arguments does not match mesh dimension!!");
608  gridSizes[0] = I.length(); // Number of vertices along this dimension.
609  gridSizes[1] = J.length(); // Number of vertices along this dimension.
610  setup(); // Setup chores, such as array allocations
611  set_origin(orig); // Set origin.
612  set_MeshBC(mbc); // Set up mesh boundary conditions
613  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
614  set_Dvc(); // Set derivative coefficients from spacings.
615 }
616 
617 //===========3D============
618 template <unsigned Dim, class MFLOAT>
619 void
621 initialize(const Index& I, const Index& J, const Index& K)
622 {
623  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
624  gridSizes[0] = I.length(); // Number of vertices along this dimension.
625  gridSizes[1] = J.length(); // Number of vertices along this dimension.
626  gridSizes[2] = K.length(); // Number of vertices along this dimension.
627  // Setup chores, such as array allocations
628  setup();
629  origin(0) = I.first(); // Default origin at I.first(),J.first(),K.first()
630  origin(1) = J.first();
631  origin(2) = K.first();
632  int i;
633  // Default mesh spacing from stride()
634  for (i=0; i < gridSizes[0]-1; i++) {
635  (meshSpacing[0])[i] = I.stride();
636  (meshPosition[0])[i] = MFLOAT(i);
637  }
638  (meshPosition[0])[gridSizes[0]-1] = MFLOAT(gridSizes[0]-1);
639  for (i=0; i < gridSizes[1]-1; i++) {
640  (meshSpacing[1])[i] = J.stride();
641  (meshPosition[1])[i] = MFLOAT(i);
642  }
643  (meshPosition[1])[gridSizes[1]-1] = MFLOAT(gridSizes[1]-1);
644  for (i=0; i < gridSizes[2]-1; i++) {
645  (meshSpacing[2])[i] = K.stride();
646  (meshPosition[2])[i] = MFLOAT(i);
647  }
648  (meshPosition[2])[gridSizes[2]-1] = MFLOAT(gridSizes[2]-1);
649 
650  for (unsigned int d=0; d<Dim; d++) {
651  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
652  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
653  }
654  set_Dvc(); // Set derivative coefficients from spacings.
655 }
656 // Also specify mesh spacings:
657 template <unsigned Dim, class MFLOAT>
658 void
660 initialize(const Index& I, const Index& J, const Index& K,
661  MFLOAT** const delX)
662 {
663  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
664  gridSizes[0] = I.length(); // Number of vertices along this dimension.
665  gridSizes[1] = J.length(); // Number of vertices along this dimension.
666  gridSizes[2] = K.length(); // Number of vertices along this dimension.
667  setup(); // Setup chores, such as array allocations
668  origin(0) = I.first(); // Default origin at I.first(),J.first(),K.first()
669  origin(1) = J.first();
670  origin(2) = K.first();
671  for (unsigned int d=0; d<Dim; d++) {
672  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
673  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
674  }
675  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
676  set_Dvc(); // Set derivative coefficients from spacings.
677 }
678 // Also specify mesh spacings and origin:
679 template <unsigned Dim, class MFLOAT>
680 void
682 initialize(const Index& I, const Index& J, const Index& K,
683  MFLOAT** const delX, const Vektor<MFLOAT,Dim>& orig)
684 {
685  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
686  gridSizes[0] = I.length(); // Number of vertices along this dimension.
687  gridSizes[1] = J.length(); // Number of vertices along this dimension.
688  gridSizes[2] = K.length(); // Number of vertices along this dimension.
689  setup(); // Setup chores, such as array allocations
690  for (unsigned int d=0; d<Dim; d++) {
691  MeshBC[2*d] = Reflective; // Default mesh: reflective boundary conds
692  MeshBC[2*d+1] = Reflective; // Default mesh: reflective boundary conds
693  }
694  set_origin(orig); // Set origin.
695  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
696  set_Dvc(); // Set derivative coefficients from spacings.
697 }
698 // Also specify a MeshBC_E array for mesh boundary conditions:
699 template <unsigned Dim, class MFLOAT>
700 void
702 initialize(const Index& I, const Index& J, const Index& K,
703  MFLOAT** const delX, const Vektor<MFLOAT,Dim>& orig,
704  MeshBC_E* const mbc)
705 {
706  PInsist(Dim==3,"Number of Index arguments does not match mesh dimension!!");
707  gridSizes[0] = I.length(); // Number of vertices along this dimension.
708  gridSizes[1] = J.length(); // Number of vertices along this dimension.
709  gridSizes[2] = K.length(); // Number of vertices along this dimension.
710  setup(); // Setup chores, such as array allocations
711  set_origin(orig); // Set origin.
712  set_MeshBC(mbc); // Set up mesh boundary conditions
713  set_meshSpacing(delX); // Set mesh spacings and compute cell volume
714  set_Dvc(); // Set derivative coefficients from spacings.
715 }
716 
717 //-----------------------------------------------------------------------------
718 // Set/accessor functions for member data:
719 //-----------------------------------------------------------------------------
720 // Set the origin of mesh vertex positions:
721 template<unsigned Dim, class MFLOAT>
724 {
725  origin = o;
726  for (unsigned d=0; d<Dim; ++d) {
727  (meshPosition[d])[0] = o(d);
728  for (unsigned vert=1; vert<gridSizes[d]; ++vert) {
729  (meshPosition[d])[vert] = (meshPosition[d])[vert-1] +
730  (meshSpacing[d])[vert-1];
731  }
732  }
733  // Apply the current state of the mesh BC to add guards to meshPosition map:
734  for (unsigned face=0; face < 2*Dim; ++face) updateMeshSpacingGuards(face);
735  this->notifyOfChange();
736 }
737 // Get the origin of mesh vertex positions:
738 template<unsigned Dim, class MFLOAT>
740 get_origin() const
741 {
742  return origin;
743 }
744 
745 // Set the spacings of mesh vertex positions:
746 template<unsigned Dim, class MFLOAT>
748 set_meshSpacing(MFLOAT** const del)
749 {
750  unsigned d, cell, face;
751 
752  for (d=0;d<Dim;++d) {
753  (meshPosition[d])[0] = origin(d);
754  for (cell=0; cell < gridSizes[d]-1; cell++) {
755  (meshSpacing[d])[cell] = del[d][cell];
756  (meshPosition[d])[cell+1] = (meshPosition[d])[cell] + del[d][cell];
757  }
758  }
759  // Apply the current state of the mesh BC to add guards to meshSpacings map:
760  for (face=0; face < 2*Dim; ++face) updateMeshSpacingGuards(face);
761  // if spacing fields allocated, we must update values
762  if (hasSpacingFields) storeSpacingFields();
763  this->notifyOfChange();
764 }
765 
766 // Set only the derivative constants, using pre-set spacings:
767 template<unsigned Dim, class MFLOAT>
769 set_Dvc()
770 {
771  unsigned d;
772  MFLOAT coef = 1.0;
773  for (d=1;d<Dim;++d) coef *= 0.5;
774 
775  for (d=0;d<Dim;++d) {
776  MFLOAT dvc = coef;
777  for (unsigned b=0; b<(1<<Dim); ++b) {
778  int s = ( b&(1<<d) ) ? 1 : -1;
779  Dvc[b](d) = s*dvc;
780  }
781  }
782 }
783 
784 // Get the spacings of mesh vertex positions along specified direction:
785 template<unsigned Dim, class MFLOAT>
787 get_meshSpacing(unsigned d, MFLOAT* spacings) const
788 {
789  PAssert_LT(d, Dim);
790  for (unsigned int cell=0; cell < gridSizes[d]-1; cell++)
791  spacings[cell] = (*(meshSpacing[d].find(cell))).second;
792  return;
793 }
794 //leak template<unsigned Dim, class MFLOAT>
795 //leak MFLOAT* Cartesian<Dim,MFLOAT>::
796 //leak get_meshSpacing(unsigned d) const
797 //leak {
798 //leak PAssert_LT(d, Dim);
799 //leak MFLOAT* theMeshSpacing = new MFLOAT[gridSizes[d]-1];
800 //leak for (int cell=0; cell < gridSizes[d]-1; cell++)
801 //leak theMeshSpacing[cell] = (*(meshSpacing[d].find(cell))).second;
802 //leak return theMeshSpacing;
803 //leak }
804 
806 
807 // Applicative templates for Mesh BC PETE_apply() functions, used
808 // by BrickExpression in storeSpacingFields()
809 
810 // Periodic:
811 template<class T>
813 {
814 };
815 template<class T>
816 inline void PETE_apply(OpMeshPeriodic<T> /*e*/, T& a, T b) { a = b; }
817 
818 // Reflective/None:
819 template<class T>
821 {
822  OpMeshExtrapolate(T& o, T& s) : Offset(o), Slope(s) {}
824 };
825 // template<class T>
826 // inline void apply(OpMeshExtrapolate<T> e, T& a, T b)
827 template<class T>
829 {
830  a = b*e.Slope+e.Offset;
831 }
832 
834 
835 // Create BareField's of vertex and cell spacings
836 // Special prototypes taking no args or FieldLayout ctor args:
837 // No-arg case:
838 template<unsigned Dim, class MFLOAT>
841 {
842  // Set up default FieldLayout parameters:
843  e_dim_tag et[Dim];
844  for (unsigned int d=0; d<Dim; d++) et[d] = PARALLEL;
845  storeSpacingFields(et, -1);
846 }
847 // 1D
848 template<unsigned Dim, class MFLOAT>
850 storeSpacingFields(e_dim_tag p1, int vnodes)
851 {
852  e_dim_tag et[1];
853  et[0] = p1;
854  storeSpacingFields(et, vnodes);
855 }
856 // 2D
857 template<unsigned Dim, class MFLOAT>
859 storeSpacingFields(e_dim_tag p1, e_dim_tag p2, int vnodes)
860 {
861  e_dim_tag et[2];
862  et[0] = p1;
863  et[1] = p2;
864  storeSpacingFields(et, vnodes);
865 }
866 // 3D
867 template<unsigned Dim, class MFLOAT>
869 storeSpacingFields(e_dim_tag p1, e_dim_tag p2, e_dim_tag p3, int vnodes)
870 {
871  e_dim_tag et[3];
872  et[0] = p1;
873  et[1] = p2;
874  et[2] = p3;
875  storeSpacingFields(et, vnodes);
876 }
877 
878 
879 // The general storeSpacingfields() function; others invoke this internally:
880 template<unsigned Dim, class MFLOAT>
882 storeSpacingFields(e_dim_tag* et, int vnodes)
883 {
884  unsigned int d;
885  int currentLocation[Dim];
886  NDIndex<Dim> cells, verts;
887  for (d=0; d<Dim; d++) {
888  cells[d] = Index(gridSizes[d]-1);
889  verts[d] = Index(gridSizes[d]);
890  }
891  if (!hasSpacingFields) {
892  // allocate layouts and spacing fields
893  FlCell = new FieldLayout<Dim>(cells, et, vnodes);
894  // Note: enough guard cells only for existing Div(), etc. implementations:
895  VertSpacings =
897  FlVert = new FieldLayout<Dim>(verts, et, vnodes);
898  // Note: enough guard cells only for existing Div(), etc. implementations:
899  CellSpacings =
901  }
902  // VERTEX-VERTEX SPACINGS:
903  BareField<Vektor<MFLOAT,Dim>,Dim>& vertSpacings = *VertSpacings;
904  Vektor<MFLOAT,Dim> vertexSpacing;
905  vertSpacings.Uncompress(); // Must do this prior to assign via iterator
907  cfi_end = vertSpacings.end();
908  for (cfi = vertSpacings.begin(); cfi != cfi_end; ++cfi) {
909  cfi.GetCurrentLocation(currentLocation);
910  for (d=0; d<Dim; d++)
911  vertexSpacing(d) = (*(meshSpacing[d].find(currentLocation[d]))).second;
912  *cfi = vertexSpacing;
913  }
914  // CELL-CELL SPACINGS:
915  BareField<Vektor<MFLOAT,Dim>,Dim>& cellSpacings = *CellSpacings;
916  Vektor<MFLOAT,Dim> cellSpacing;
917  cellSpacings.Uncompress(); // Must do this prior to assign via iterator
919  vfi_end = cellSpacings.end();
920  for (vfi = cellSpacings.begin(); vfi != vfi_end; ++vfi) {
921  vfi.GetCurrentLocation(currentLocation);
922  for (d=0; d<Dim; d++)
923  cellSpacing(d) = 0.5 * ((meshSpacing[d])[currentLocation[d]] +
924  (meshSpacing[d])[currentLocation[d]-1]);
925  *vfi = cellSpacing;
926  }
927  //-------------------------------------------------
928  // Now the hard part, filling in the guard cells:
929  //-------------------------------------------------
930  // The easy part of the hard part is filling so that all the internal
931  // guard layers are right:
932  cellSpacings.fillGuardCells();
933  vertSpacings.fillGuardCells();
934  // The hard part of the hard part is filling the external guard layers,
935  // using the mesh BC to figure out how:
936  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
937  // Temporaries used in loop over faces
938  Vektor<MFLOAT,Dim> v0,v1; v0 = 0.0; v1 = 1.0; // Used for Reflective mesh BC
939  typedef Vektor<MFLOAT,Dim> T; // Used multipple places in loop below
940  typename BareField<T,Dim>::iterator_if cfill_i; // Iterator used below
941  typename BareField<T,Dim>::iterator_if vfill_i; // Iterator used below
942  int coffset, voffset; // Pointer offsets used with LField::iterator below
943  MeshBC_E bct; // Scalar value of mesh BC used for each face in loop
944  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
945  for (unsigned int face=0; face < 2*Dim; face++) {
946  // NDIndex's spanning elements and guard elements:
947  NDIndex<Dim> cSlab = AddGuardCells(verts,cellSpacings.getGuardCellSizes());
948  NDIndex<Dim> vSlab = AddGuardCells(cells,vertSpacings.getGuardCellSizes());
949  // Shrink it down to be the guards along the active face:
950  d = face/2;
951  // The following bitwise AND logical test returns true if face is odd
952  // (meaning the "high" or "right" face in the numbering convention) and
953  // returns false if face is even (meaning the "low" or "left" face in
954  // the numbering convention):
955  if ( face & 1 ) {
956  cSlab[d] = Index(verts[d].max() + 1,
957  verts[d].max() + cellSpacings.rightGuard(d));
958  vSlab[d] = Index(cells[d].max() + 1,
959  cells[d].max() + vertSpacings.rightGuard(d));
960  } else {
961  cSlab[d] = Index(verts[d].min() - cellSpacings.leftGuard(d),
962  verts[d].min() - 1);
963  vSlab[d] = Index(cells[d].min() - vertSpacings.leftGuard(d),
964  cells[d].min() - 1);
965  }
966  // Compute pointer offsets used with LField::iterator below:
967  switch (MeshBC[face]) {
968  case Periodic:
969  bct = Periodic;
970  if ( face & 1 ) {
971  coffset = -verts[d].length();
972  voffset = -cells[d].length();
973  } else {
974  coffset = verts[d].length();
975  voffset = cells[d].length();
976  }
977  break;
978  case Reflective:
979  bct = Reflective;
980  if ( face & 1 ) {
981  coffset = 2*verts[d].max() + 1;
982  voffset = 2*cells[d].max() + 1 - 1;
983  } else {
984  coffset = 2*verts[d].min() - 1;
985  voffset = 2*cells[d].min() - 1 + 1;
986  }
987  break;
988  case NoBC:
989  bct = NoBC;
990  if ( face & 1 ) {
991  coffset = 2*verts[d].max() + 1;
992  voffset = 2*cells[d].max() + 1 - 1;
993  } else {
994  coffset = 2*verts[d].min() - 1;
995  voffset = 2*cells[d].min() - 1 + 1;
996  }
997  break;
998  default:
999  throw IpplException("Cartesian::storeSpacingFields", "unknown MeshBC type");
1000  }
1001 
1002  // Loop over all the LField's in the BareField's:
1003  // +++++++++++++++cellSpacings++++++++++++++
1004  for (cfill_i=cellSpacings.begin_if();
1005  cfill_i!=cellSpacings.end_if(); ++cfill_i)
1006  {
1007  // Cache some things we will use often below.
1008  // Pointer to the data for the current LField (right????):
1009  LField<T,Dim> &fill = *(*cfill_i).second;
1010  // NDIndex spanning all elements in the LField, including the guards:
1011  const NDIndex<Dim> &fill_alloc = fill.getAllocated();
1012  // If the previously-created boundary guard-layer NDIndex "cSlab"
1013  // contains any of the elements in this LField (they will be guard
1014  // elements if it does), assign the values into them here by applying
1015  // the boundary condition:
1016  if ( cSlab.touches( fill_alloc ) )
1017  {
1018  // Find what it touches in this LField.
1019  NDIndex<Dim> dest = cSlab.intersect( fill_alloc );
1020 
1021  // For exrapolation boundary conditions, the boundary guard-layer
1022  // elements are typically copied from interior values; the "src"
1023  // NDIndex specifies the interior elements to be copied into the
1024  // "dest" boundary guard-layer elements (possibly after some
1025  // mathematical operations like multipplying by minus 1 later):
1026  NDIndex<Dim> src = dest; // Create dest equal to src
1027  // Now calculate the interior elements; the coffset variable
1028  // computed above makes this right for "low" or "high" face cases:
1029  src[d] = coffset - src[d];
1030 
1031  // TJW: Why is there another loop over LField's here??????????
1032  // Loop over the ones that src touches.
1033  typename BareField<T,Dim>::iterator_if from_i;
1034  for (from_i=cellSpacings.begin_if();
1035  from_i!=cellSpacings.end_if(); ++from_i)
1036  {
1037  // Cache a few things.
1038  LField<T,Dim> &from = *(*from_i).second;
1039  const NDIndex<Dim> &from_owned = from.getOwned();
1040  const NDIndex<Dim> &from_alloc = from.getAllocated();
1041  // If src touches this LField...
1042  if ( src.touches( from_owned ) )
1043  {
1044  NDIndex<Dim> from_it = src.intersect( from_alloc );
1045  NDIndex<Dim> cfill_it = dest.plugBase( from_it );
1046  // Build iterators for the copy...
1047  typedef typename LField<T,Dim>::iterator LFI;
1048  LFI lhs = fill.begin(cfill_it);
1049  LFI rhs = from.begin(from_it);
1050  // And do the assignment.
1051  if (bct == Periodic) {
1053  (lhs,rhs,OpMeshPeriodic<T>()).apply();
1054  } else {
1055  if (bct == Reflective) {
1057  (lhs,rhs,OpMeshExtrapolate<T>(v0,v1)).apply();
1058  } else {
1059  if (bct == NoBC) {
1061  (lhs,rhs,OpMeshExtrapolate<T>(v0,v0)).apply();
1062  }
1063  }
1064  }
1065  }
1066  }
1067  }
1068  }
1069  // +++++++++++++++vertSpacings++++++++++++++
1070  for (vfill_i=vertSpacings.begin_if();
1071  vfill_i!=vertSpacings.end_if(); ++vfill_i)
1072  {
1073  // Cache some things we will use often below.
1074  // Pointer to the data for the current LField (right????):
1075  LField<T,Dim> &fill = *(*vfill_i).second;
1076  // NDIndex spanning all elements in the LField, including the guards:
1077  const NDIndex<Dim> &fill_alloc = fill.getAllocated();
1078  // If the previously-created boundary guard-layer NDIndex "cSlab"
1079  // contains any of the elements in this LField (they will be guard
1080  // elements if it does), assign the values into them here by applying
1081  // the boundary condition:
1082  if ( vSlab.touches( fill_alloc ) )
1083  {
1084  // Find what it touches in this LField.
1085  NDIndex<Dim> dest = vSlab.intersect( fill_alloc );
1086 
1087  // For exrapolation boundary conditions, the boundary guard-layer
1088  // elements are typically copied from interior values; the "src"
1089  // NDIndex specifies the interior elements to be copied into the
1090  // "dest" boundary guard-layer elements (possibly after some
1091  // mathematical operations like multipplying by minus 1 later):
1092  NDIndex<Dim> src = dest; // Create dest equal to src
1093  // Now calculate the interior elements; the voffset variable
1094  // computed above makes this right for "low" or "high" face cases:
1095  src[d] = voffset - src[d];
1096 
1097  // TJW: Why is there another loop over LField's here??????????
1098  // Loop over the ones that src touches.
1099  typename BareField<T,Dim>::iterator_if from_i;
1100  for (from_i=vertSpacings.begin_if();
1101  from_i!=vertSpacings.end_if(); ++from_i)
1102  {
1103  // Cache a few things.
1104  LField<T,Dim> &from = *(*from_i).second;
1105  const NDIndex<Dim> &from_owned = from.getOwned();
1106  const NDIndex<Dim> &from_alloc = from.getAllocated();
1107  // If src touches this LField...
1108  if ( src.touches( from_owned ) )
1109  {
1110  NDIndex<Dim> from_it = src.intersect( from_alloc );
1111  NDIndex<Dim> vfill_it = dest.plugBase( from_it );
1112  // Build iterators for the copy...
1113  typedef typename LField<T,Dim>::iterator LFI;
1114  LFI lhs = fill.begin(vfill_it);
1115  LFI rhs = from.begin(from_it);
1116  // And do the assignment.
1117  if (bct == Periodic) {
1119  (lhs,rhs,OpMeshPeriodic<T>()).apply();
1120  } else {
1121  if (bct == Reflective) {
1123  (lhs,rhs,OpMeshExtrapolate<T>(v0,v1)).apply();
1124  } else {
1125  if (bct == NoBC) {
1127  (lhs,rhs,OpMeshExtrapolate<T>(v0,v0)).apply();
1128  }
1129  }
1130  }
1131  }
1132  }
1133  }
1134  }
1135 
1136  }
1137 
1138  hasSpacingFields = true; // Flag this as having been done to this object.
1139 }
1140 
1141 
1142 // These specify both the total number of vnodes and the numbers of vnodes
1143 // along each dimension for the partitioning of the index space. Obviously
1144 // this restricts the number of vnodes to be a product of the numbers along
1145 // each dimension (the constructor implementation checks this): Special
1146 // cases for 1-3 dimensions, ala FieldLayout ctors (see FieldLayout.h for
1147 // more relevant comments, including definition of recurse):
1148 
1149 // 1D
1150 template<unsigned Dim, class MFLOAT>
1153  unsigned vnodes1,
1154  bool recurse,
1155  int vnodes) {
1156  e_dim_tag et[1];
1157  et[0] = p1;
1158  unsigned vnodesPerDirection[Dim];
1159  vnodesPerDirection[0] = vnodes1;
1160  storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
1161 }
1162 // 2D
1163 template<unsigned Dim, class MFLOAT>
1166  unsigned vnodes1, unsigned vnodes2,
1167  bool recurse,int vnodes) {
1168  e_dim_tag et[2];
1169  et[0] = p1;
1170  et[1] = p2;
1171  unsigned vnodesPerDirection[Dim];
1172  vnodesPerDirection[0] = vnodes1;
1173  vnodesPerDirection[1] = vnodes2;
1174  storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
1175 }
1176 // 3D
1177 template<unsigned Dim, class MFLOAT>
1180  unsigned vnodes1, unsigned vnodes2, unsigned vnodes3,
1181  bool recurse, int vnodes) {
1182  e_dim_tag et[3];
1183  et[0] = p1;
1184  et[1] = p2;
1185  et[2] = p3;
1186  unsigned vnodesPerDirection[Dim];
1187  vnodesPerDirection[0] = vnodes1;
1188  vnodesPerDirection[1] = vnodes2;
1189  vnodesPerDirection[2] = vnodes3;
1190  storeSpacingFields(et, vnodesPerDirection, recurse, vnodes);
1191 }
1192 
1193 // TJW: Note: should clean up here eventually, and put redundant code from
1194 // this and the other general storeSpacingFields() implementation into one
1195 // function. Need to check this in quickly for Blanca right now --12/8/98
1196 // The general storeSpacingfields() function; others invoke this internally:
1197 template<unsigned Dim, class MFLOAT>
1200  unsigned* vnodesPerDirection,
1201  bool recurse, int vnodes) {
1202  unsigned int d;
1203  int currentLocation[Dim];
1204  NDIndex<Dim> cells, verts;
1205  for (d=0; d<Dim; d++) {
1206  cells[d] = Index(gridSizes[d]-1);
1207  verts[d] = Index(gridSizes[d]);
1208  }
1209  if (!hasSpacingFields) {
1210  // allocate layouts and spacing fields
1211  FlCell =
1212  new FieldLayout<Dim>(cells, p, vnodesPerDirection, recurse, vnodes);
1213  // Note: enough guard cells only for existing Div(), etc. implementations:
1214  VertSpacings =
1216  FlVert =
1217  new FieldLayout<Dim>(verts, p, vnodesPerDirection, recurse, vnodes);
1218  // Note: enough guard cells only for existing Div(), etc. implementations:
1219  CellSpacings =
1221  }
1222  // VERTEX-VERTEX SPACINGS:
1223  BareField<Vektor<MFLOAT,Dim>,Dim>& vertSpacings = *VertSpacings;
1224  Vektor<MFLOAT,Dim> vertexSpacing;
1225  vertSpacings.Uncompress(); // Must do this prior to assign via iterator
1227  cfi_end = vertSpacings.end();
1228  for (cfi = vertSpacings.begin(); cfi != cfi_end; ++cfi) {
1229  cfi.GetCurrentLocation(currentLocation);
1230  for (d=0; d<Dim; d++)
1231  vertexSpacing(d) = (*(meshSpacing[d].find(currentLocation[d]))).second;
1232  *cfi = vertexSpacing;
1233  }
1234  // CELL-CELL SPACINGS:
1235  BareField<Vektor<MFLOAT,Dim>,Dim>& cellSpacings = *CellSpacings;
1236  Vektor<MFLOAT,Dim> cellSpacing;
1237  cellSpacings.Uncompress(); // Must do this prior to assign via iterator
1239  vfi_end = cellSpacings.end();
1240  for (vfi = cellSpacings.begin(); vfi != vfi_end; ++vfi) {
1241  vfi.GetCurrentLocation(currentLocation);
1242  for (d=0; d<Dim; d++)
1243  cellSpacing(d) = 0.5 * ((meshSpacing[d])[currentLocation[d]] +
1244  (meshSpacing[d])[currentLocation[d]-1]);
1245  *vfi = cellSpacing;
1246  }
1247  //-------------------------------------------------
1248  // Now the hard part, filling in the guard cells:
1249  //-------------------------------------------------
1250  // The easy part of the hard part is filling so that all the internal
1251  // guard layers are right:
1252  cellSpacings.fillGuardCells();
1253  vertSpacings.fillGuardCells();
1254  // The hard part of the hard part is filling the external guard layers,
1255  // using the mesh BC to figure out how:
1256  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1257  // Temporaries used in loop over faces
1258  Vektor<MFLOAT,Dim> v0,v1; v0 = 0.0; v1 = 1.0; // Used for Reflective mesh BC
1259  unsigned int face;
1260  typedef Vektor<MFLOAT,Dim> T; // Used multipple places in loop below
1261  typename BareField<T,Dim>::iterator_if cfill_i; // Iterator used below
1262  typename BareField<T,Dim>::iterator_if vfill_i; // Iterator used below
1263  int coffset, voffset; // Pointer offsets used with LField::iterator below
1264  MeshBC_E bct; // Scalar value of mesh BC used for each face in loop
1265  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1266  for (face=0; face < 2*Dim; face++) {
1267  // NDIndex's spanning elements and guard elements:
1268  NDIndex<Dim> cSlab = AddGuardCells(verts,cellSpacings.getGuardCellSizes());
1269  NDIndex<Dim> vSlab = AddGuardCells(cells,vertSpacings.getGuardCellSizes());
1270  // Shrink it down to be the guards along the active face:
1271  d = face/2;
1272  // The following bitwise AND logical test returns true if face is odd
1273  // (meaning the "high" or "right" face in the numbering convention) and
1274  // returns false if face is even (meaning the "low" or "left" face in
1275  // the numbering convention):
1276  if ( face & 1 ) {
1277  cSlab[d] = Index(verts[d].max() + 1,
1278  verts[d].max() + cellSpacings.rightGuard(d));
1279  vSlab[d] = Index(cells[d].max() + 1,
1280  cells[d].max() + vertSpacings.rightGuard(d));
1281  } else {
1282  cSlab[d] = Index(verts[d].min() - cellSpacings.leftGuard(d),
1283  verts[d].min() - 1);
1284  vSlab[d] = Index(cells[d].min() - vertSpacings.leftGuard(d),
1285  cells[d].min() - 1);
1286  }
1287  // Compute pointer offsets used with LField::iterator below:
1288  switch (MeshBC[face]) {
1289  case Periodic:
1290  bct = Periodic;
1291  if ( face & 1 ) {
1292  coffset = -verts[d].length();
1293  voffset = -cells[d].length();
1294  } else {
1295  coffset = verts[d].length();
1296  voffset = cells[d].length();
1297  }
1298  break;
1299  case Reflective:
1300  bct = Reflective;
1301  if ( face & 1 ) {
1302  coffset = 2*verts[d].max() + 1;
1303  voffset = 2*cells[d].max() + 1 - 1;
1304  } else {
1305  coffset = 2*verts[d].min() - 1;
1306  voffset = 2*cells[d].min() - 1 + 1;
1307  }
1308  break;
1309  case NoBC:
1310  bct = NoBC;
1311  if ( face & 1 ) {
1312  coffset = 2*verts[d].max() + 1;
1313  voffset = 2*cells[d].max() + 1 - 1;
1314  } else {
1315  coffset = 2*verts[d].min() - 1;
1316  voffset = 2*cells[d].min() - 1 + 1;
1317  }
1318  break;
1319  default:
1320  ERRORMSG("Cartesian::storeSpacingFields(): unknown MeshBC type" << endl);
1321  break;
1322  }
1323 
1324  // Loop over all the LField's in the BareField's:
1325  // +++++++++++++++cellSpacings++++++++++++++
1326  for (cfill_i=cellSpacings.begin_if();
1327  cfill_i!=cellSpacings.end_if(); ++cfill_i)
1328  {
1329  // Cache some things we will use often below.
1330  // Pointer to the data for the current LField (right????):
1331  LField<T,Dim> &fill = *(*cfill_i).second;
1332  // NDIndex spanning all elements in the LField, including the guards:
1333  const NDIndex<Dim> &fill_alloc = fill.getAllocated();
1334  // If the previously-created boundary guard-layer NDIndex "cSlab"
1335  // contains any of the elements in this LField (they will be guard
1336  // elements if it does), assign the values into them here by applying
1337  // the boundary condition:
1338  if ( cSlab.touches( fill_alloc ) )
1339  {
1340  // Find what it touches in this LField.
1341  NDIndex<Dim> dest = cSlab.intersect( fill_alloc );
1342 
1343  // For exrapolation boundary conditions, the boundary guard-layer
1344  // elements are typically copied from interior values; the "src"
1345  // NDIndex specifies the interior elements to be copied into the
1346  // "dest" boundary guard-layer elements (possibly after some
1347  // mathematical operations like multipplying by minus 1 later):
1348  NDIndex<Dim> src = dest; // Create dest equal to src
1349  // Now calculate the interior elements; the coffset variable
1350  // computed above makes this right for "low" or "high" face cases:
1351  src[d] = coffset - src[d];
1352 
1353  // TJW: Why is there another loop over LField's here??????????
1354  // Loop over the ones that src touches.
1355  typename BareField<T,Dim>::iterator_if from_i;
1356  for (from_i=cellSpacings.begin_if();
1357  from_i!=cellSpacings.end_if(); ++from_i)
1358  {
1359  // Cache a few things.
1360  LField<T,Dim> &from = *(*from_i).second;
1361  const NDIndex<Dim> &from_owned = from.getOwned();
1362  const NDIndex<Dim> &from_alloc = from.getAllocated();
1363  // If src touches this LField...
1364  if ( src.touches( from_owned ) )
1365  {
1366  NDIndex<Dim> from_it = src.intersect( from_alloc );
1367  NDIndex<Dim> cfill_it = dest.plugBase( from_it );
1368  // Build iterators for the copy...
1369  typedef typename LField<T,Dim>::iterator LFI;
1370  LFI lhs = fill.begin(cfill_it);
1371  LFI rhs = from.begin(from_it);
1372  // And do the assignment.
1373  if (bct == Periodic) {
1375  (lhs,rhs,OpMeshPeriodic<T>()).apply();
1376  } else {
1377  if (bct == Reflective) {
1379  (lhs,rhs,OpMeshExtrapolate<T>(v0,v1)).apply();
1380  } else {
1381  if (bct == NoBC) {
1383  (lhs,rhs,OpMeshExtrapolate<T>(v0,v0)).apply();
1384  }
1385  }
1386  }
1387  }
1388  }
1389  }
1390  }
1391  // +++++++++++++++vertSpacings++++++++++++++
1392  for (vfill_i=vertSpacings.begin_if();
1393  vfill_i!=vertSpacings.end_if(); ++vfill_i)
1394  {
1395  // Cache some things we will use often below.
1396  // Pointer to the data for the current LField (right????):
1397  LField<T,Dim> &fill = *(*vfill_i).second;
1398  // NDIndex spanning all elements in the LField, including the guards:
1399  const NDIndex<Dim> &fill_alloc = fill.getAllocated();
1400  // If the previously-created boundary guard-layer NDIndex "cSlab"
1401  // contains any of the elements in this LField (they will be guard
1402  // elements if it does), assign the values into them here by applying
1403  // the boundary condition:
1404  if ( vSlab.touches( fill_alloc ) )
1405  {
1406  // Find what it touches in this LField.
1407  NDIndex<Dim> dest = vSlab.intersect( fill_alloc );
1408 
1409  // For exrapolation boundary conditions, the boundary guard-layer
1410  // elements are typically copied from interior values; the "src"
1411  // NDIndex specifies the interior elements to be copied into the
1412  // "dest" boundary guard-layer elements (possibly after some
1413  // mathematical operations like multipplying by minus 1 later):
1414  NDIndex<Dim> src = dest; // Create dest equal to src
1415  // Now calculate the interior elements; the voffset variable
1416  // computed above makes this right for "low" or "high" face cases:
1417  src[d] = voffset - src[d];
1418 
1419  // TJW: Why is there another loop over LField's here??????????
1420  // Loop over the ones that src touches.
1421  typename BareField<T,Dim>::iterator_if from_i;
1422  for (from_i=vertSpacings.begin_if();
1423  from_i!=vertSpacings.end_if(); ++from_i)
1424  {
1425  // Cache a few things.
1426  LField<T,Dim> &from = *(*from_i).second;
1427  const NDIndex<Dim> &from_owned = from.getOwned();
1428  const NDIndex<Dim> &from_alloc = from.getAllocated();
1429  // If src touches this LField...
1430  if ( src.touches( from_owned ) )
1431  {
1432  NDIndex<Dim> from_it = src.intersect( from_alloc );
1433  NDIndex<Dim> vfill_it = dest.plugBase( from_it );
1434  // Build iterators for the copy...
1435  typedef typename LField<T,Dim>::iterator LFI;
1436  LFI lhs = fill.begin(vfill_it);
1437  LFI rhs = from.begin(from_it);
1438  // And do the assignment.
1439  if (bct == Periodic) {
1441  (lhs,rhs,OpMeshPeriodic<T>()).apply();
1442  } else {
1443  if (bct == Reflective) {
1445  (lhs,rhs,OpMeshExtrapolate<T>(v0,v1)).apply();
1446  } else {
1447  if (bct == NoBC) {
1449  (lhs,rhs,OpMeshExtrapolate<T>(v0,v0)).apply();
1450  }
1451  }
1452  }
1453  }
1454  }
1455  }
1456  }
1457 
1458  }
1459 
1460  hasSpacingFields = true; // Flag this as having been done to this object.
1461 }
1462 
1463 
1464 //-----------------------------------------------------------------------------
1465 // I/O:
1466 //-----------------------------------------------------------------------------
1467 // Formatted output of Cartesian object:
1468 template< unsigned Dim, class MFLOAT >
1469 void
1471 print(std::ostream& out)
1472 {
1473  unsigned int d;
1474  out << "======Cartesian<" << Dim << ",MFLOAT>==begin======" << std::endl;
1475  for (d=0; d < Dim; d++)
1476  out << "gridSizes[" << d << "] = " << gridSizes[d] << std::endl;
1477  out << "origin = " << origin << std::endl;
1478  for (d=0; d < Dim; d++) {
1479  out << "--------meshSpacing[" << d << "]---------" << std::endl;
1480  typename std::map<int,MFLOAT>::iterator mi;
1481  for (mi=meshSpacing[d].begin(); mi != meshSpacing[d].end(); ++mi) {
1482  out << "meshSpacing[" << d << "][" << (*mi).first << "] = "
1483  << (*mi).second << std::endl;
1484  }
1485  }
1486  for (unsigned b=0; b < (1<<Dim); b++)
1487  out << "Dvc[" << b << "] = " << Dvc[b] << std::endl;
1488  for (d=0; d < Dim; d++)
1489  out << "MeshBC[" << 2*d << "] = " << Mesh<Dim>::MeshBC_E_Names[MeshBC[2*d]]
1490  << " ; MeshBC[" << 2*d+1 << "] = " << Mesh<Dim>::MeshBC_E_Names[MeshBC[2*d+1]]
1491  << std::endl;
1492  out << "======Cartesian<" << Dim << ",MFLOAT>==end========" << std::endl;
1493 }
1494 
1495 //--------------------------------------------------------------------------
1496 // Various (Cartesian) mesh mechanisms:
1497 //--------------------------------------------------------------------------
1498 
1499 // Volume of cell indexed by NDIndex:
1500 template <unsigned Dim, class MFLOAT>
1501 MFLOAT
1503 getCellVolume(const NDIndex<Dim>& ndi) const
1504 {
1505  MFLOAT volume = 1.0;
1506  for (unsigned int d=0; d<Dim; d++)
1507  if (ndi[d].length() != 1) {
1508  ERRORMSG("Cartesian::getCellVolume() error: arg is not a NDIndex"
1509  << "specifying a single element" << endl);
1510  }
1511  else {
1512  volume *= (*(meshSpacing[d].find(ndi[d].first()))).second;
1513  }
1514  return volume;
1515 }
1516 // Field of volumes of all cells:
1517 template <unsigned Dim, class MFLOAT>
1520 getCellVolumeField(Field<MFLOAT,Dim,Cartesian<Dim,MFLOAT>,Cell>& volumes) const
1521 {
1522  // N.B.: here, other places taking Field& (in UniformCartesian, too), should
1523  // have check on domain of input Field& to make sure it's big enough to hold
1524  // all the values for this mesh object.
1525  volumes = 1.0;
1526  int currentLocation[Dim];
1527  volumes.Uncompress();
1528  // Iterate through all cells:
1530  fi_end=volumes.end();
1531  for (fi = volumes.begin(); fi != fi_end; ++fi) {
1532  fi.GetCurrentLocation(currentLocation);
1533  for (unsigned int d=0; d<Dim; d++)
1534  *fi *= (*(meshSpacing[d].find(currentLocation[d]))).second;
1535  }
1536  return volumes;
1537 }
1538 // Volume of range of cells bounded by verticies specified by input NDIndex;
1539 template <unsigned Dim, class MFLOAT>
1540 MFLOAT
1542 getVertRangeVolume(const NDIndex<Dim>& ndi) const
1543 {
1544  // Get vertex positions of extremal cells:
1545  Vektor<MFLOAT,Dim> v0, v1;
1546  unsigned int d;
1547  int i0, i1;
1548  for (d=0; d<Dim; d++) {
1549  i0 = ndi[d].first();
1550  if ( (i0 < -(int(gridSizes[d])-1)/2) ||
1551  (i0 > 3*(int(gridSizes[d])-1)/2) )
1552  ERRORMSG("Cartesian::getVertRangeVolume() error: " << ndi
1553  << " is an NDIndex ranging outside the mesh and guard layers;"
1554  << " not allowed." << endl);
1555  v0(d) = (*(meshPosition[d].find(i0))).second;
1556  i1 = ndi[d].last();
1557  if ( (i1 < -(int(gridSizes[d])-1)/2) ||
1558  (i1 > 3*(int(gridSizes[d])-1)/2) )
1559  ERRORMSG("Cartesian::getVertRangeVolume() error: " << ndi
1560  << " is an NDIndex ranging outside the mesh and guard layers;"
1561  << " not allowed." << endl);
1562  v1(d) = (*(meshPosition[d].find(i1))).second;
1563  }
1564  // Compute volume of rectangular solid beweeen these extremal vertices:
1565  MFLOAT volume = 1.0;
1566  for (d=0; d<Dim; d++) volume *= std::abs(v1(d) - v0(d));
1567  return volume;
1568 }
1569 // Volume of range of cells spanned by input NDIndex (index of cells):
1570 template <unsigned Dim, class MFLOAT>
1571 MFLOAT
1573 getCellRangeVolume(const NDIndex<Dim>& ndi) const
1574 {
1575  // Get vertex positions bounding extremal cells:
1576  Vektor<MFLOAT,Dim> v0, v1;
1577  int i0, i1;
1578  for (unsigned int d=0; d<Dim; d++) {
1579  i0 = ndi[d].first();
1580  if ( (i0 < -(int(gridSizes[d])-1)/2) ||
1581  (i0 > 3*(int(gridSizes[d])-1)/2) )
1582  ERRORMSG("Cartesian::getCellRangeVolume() error: " << ndi
1583  << " is an NDIndex ranging outside the mesh and guard layers;"
1584  << " not allowed." << endl);
1585  v0(d) = (*(meshPosition[d].find(i0))).second;
1586  i1 = ndi[d].last()+1;
1587  if ( (i1 < -(int(gridSizes[d])-1)/2) ||
1588  (i1 > 3*(int(gridSizes[d])-1)/2) )
1589  ERRORMSG("Cartesian::getCellRangeVolume() error: " << ndi
1590  << " is an NDIndex ranging outside the mesh and guard layers;"
1591  << " not allowed." << endl);
1592  v1(d) = (*(meshPosition[d].find(i1))).second;
1593  }
1594  // Compute volume of rectangular solid beweeen these extremal vertices:
1595  MFLOAT volume = 1.0;
1596  for (unsigned int d=0; d<Dim; d++) volume *= std::abs(v1(d) - v0(d));
1597  return volume;
1598 }
1599 
1600 // Nearest vertex index to (x,y,z):
1601 template <unsigned Dim, class MFLOAT>
1604 getNearestVertex(const Vektor<MFLOAT,Dim>& x) const
1605 {
1606  unsigned int d;
1607  Vektor<MFLOAT,Dim> boxMin, boxMax;
1608  for (d=0; d<Dim; d++) {
1609  int gs = (int(gridSizes[d])-1)/2;
1610  boxMin(d) = (*(meshPosition[d].find(-gs))).second;
1611  boxMax(d) = (*(meshPosition[d].find(3*gs))).second;
1612  }
1613  for (d=0; d<Dim; d++)
1614  if ( (x(d) < boxMin(d)) || (x(d) > boxMax(d)) )
1615  ERRORMSG("Cartesian::getNearestVertex() - input point is outside"
1616  << " mesh boundary and guard layers; not allowed." << endl);
1617 
1618  // Find coordinate vectors of the vertices just above and just below the
1619  // input point (extremal vertices on cell containing point);
1620  MFLOAT xVertexBelow, xVertexAbove, xVertex;
1621  int vertBelow, vertAbove, vertNearest[Dim];
1622  for (d=0; d<Dim; d++) {
1623  vertBelow = -(int(gridSizes[d])-1)/2;
1624  vertAbove = 3*(int(gridSizes[d])-1)/2;
1625  xVertexBelow = (*(meshPosition[d].find(vertBelow))).second;
1626  xVertexAbove = (*(meshPosition[d].find(vertAbove))).second;
1627  // check for out of bounds
1628  if (x(d) < xVertexBelow) {
1629  vertNearest[d] = vertBelow;
1630  continue;
1631  }
1632  if (x(d) > xVertexAbove) {
1633  vertNearest[d] = vertAbove;
1634  continue;
1635  }
1636  while (vertAbove > vertBelow+1) {
1637  vertNearest[d] = (vertAbove+vertBelow)/2;
1638  xVertex = (*(meshPosition[d].find(vertNearest[d]))).second;
1639  if (x(d) > xVertex) {
1640  vertBelow = vertNearest[d];
1641  xVertexBelow = xVertex;
1642  }
1643  else if (x(d) < xVertex) {
1644  vertAbove = vertNearest[d];
1645  xVertexAbove = xVertex;
1646  }
1647  else { // found exact match!
1648  vertAbove = vertBelow;
1649  }
1650  }
1651  if (vertAbove != vertBelow) {
1652  if ((x(d)-xVertexBelow)<(xVertexAbove-x(d))) {
1653  vertNearest[d] = vertBelow;
1654  }
1655  else {
1656  vertNearest[d] = vertAbove;
1657  }
1658  }
1659  }
1660 
1661  // Construct the NDIndex for nearest vert get its position vector:
1662  NDIndex<Dim> ndi;
1663  for (d=0; d<Dim; d++) ndi[d] = Index(vertNearest[d],vertNearest[d],1);
1664 
1665  return ndi;
1666 }
1667 // Nearest vertex index with all vertex coordinates below (x,y,z):
1668 template <unsigned Dim, class MFLOAT>
1671 getVertexBelow(const Vektor<MFLOAT,Dim>& x) const
1672 {
1673  unsigned int d;
1674  Vektor<MFLOAT,Dim> boxMin, boxMax;
1675  for (d=0; d<Dim; d++) {
1676  int gs = (int(gridSizes[d]) - 1)/2;
1677  boxMin(d) = (*(meshPosition[d].find(-gs))).second;
1678  boxMax(d) = (*(meshPosition[d].find(3*gs))).second;
1679  }
1680  for (d=0; d<Dim; d++)
1681  if ( (x(d) < boxMin(d)) || (x(d) > boxMax(d)) )
1682  ERRORMSG("Cartesian::getVertexBelow() - input point is outside"
1683  << " mesh boundary and guard layers; not allowed." << endl);
1684 
1685  // Find coordinate vectors of the vertices just below the input point;
1686  MFLOAT xVertexBelow, xVertexAbove, xVertex;
1687  int vertBelow, vertAbove, vertNearest[Dim];
1688  for (d=0; d<Dim; d++) {
1689  vertBelow = -(int(gridSizes[d])-1)/2;
1690  vertAbove = 3*(int(gridSizes[d])-1)/2;
1691  xVertexBelow = (*(meshPosition[d].find(vertBelow))).second;
1692  xVertexAbove = (*(meshPosition[d].find(vertAbove))).second;
1693  // check for out of bounds
1694  if (x(d) < xVertexBelow) {
1695  vertNearest[d] = vertBelow;
1696  continue;
1697  }
1698  if (x(d) > xVertexAbove) {
1699  vertNearest[d] = vertAbove;
1700  continue;
1701  }
1702  while (vertAbove > vertBelow+1) {
1703  vertNearest[d] = (vertAbove+vertBelow)/2;
1704  xVertex = (*(meshPosition[d].find(vertNearest[d]))).second;
1705  if (x(d) > xVertex) {
1706  vertBelow = vertNearest[d];
1707  xVertexBelow = xVertex;
1708  }
1709  else if (x(d) < xVertex) {
1710  vertAbove = vertNearest[d];
1711  xVertexAbove = xVertex;
1712  }
1713  else { // found exact match!
1714  vertAbove = vertBelow;
1715  }
1716  }
1717  if (vertAbove != vertBelow) {
1718  vertNearest[d] = vertBelow;
1719  }
1720  }
1721 
1722  // Construct the NDIndex for nearest vert get its position vector:
1723  NDIndex<Dim> ndi;
1724  for (d=0; d<Dim; d++) ndi[d] = Index(vertNearest[d],vertNearest[d],1);
1725 
1726  return ndi;
1727 }
1728 // (x,y,z) coordinates of indexed vertex:
1729 template <unsigned Dim, class MFLOAT>
1732 getVertexPosition(const NDIndex<Dim>& ndi) const
1733 {
1734  unsigned int d;
1735  int i;
1736  Vektor<MFLOAT,Dim> vertexPosition;
1737  for (d=0; d<Dim; d++) {
1738  if (ndi[d].length() != 1)
1739  ERRORMSG("Cartesian::getVertexPosition() error: " << ndi
1740  << " is not an NDIndex specifying a single element" << endl);
1741  i = ndi[d].first();
1742  if ( (i < -(int(gridSizes[d])-1)/2) ||
1743  (i > 3*(int(gridSizes[d])-1)/2) )
1744  ERRORMSG("Cartesian::getVertexPosition() error: " << ndi
1745  << " is an NDIndex outside the mesh and guard layers;"
1746  << " not allowed." << endl);
1747  vertexPosition(d) = (*(meshPosition[d].find(i))).second;
1748  }
1749  return vertexPosition;
1750 }
1751 // Field of (x,y,z) coordinates of all vertices:
1752 template <unsigned Dim, class MFLOAT>
1756  Cartesian<Dim,MFLOAT>,Vert>& vertexPositions) const
1757 {
1758  int currentLocation[Dim];
1759  Vektor<MFLOAT,Dim> vertexPosition;
1760  vertexPositions.Uncompress();
1762  fi_end = vertexPositions.end();
1763  for (fi = vertexPositions.begin(); fi != fi_end; ++fi) {
1764  // Construct a NDIndex for each field element:
1765  fi.GetCurrentLocation(currentLocation);
1766  for (unsigned int d=0; d<Dim; d++) {
1767  vertexPosition(d) = (*(meshPosition[d].find(currentLocation[d]))).second;
1768  }
1769  *fi = vertexPosition;
1770  }
1771  return vertexPositions;
1772 }
1773 
1774 // (x,y,z) coordinates of indexed cell:
1775 template <unsigned Dim, class MFLOAT>
1778 getCellPosition(const NDIndex<Dim>& ndi) const
1779 {
1780  unsigned int d;
1781  int i;
1782  Vektor<MFLOAT,Dim> cellPosition;
1783  for (d=0; d<Dim; d++) {
1784  if (ndi[d].length() != 1)
1785  ERRORMSG("Cartesian::getCellPosition() error: " << ndi
1786  << " is not an NDIndex specifying a single element" << endl);
1787  i = ndi[d].first();
1788  if ( (i < -(int(gridSizes[d])-1)/2) ||
1789  (i >= 3*(int(gridSizes[d])-1)/2) )
1790  ERRORMSG("Cartesian::getCellPosition() error: " << ndi
1791  << " is an NDIndex outside the mesh and guard layers;"
1792  << " not allowed." << endl);
1793  cellPosition(d) = 0.5 * ( (*(meshPosition[d].find(i))).second +
1794  (*(meshPosition[d].find(i+1))).second );
1795  }
1796  return cellPosition;
1797 }
1798 // Field of (x,y,z) coordinates of all cells:
1799 template <unsigned Dim, class MFLOAT>
1803  Cartesian<Dim,MFLOAT>,Cell>& cellPositions) const
1804 {
1805  int currentLocation[Dim];
1806  Vektor<MFLOAT,Dim> cellPosition;
1807  cellPositions.Uncompress();
1809  fi_end = cellPositions.end();
1810  for (fi = cellPositions.begin(); fi != fi_end; ++fi) {
1811  // Construct a NDIndex for each field element:
1812  fi.GetCurrentLocation(currentLocation);
1813  for (unsigned int d=0; d<Dim; d++) {
1814  cellPosition(d) =
1815  0.5 * ( (*(meshPosition[d].find(currentLocation[d]))).second +
1816  (*(meshPosition[d].find(currentLocation[d]+1))).second );
1817  }
1818  *fi = cellPosition;
1819  }
1820  return cellPositions;
1821 }
1822 
1823 // Vertex-vertex grid spacing of indexed cell:
1824 template <unsigned Dim, class MFLOAT>
1827 getDeltaVertex(const NDIndex<Dim>& ndi) const
1828 {
1829  // return value
1830  Vektor<MFLOAT,Dim> vertexVertexSpacing(0);
1831 
1832  for (unsigned int d=0; d<Dim; d++) {
1833  // endpoints of the index range ... make sure they are in ascending order
1834  int a = ndi[d].first();
1835  int b = ndi[d].last();
1836  if (b < a) {
1837  int tmpa = a; a = b; b = tmpa;
1838  }
1839 
1840  // make sure we have valid endpoints
1841  if (a < -((int(gridSizes[d])-1)/2) || b >= 3*(int(gridSizes[d])-1)/2) {
1842  ERRORMSG("Cartesian::getDeltaVertex() error: " << ndi
1843  << " is an NDIndex ranging outside"
1844  << " the mesh and guard layers region; not allowed."
1845  << endl);
1846  }
1847 
1848  // add up all the values between the endpoints
1849  // N.B.: following may need modification to be right for periodic Mesh BC:
1850  while (a <= b)
1851  vertexVertexSpacing[d] += (*(meshSpacing[d].find(a++))).second;
1852  }
1853 
1854  return vertexVertexSpacing;
1855 }
1856 
1857 // Field of vertex-vertex grid spacings of all cells:
1858 template <unsigned Dim, class MFLOAT>
1862  Cartesian<Dim,MFLOAT>,Cell>& vertexSpacings) const
1863 {
1864  int currentLocation[Dim];
1865  Vektor<MFLOAT,Dim> vertexVertexSpacing;
1866  vertexSpacings.Uncompress();
1868  fi_end = vertexSpacings.end();
1869  for (fi = vertexSpacings.begin(); fi != fi_end; ++fi) {
1870  fi.GetCurrentLocation(currentLocation);
1871  for (unsigned int d=0; d<Dim; d++)
1872  vertexVertexSpacing[d]=(*(meshSpacing[d].find(currentLocation[d]))).second;
1873  *fi = vertexVertexSpacing;
1874  }
1875  return vertexSpacings;
1876 }
1877 
1878 // Cell-cell grid spacing of indexed cell:
1879 template <unsigned Dim, class MFLOAT>
1882 getDeltaCell(const NDIndex<Dim>& ndi) const
1883 {
1884  // return value
1885  Vektor<MFLOAT,Dim> cellCellSpacing(0);
1886 
1887  for (unsigned int d=0; d<Dim; d++) {
1888  // endpoints of the index range ... make sure they are in ascending order
1889  int a = ndi[d].first();
1890  int b = ndi[d].last();
1891  if (b < a) {
1892  int tmpa = a; a = b; b = tmpa;
1893  }
1894 
1895  // make sure the endpoints are valid
1896  if (a <= -(int(gridSizes[d])-1)/2 || b >= 3*(int(gridSizes[d])-1)/2) {
1897  ERRORMSG("Cartesian::getDeltaCell() error: " << ndi
1898  << " is an NDIndex ranging outside"
1899  << " the mesh and guard layers region; not allowed."
1900  << endl);
1901  }
1902 
1903  // add up the contributions along the interval ...
1904  while (a <= b) {
1905  cellCellSpacing[d] += ((*(meshSpacing[d].find(a))).second +
1906  (*(meshSpacing[d].find(a-1))).second) * 0.5;
1907  a++;
1908  }
1909  }
1910  return cellCellSpacing;
1911 }
1912 
1913 // Field of cell-cell grid spacings of all cells:
1914 template <unsigned Dim, class MFLOAT>
1918  Cartesian<Dim,MFLOAT>,Vert>& cellSpacings) const
1919 {
1920  int currentLocation[Dim];
1921  Vektor<MFLOAT,Dim> cellCellSpacing;
1922  cellSpacings.Uncompress();
1924  fi_end = cellSpacings.end();
1925  for (fi = cellSpacings.begin(); fi != fi_end; ++fi) {
1926  fi.GetCurrentLocation(currentLocation);
1927  for (unsigned int d=0; d<Dim; d++)
1928  cellCellSpacing[d]+=((*(meshSpacing[d].find(currentLocation[d]))).second +
1929  (*(meshSpacing[d].find(currentLocation[d]-1))).second) * 0.5;
1930  *fi = cellCellSpacing;
1931  }
1932  return cellSpacings;
1933 }
1934 // Array of surface normals to cells adjoining indexed cell:
1935 template <unsigned Dim, class MFLOAT>
1938 getSurfaceNormals(const NDIndex<Dim>& /*ndi*/) const
1939 {
1940  Vektor<MFLOAT,Dim>* surfaceNormals = new Vektor<MFLOAT,Dim>[2*Dim];
1941  unsigned int d, i;
1942  for (d=0; d<Dim; d++) {
1943  for (i=0; i<Dim; i++) {
1944  surfaceNormals[2*d](i) = 0.0;
1945  surfaceNormals[2*d+1](i) = 0.0;
1946  }
1947  surfaceNormals[2*d](d) = -1.0;
1948  surfaceNormals[2*d+1](d) = 1.0;
1949  }
1950  return surfaceNormals;
1951 }
1952 // Array of (pointers to) Fields of surface normals to all cells:
1953 template <unsigned Dim, class MFLOAT>
1954 void
1958  surfaceNormalsFields ) const
1959 {
1960  Vektor<MFLOAT,Dim>* surfaceNormals = new Vektor<MFLOAT,Dim>[2*Dim];
1961  unsigned int d, i;
1962  for (d=0; d<Dim; d++) {
1963  for (i=0; i<Dim; i++) {
1964  surfaceNormals[2*d](i) = 0.0;
1965  surfaceNormals[2*d+1](i) = 0.0;
1966  }
1967  surfaceNormals[2*d](d) = -1.0;
1968  surfaceNormals[2*d+1](d) = 1.0;
1969  }
1970  for (d=0; d<2*Dim; d++) assign((*(surfaceNormalsFields[d])),
1971  surfaceNormals[d]);
1972  // return surfaceNormalsFields;
1973 }
1974 // Similar functions, but specify the surface normal to a single face, using
1975 // the following numbering convention: 0 means low face of 1st dim, 1 means
1976 // high face of 1st dim, 2 means low face of 2nd dim, 3 means high face of
1977 // 2nd dim, and so on:
1978 // Surface normal to face on indexed cell:
1979 template <unsigned Dim, class MFLOAT>
1982 getSurfaceNormal(const NDIndex<Dim>& /*ndi*/, unsigned face) const
1983 {
1984  Vektor<MFLOAT,Dim> surfaceNormal;
1985  unsigned int d;
1986  // The following bitwise AND logical test returns true if face is odd
1987  // (meaning the "high" or "right" face in the numbering convention) and
1988  // returns false if face is even (meaning the "low" or "left" face in the
1989  // numbering convention):
1990  if ( face & 1 ) {
1991  for (d=0; d<Dim; d++) {
1992  if ((face/2) == d) {
1993  surfaceNormal(face) = -1.0;
1994  } else {
1995  surfaceNormal(face) = 0.0;
1996  }
1997  }
1998  } else {
1999  for (d=0; d<Dim; d++) {
2000  if ((face/2) == d) {
2001  surfaceNormal(face) = 1.0;
2002  } else {
2003  surfaceNormal(face) = 0.0;
2004  }
2005  }
2006  }
2007  return surfaceNormal;
2008 }
2009 // Field of surface normals to face on all cells:
2010 template <unsigned Dim, class MFLOAT>
2014  Cartesian<Dim,MFLOAT>,Cell>& surfaceNormalField,
2015  unsigned face) const
2016 {
2017  Vektor<MFLOAT,Dim> surfaceNormal;
2018  unsigned int d;
2019  // The following bitwise AND logical test returns true if face is odd
2020  // (meaning the "high" or "right" face in the numbering convention) and
2021  // returns false if face is even (meaning the "low" or "left" face in the
2022  // numbering convention):
2023  if ( face & 1 ) {
2024  for (d=0; d<Dim; d++) {
2025  if ((face/2) == d) {
2026  surfaceNormal(face) = -1.0;
2027  } else {
2028  surfaceNormal(face) = 0.0;
2029  }
2030  }
2031  } else {
2032  for (d=0; d<Dim; d++) {
2033  if ((face/2) == d) {
2034  surfaceNormal(face) = 1.0;
2035  } else {
2036  surfaceNormal(face) = 0.0;
2037  }
2038  }
2039  }
2040  surfaceNormalField = surfaceNormal;
2041  return surfaceNormalField;
2042 }
2043 
2044 // Set up mesh boundary conditions:
2045 // Face specifies the mesh face, following usual numbering convention.
2046 // MeshBC_E "type" specifies the kind of BC reflective/periodic/none.
2047 // One face at a time:
2048 template <unsigned Dim, class MFLOAT>
2049 void
2051 set_MeshBC(unsigned face, MeshBC_E meshBCType)
2052 {
2053  MeshBC[face] = meshBCType;
2054  updateMeshSpacingGuards(face);
2055  // if spacing fields allocated, we must update values
2056  if (hasSpacingFields) storeSpacingFields();
2057 }
2058 // All faces at once:
2059 template <unsigned Dim, class MFLOAT>
2060 void
2062 set_MeshBC(MeshBC_E* meshBCTypes)
2063 {
2064  for (unsigned int face=0; face < 2*Dim; face++) {
2065  MeshBC[face] = meshBCTypes[face];
2066  updateMeshSpacingGuards(face);
2067  }
2068  // if spacing fields allocated, we must update values
2069  if (hasSpacingFields) storeSpacingFields();
2070 }
2071 // Helper function to update guard layer values of mesh spacings:
2072 template <unsigned Dim, class MFLOAT>
2073 void
2075 updateMeshSpacingGuards(int face)
2076 {
2077  // Apply the current state of the mesh BC to add guards to meshSpacings map
2078  // Assume worst case of needing ngridpts/2 guard layers (for periodic, most
2079  // likely):
2080  int d = face/2;
2081  unsigned int cell, guardLayer;
2082  // The following bitwise AND logical test returns true if face is odd
2083  // (meaning the "high" or "right" face in the numbering convention) and
2084  // returns false if face is even (meaning the "low" or "left" face in
2085  // the numbering convention):
2086  if ( face & 1 ) {
2087  // "High" guard cells:
2088  switch (MeshBC[d*2]) {
2089  case Periodic:
2090  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2091  cell = gridSizes[d] - 1 + guardLayer;
2092  (meshSpacing[d])[cell] = (meshSpacing[d])[guardLayer];
2093  (meshPosition[d])[cell+1] = (meshPosition[d])[cell] +
2094  (meshSpacing[d])[cell];
2095  }
2096  break;
2097  case Reflective:
2098  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2099  cell = gridSizes[d] - 1 + guardLayer;
2100  (meshSpacing[d])[cell] = (meshSpacing[d])[cell - guardLayer - 1];
2101  (meshPosition[d])[cell+1] = (meshPosition[d])[cell] +
2102  (meshSpacing[d])[cell];
2103  }
2104  break;
2105  case NoBC:
2106  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2107  cell = gridSizes[d] - 1 + guardLayer;
2108  (meshSpacing[d])[cell] = 0;
2109  (meshPosition[d])[cell+1] = (meshPosition[d])[cell] +
2110  (meshSpacing[d])[cell];
2111  }
2112  break;
2113  default:
2114  ERRORMSG("Cartesian::updateMeshSpacingGuards(): unknown MeshBC type"
2115  << endl);
2116  break;
2117  }
2118  }
2119  else {
2120  // "Low" guard cells:
2121  switch (MeshBC[d]) {
2122  case Periodic:
2123  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2124  cell = -1 - guardLayer;
2125  (meshSpacing[d])[cell] = (meshSpacing[d])[gridSizes[d] + cell];
2126  (meshPosition[d])[cell] = (meshPosition[d])[cell+1] -
2127  (meshSpacing[d])[cell];
2128  }
2129  break;
2130  case Reflective:
2131  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2132  cell = -1 - guardLayer;
2133  (meshSpacing[d])[cell] = (meshSpacing[d])[-cell - 1];
2134  (meshPosition[d])[cell] = (meshPosition[d])[cell+1] -
2135  (meshSpacing[d])[cell];
2136  }
2137  break;
2138  case NoBC:
2139  for (guardLayer = 0; guardLayer <= (gridSizes[d]-1)/2; guardLayer++) {
2140  cell = -1 - guardLayer;
2141  (meshSpacing[d])[cell] = 0;
2142  (meshPosition[d])[cell] = (meshPosition[d])[cell+1] -
2143  (meshSpacing[d])[cell];
2144  }
2145  break;
2146  default:
2147  ERRORMSG("Cartesian::updateMeshSpacingGuards(): unknown MeshBC type"
2148  << endl);
2149  break;
2150  }
2151  }
2152 }
2153 
2154 // Get mesh boundary conditions:
2155 // One face at a time
2156 template <unsigned Dim, class MFLOAT>
2157 MeshBC_E
2159 get_MeshBC(unsigned face) const
2160 {
2161  MeshBC_E mb;
2162  mb = MeshBC[face];
2163  return mb;
2164 }
2165 // All faces at once
2166 template <unsigned Dim, class MFLOAT>
2167 MeshBC_E*
2169 get_MeshBC() const
2170 {
2171  MeshBC_E* mb = new MeshBC_E[2*Dim];
2172  for (unsigned int b=0; b < 2*Dim; b++) mb[b] = MeshBC[b];
2173  return mb;
2174 }
2175 
2176 
2177 
2178 //--------------------------------------------------------------------------
2179 // Global functions
2180 //--------------------------------------------------------------------------
2181 
2182 
2183 //*****************************************************************************
2184 // Stuff taken from old Cartesian.h, modified for new nonuniform Cartesian:
2185 //*****************************************************************************
2186 
2187 //----------------------------------------------------------------------
2188 // Divergence Vektor/Vert -> Scalar/Cell
2189 //----------------------------------------------------------------------
2190 template < class T, class MFLOAT >
2194 {
2195  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2196  BareField<Vektor<MFLOAT,1U>,1U>& vertSpacings = *(x.get_mesh().VertSpacings);
2197  const NDIndex<1U>& domain = r.getDomain();
2198  Index I = domain[0];
2199  r[I] =
2200  dot(x[I ], x.get_mesh().Dvc[0]/vertSpacings[I]) +
2201  dot(x[I+1], x.get_mesh().Dvc[1]/vertSpacings[I]);
2202  return r;
2203 }
2204 //----------------------------------------------------------------------
2205 template < class T, class MFLOAT >
2209 {
2210  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2211  BareField<Vektor<MFLOAT,2U>,2U>& vertSpacings = *(x.get_mesh().VertSpacings);
2212  const NDIndex<2U>& domain = r.getDomain();
2213  Index I = domain[0];
2214  Index J = domain[1];
2215  r[I][J] =
2216  dot(x[I ][J ], x.get_mesh().Dvc[0]/vertSpacings[I][J]) +
2217  dot(x[I+1][J ], x.get_mesh().Dvc[1]/vertSpacings[I][J]) +
2218  dot(x[I ][J+1], x.get_mesh().Dvc[2]/vertSpacings[I][J]) +
2219  dot(x[I+1][J+1], x.get_mesh().Dvc[3]/vertSpacings[I][J]);
2220  return r;
2221 }
2222 //----------------------------------------------------------------------
2223 template < class T, class MFLOAT >
2227 {
2228  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2229  BareField<Vektor<MFLOAT,3U>,3U>& vertSpacings = *(x.get_mesh().VertSpacings);
2230  const NDIndex<3U>& domain = r.getDomain();
2231  Index I = domain[0];
2232  Index J = domain[1];
2233  Index K = domain[2];
2234  r[I][J][K] =
2235  dot(x[I ][J ][K ], x.get_mesh().Dvc[0]/vertSpacings[I][J][K]) +
2236  dot(x[I+1][J ][K ], x.get_mesh().Dvc[1]/vertSpacings[I][J][K]) +
2237  dot(x[I ][J+1][K ], x.get_mesh().Dvc[2]/vertSpacings[I][J][K]) +
2238  dot(x[I+1][J+1][K ], x.get_mesh().Dvc[3]/vertSpacings[I][J][K]) +
2239  dot(x[I ][J ][K+1], x.get_mesh().Dvc[4]/vertSpacings[I][J][K]) +
2240  dot(x[I+1][J ][K+1], x.get_mesh().Dvc[5]/vertSpacings[I][J][K]) +
2241  dot(x[I ][J+1][K+1], x.get_mesh().Dvc[6]/vertSpacings[I][J][K]) +
2242  dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]/vertSpacings[I][J][K]);
2243  return r;
2244 }
2245 //----------------------------------------------------------------------
2246 // Divergence Vektor/Cell -> Scalar/Vert
2247 //----------------------------------------------------------------------
2248 template < class T, class MFLOAT >
2252 {
2253  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2254  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings = *(x.get_mesh().CellSpacings);
2255  const NDIndex<1U>& domain = r.getDomain();
2256  Index I = domain[0];
2257  r[I] =
2258  dot(x[I-1], x.get_mesh().Dvc[0]/cellSpacings[I]) +
2259  dot(x[I ], x.get_mesh().Dvc[1]/cellSpacings[I]);
2260  return r;
2261 }
2262 //----------------------------------------------------------------------
2263 template < class T, class MFLOAT >
2267 {
2268  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2269  BareField<Vektor<MFLOAT,2U>,2U>& cellSpacings = *(x.get_mesh().CellSpacings);
2270  const NDIndex<2U>& domain = r.getDomain();
2271  Index I = domain[0];
2272  Index J = domain[1];
2273  r[I][J] =
2274  dot(x[I-1][J-1], x.get_mesh().Dvc[0]/cellSpacings[I][J]) +
2275  dot(x[I ][J-1], x.get_mesh().Dvc[1]/cellSpacings[I][J]) +
2276  dot(x[I-1][J ], x.get_mesh().Dvc[2]/cellSpacings[I][J]) +
2277  dot(x[I ][J ], x.get_mesh().Dvc[3]/cellSpacings[I][J]);
2278  return r;
2279 }
2280 //----------------------------------------------------------------------
2281 template < class T, class MFLOAT >
2285 {
2286  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2287  BareField<Vektor<MFLOAT,3U>,3U>& cellSpacings = *(x.get_mesh().CellSpacings);
2288  const NDIndex<3U>& domain = r.getDomain();
2289  Index I = domain[0];
2290  Index J = domain[1];
2291  Index K = domain[2];
2292  r[I][J][K] =
2293  dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]/cellSpacings[I][J][K]) +
2294  dot(x[I ][J-1][K-1], x.get_mesh().Dvc[1]/cellSpacings[I][J][K]) +
2295  dot(x[I-1][J ][K-1], x.get_mesh().Dvc[2]/cellSpacings[I][J][K]) +
2296  dot(x[I ][J ][K-1], x.get_mesh().Dvc[3]/cellSpacings[I][J][K]) +
2297  dot(x[I-1][J-1][K ], x.get_mesh().Dvc[4]/cellSpacings[I][J][K]) +
2298  dot(x[I ][J-1][K ], x.get_mesh().Dvc[5]/cellSpacings[I][J][K]) +
2299  dot(x[I-1][J ][K ], x.get_mesh().Dvc[6]/cellSpacings[I][J][K]) +
2300  dot(x[I ][J ][K ], x.get_mesh().Dvc[7]/cellSpacings[I][J][K]);
2301  return r;
2302 }
2303 
2304 
2305 // TJW: I've attempted to update these differential operators from uniform
2306 // cartesian implementations to workfor (nonuniform) Cartesian class, but they
2307 // may really need to get changed in other ways, such as something besides
2308 // simple centered differncing for cell-cell and vert-vert cases. Flag these
2309 // operator implementations since they may be a source of trouble until tested
2310 // and debugged further. The Grad() operators, especially, may be wrong. All
2311 // that being said, I have tested quite a few of these, including the following
2312 // two needed by Tecolote: 1) Div SymTenzor/Cell->Vektor/Vert 2) Grad
2313 // Vektor/Vert->Tenzor/Cell
2314 
2315 // BEGIN FLAGGED DIFFOPS REGION I
2316 
2317 //----------------------------------------------------------------------
2318 // Divergence Vektor/Vert -> Scalar/Vert
2319 // (Re-coded 1/20/1998 tjw. Hope it's right....???)
2320 //----------------------------------------------------------------------
2321 template < class T, class MFLOAT >
2325 {
2326  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2327  BareField<Vektor<MFLOAT,1U>,1U>& vS = *(x.get_mesh().VertSpacings);
2328  const NDIndex<1U>& domain = r.getDomain();
2329  Index I = domain[0];
2330  Vektor<MFLOAT,1U> idx;
2331  idx[0] = 1.0;
2332  r[I] = dot(idx, (x[I+1] - x[I-1])/(vS[I ] + vS[I-1]));
2333  return r;
2334 }
2335 //----------------------------------------------------------------------
2336 template < class T, class MFLOAT >
2340 {
2341  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2342  BareField<Vektor<MFLOAT,2U>,2U>& vS = *(x.get_mesh().VertSpacings);
2343  const NDIndex<2U>& domain = r.getDomain();
2344  Index I = domain[0];
2345  Index J = domain[1];
2346  Vektor<MFLOAT,2U> idx,idy;
2347  idx[0] = 1.0;
2348  idx[1] = 0.0;
2349  idy[0] = 0.0;
2350  idy[1] = 1.0;
2351  r[I][J] =
2352  dot(idx, (x[I+1][J ] - x[I-1][J ])/(vS[I ][J ] + vS[I-1][J ])) +
2353  dot(idy, (x[I ][J+1] - x[I ][J-1])/(vS[I ][J ] + vS[I ][J-1]));
2354  return r;
2355 }
2356 //----------------------------------------------------------------------
2357 template < class T, class MFLOAT >
2361 {
2362  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2363  BareField<Vektor<MFLOAT,3U>,3U>& vS = *(x.get_mesh().VertSpacings);
2364  const NDIndex<3U>& domain = r.getDomain();
2365  Index I = domain[0];
2366  Index J = domain[1];
2367  Index K = domain[2];
2368  Vektor<MFLOAT,3U> idx,idy,idz;
2369  idx[0] = 1.0;
2370  idx[1] = 0.0;
2371  idx[2] = 0.0;
2372  idy[0] = 0.0;
2373  idy[1] = 1.0;
2374  idy[2] = 0.0;
2375  idz[0] = 0.0;
2376  idz[1] = 0.0;
2377  idz[2] = 1.0;
2378  r[I][J][K] =
2379  dot(idx, ((x[I+1][J ][K ] - x[I-1][J ][K ])/
2380  (vS[I ][J ][K ] + vS[I-1][J ][K ]))) +
2381  dot(idy, ((x[I ][J+1][K ] - x[I ][J-1][K ])/
2382  (vS[I ][J ][K ] + vS[I ][J-1][K ]))) +
2383  dot(idz, ((x[I ][J ][K+1] - x[I ][J ][K-1])/
2384  (vS[I ][J ][K ] + vS[I ][J ][K-1])));
2385  return r;
2386 }
2387 //----------------------------------------------------------------------
2388 // Divergence Vektor/Cell -> Scalar/Cell (???right? tjw 3/10/97)
2389 // (Re-coded 1/20/1998 tjw. Hope it's right....???)
2390 // TJW 5/14/1999: I think there's a bug here, in the denominators. For example,
2391 // the 1D denom should be (cs[I+1] + cs[I]) as I see it.
2392 // This one wasn't in test/simple/TestCartesian.cpp.
2393 //----------------------------------------------------------------------
2394 template < class T, class MFLOAT >
2398 {
2399  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2400  BareField<Vektor<MFLOAT,1U>,1U>& cS = *(x.get_mesh().CellSpacings);
2401  const NDIndex<1U>& domain = r.getDomain();
2402  Index I = domain[0];
2403  Vektor<MFLOAT,1U> idx;
2404  idx[0] = 1.0;
2405  r[I] = dot(idx, (x[I+1] - x[I-1])/(cS[I ] + cS[I-1]));
2406  return r;
2407 }
2408 //----------------------------------------------------------------------
2409 template < class T, class MFLOAT >
2413 {
2414  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2415  BareField<Vektor<MFLOAT,2U>,2U>& cS = *(x.get_mesh().CellSpacings);
2416  const NDIndex<2U>& domain = r.getDomain();
2417  Index I = domain[0];
2418  Index J = domain[1];
2419  Vektor<MFLOAT,2U> idx,idy;
2420  idx[0] = 1.0;
2421  idx[1] = 0.0;
2422  idy[0] = 0.0;
2423  idy[1] = 1.0;
2424  r[I][J] =
2425  dot(idx, (x[I+1][J ] - x[I-1][J ])/(cS[I ][J ] + cS[I-1][J ])) +
2426  dot(idy, (x[I ][J+1] - x[I ][J-1])/(cS[I ][J ] + cS[I ][J-1]));
2427  return r;
2428 }
2429 //----------------------------------------------------------------------
2430 template < class T, class MFLOAT >
2434 {
2435  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2436  BareField<Vektor<MFLOAT,3U>,3U>& cS = *(x.get_mesh().CellSpacings);
2437  const NDIndex<3U>& domain = r.getDomain();
2438  Index I = domain[0];
2439  Index J = domain[1];
2440  Index K = domain[2];
2441  Vektor<MFLOAT,3U> idx,idy,idz;
2442  idx[0] = 1.0;
2443  idx[1] = 0.0;
2444  idx[2] = 0.0;
2445  idy[0] = 0.0;
2446  idy[1] = 1.0;
2447  idy[2] = 0.0;
2448  idz[0] = 0.0;
2449  idz[1] = 0.0;
2450  idz[2] = 1.0;
2451  r[I][J][K] =
2452  dot(idx, ((x[I+1][J ][K ] - x[I-1][J ][K ])/
2453  (cS[I ][J ][K ] + cS[I-1][J ][K ]))) +
2454  dot(idy, ((x[I ][J+1][K ] - x[I ][J-1][K ])/
2455  (cS[I ][J ][K ] + cS[I ][J-1][K ]))) +
2456  dot(idz, ((x[I ][J ][K+1] - x[I ][J ][K-1])/
2457  (cS[I ][J ][K ] + cS[I ][J ][K-1])));
2458  return r;
2459 }
2460 //----------------------------------------------------------------------
2461 // Divergence Tenzor/Vert -> Vektor/Cell (???dot right thing? tjw 1/20/1998)
2462 //----------------------------------------------------------------------
2463 template < class T, class MFLOAT >
2467 {
2468  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2469  BareField<Vektor<MFLOAT,1U>,1U>& vertSpacings = *(x.get_mesh().VertSpacings);
2470  const NDIndex<1U>& domain = r.getDomain();
2471  Index I = domain[0];
2472  r[I] =
2473  dot(x[I ], x.get_mesh().Dvc[0]/vertSpacings[I]) +
2474  dot(x[I+1], x.get_mesh().Dvc[1]/vertSpacings[I]);
2475  return r;
2476 }
2477 //----------------------------------------------------------------------
2478 template < class T, class MFLOAT >
2482 {
2483  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2484  BareField<Vektor<MFLOAT,2U>,2U>& vertSpacings = *(x.get_mesh().VertSpacings);
2485  const NDIndex<2U>& domain = r.getDomain();
2486  Index I = domain[0];
2487  Index J = domain[1];
2488  r[I][J] =
2489  dot(x[I ][J ], x.get_mesh().Dvc[0]/vertSpacings[I][J]) +
2490  dot(x[I+1][J ], x.get_mesh().Dvc[1]/vertSpacings[I][J]) +
2491  dot(x[I ][J+1], x.get_mesh().Dvc[2]/vertSpacings[I][J]) +
2492  dot(x[I+1][J+1], x.get_mesh().Dvc[3]/vertSpacings[I][J]);
2493  return r;
2494 }
2495 //----------------------------------------------------------------------
2496 template < class T, class MFLOAT >
2500 {
2501  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2502  BareField<Vektor<MFLOAT,3U>,3U>& vertSpacings = *(x.get_mesh().VertSpacings);
2503  const NDIndex<3U>& domain = r.getDomain();
2504  Index I = domain[0];
2505  Index J = domain[1];
2506  Index K = domain[2];
2507  r[I][J][K] =
2508  dot(x[I ][J ][K ], x.get_mesh().Dvc[0]/vertSpacings[I][J][K]) +
2509  dot(x[I+1][J ][K ], x.get_mesh().Dvc[1]/vertSpacings[I][J][K]) +
2510  dot(x[I ][J+1][K ], x.get_mesh().Dvc[2]/vertSpacings[I][J][K]) +
2511  dot(x[I+1][J+1][K ], x.get_mesh().Dvc[3]/vertSpacings[I][J][K]) +
2512  dot(x[I ][J ][K+1], x.get_mesh().Dvc[4]/vertSpacings[I][J][K]) +
2513  dot(x[I+1][J ][K+1], x.get_mesh().Dvc[5]/vertSpacings[I][J][K]) +
2514  dot(x[I ][J+1][K+1], x.get_mesh().Dvc[6]/vertSpacings[I][J][K]) +
2515  dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]/vertSpacings[I][J][K]);
2516  return r;
2517 }
2518 //----------------------------------------------------------------------
2519 // Divergence SymTenzor/Vert -> Vektor/Cell (???dot right thing? tjw 1/20/1998)
2520 //----------------------------------------------------------------------
2521 template < class T, class MFLOAT >
2525 {
2526  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2527  BareField<Vektor<MFLOAT,1U>,1U>& vertSpacings = *(x.get_mesh().VertSpacings);
2528  const NDIndex<1U>& domain = r.getDomain();
2529  Index I = domain[0];
2530  r[I] =
2531  dot(x[I ], x.get_mesh().Dvc[0]/vertSpacings[I]) +
2532  dot(x[I+1], x.get_mesh().Dvc[1]/vertSpacings[I]);
2533  return r;
2534 }
2535 //----------------------------------------------------------------------
2536 template < class T, class MFLOAT >
2540 {
2541  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2542  BareField<Vektor<MFLOAT,2U>,2U>& vertSpacings = *(x.get_mesh().VertSpacings);
2543  const NDIndex<2U>& domain = r.getDomain();
2544  Index I = domain[0];
2545  Index J = domain[1];
2546  r[I][J] =
2547  dot(x[I ][J ], x.get_mesh().Dvc[0]/vertSpacings[I][J]) +
2548  dot(x[I+1][J ], x.get_mesh().Dvc[1]/vertSpacings[I][J]) +
2549  dot(x[I ][J+1], x.get_mesh().Dvc[2]/vertSpacings[I][J]) +
2550  dot(x[I+1][J+1], x.get_mesh().Dvc[3]/vertSpacings[I][J]);
2551  return r;
2552 }
2553 //----------------------------------------------------------------------
2554 template < class T, class MFLOAT >
2558 {
2559  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2560  BareField<Vektor<MFLOAT,3U>,3U>& vertSpacings = *(x.get_mesh().VertSpacings);
2561  const NDIndex<3U>& domain = r.getDomain();
2562  Index I = domain[0];
2563  Index J = domain[1];
2564  Index K = domain[2];
2565  r[I][J][K] =
2566  dot(x[I ][J ][K ], x.get_mesh().Dvc[0]/vertSpacings[I][J][K]) +
2567  dot(x[I+1][J ][K ], x.get_mesh().Dvc[1]/vertSpacings[I][J][K]) +
2568  dot(x[I ][J+1][K ], x.get_mesh().Dvc[2]/vertSpacings[I][J][K]) +
2569  dot(x[I+1][J+1][K ], x.get_mesh().Dvc[3]/vertSpacings[I][J][K]) +
2570  dot(x[I ][J ][K+1], x.get_mesh().Dvc[4]/vertSpacings[I][J][K]) +
2571  dot(x[I+1][J ][K+1], x.get_mesh().Dvc[5]/vertSpacings[I][J][K]) +
2572  dot(x[I ][J+1][K+1], x.get_mesh().Dvc[6]/vertSpacings[I][J][K]) +
2573  dot(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]/vertSpacings[I][J][K]);
2574  return r;
2575 }
2576 
2577 //----------------------------------------------------------------------
2578 // Divergence Tenzor/Cell -> Vektor/Vert (???dot right thing? tjw 1/20/1998)
2579 //----------------------------------------------------------------------
2580 template < class T, class MFLOAT >
2584 {
2585  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2586  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings = *(x.get_mesh().CellSpacings);
2587  const NDIndex<1U>& domain = r.getDomain();
2588  Index I = domain[0];
2589  r[I] =
2590  dot(x[I-1], x.get_mesh().Dvc[0]/cellSpacings[I]) +
2591  dot(x[I ], x.get_mesh().Dvc[1]/cellSpacings[I]);
2592  return r;
2593 }
2594 //----------------------------------------------------------------------
2595 template < class T, class MFLOAT >
2599 {
2600  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2601  BareField<Vektor<MFLOAT,2U>,2U>& cellSpacings = *(x.get_mesh().CellSpacings);
2602  const NDIndex<2U>& domain = r.getDomain();
2603  Index I = domain[0];
2604  Index J = domain[1];
2605  r[I][J] =
2606  dot(x[I-1][J-1], x.get_mesh().Dvc[0]/cellSpacings[I][J]) +
2607  dot(x[I ][J-1], x.get_mesh().Dvc[1]/cellSpacings[I][J]) +
2608  dot(x[I-1][J ], x.get_mesh().Dvc[2]/cellSpacings[I][J]) +
2609  dot(x[I ][J ], x.get_mesh().Dvc[3]/cellSpacings[I][J]);
2610  return r;
2611 }
2612 //----------------------------------------------------------------------
2613 template < class T, class MFLOAT >
2617 {
2618  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2619  BareField<Vektor<MFLOAT,3U>,3U>& cellSpacings = *(x.get_mesh().CellSpacings);
2620  const NDIndex<3U>& domain = r.getDomain();
2621  Index I = domain[0];
2622  Index J = domain[1];
2623  Index K = domain[2];
2624  r[I][J][K] =
2625  dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]/cellSpacings[I][J][K]) +
2626  dot(x[I ][J-1][K-1], x.get_mesh().Dvc[1]/cellSpacings[I][J][K]) +
2627  dot(x[I-1][J ][K-1], x.get_mesh().Dvc[2]/cellSpacings[I][J][K]) +
2628  dot(x[I ][J ][K-1], x.get_mesh().Dvc[3]/cellSpacings[I][J][K]) +
2629  dot(x[I-1][J-1][K ], x.get_mesh().Dvc[4]/cellSpacings[I][J][K]) +
2630  dot(x[I ][J-1][K ], x.get_mesh().Dvc[5]/cellSpacings[I][J][K]) +
2631  dot(x[I-1][J ][K ], x.get_mesh().Dvc[6]/cellSpacings[I][J][K]) +
2632  dot(x[I ][J ][K ], x.get_mesh().Dvc[7]/cellSpacings[I][J][K]);
2633  return r;
2634 }
2635 
2636 //----------------------------------------------------------------------
2637 // Divergence SymTenzor/Cell -> Vektor/Vert (???dot right thing? tjw 1/20/1998)
2638 //----------------------------------------------------------------------
2639 template < class T, class MFLOAT >
2643 {
2644  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2645  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings = *(x.get_mesh().CellSpacings);
2646  const NDIndex<1U>& domain = r.getDomain();
2647  Index I = domain[0];
2648  r[I] =
2649  dot(x[I-1], x.get_mesh().Dvc[0]/cellSpacings[I]) +
2650  dot(x[I ], x.get_mesh().Dvc[1]/cellSpacings[I]);
2651  return r;
2652 }
2653 //----------------------------------------------------------------------
2654 template < class T, class MFLOAT >
2658 {
2659  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2660  BareField<Vektor<MFLOAT,2U>,2U>& cellSpacings = *(x.get_mesh().CellSpacings);
2661  const NDIndex<2U>& domain = r.getDomain();
2662  Index I = domain[0];
2663  Index J = domain[1];
2664  r[I][J] =
2665  dot(x[I-1][J-1], x.get_mesh().Dvc[0]/cellSpacings[I][J]) +
2666  dot(x[I ][J-1], x.get_mesh().Dvc[1]/cellSpacings[I][J]) +
2667  dot(x[I-1][J ], x.get_mesh().Dvc[2]/cellSpacings[I][J]) +
2668  dot(x[I ][J ], x.get_mesh().Dvc[3]/cellSpacings[I][J]);
2669  return r;
2670 }
2671 //----------------------------------------------------------------------
2672 template < class T, class MFLOAT >
2676 {
2677  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2678  BareField<Vektor<MFLOAT,3U>,3U>& cellSpacings = *(x.get_mesh().CellSpacings);
2679  const NDIndex<3U>& domain = r.getDomain();
2680  Index I = domain[0];
2681  Index J = domain[1];
2682  Index K = domain[2];
2683  r[I][J][K] =
2684  dot(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]/cellSpacings[I][J][K]) +
2685  dot(x[I ][J-1][K-1], x.get_mesh().Dvc[1]/cellSpacings[I][J][K]) +
2686  dot(x[I-1][J ][K-1], x.get_mesh().Dvc[2]/cellSpacings[I][J][K]) +
2687  dot(x[I ][J ][K-1], x.get_mesh().Dvc[3]/cellSpacings[I][J][K]) +
2688  dot(x[I-1][J-1][K ], x.get_mesh().Dvc[4]/cellSpacings[I][J][K]) +
2689  dot(x[I ][J-1][K ], x.get_mesh().Dvc[5]/cellSpacings[I][J][K]) +
2690  dot(x[I-1][J ][K ], x.get_mesh().Dvc[6]/cellSpacings[I][J][K]) +
2691  dot(x[I ][J ][K ], x.get_mesh().Dvc[7]/cellSpacings[I][J][K]);
2692  return r;
2693 }
2694 
2695 // END FLAGGED DIFFOPS REGION I
2696 
2697 //----------------------------------------------------------------------
2698 // Grad Scalar/Vert -> Vektor/Cell
2699 //----------------------------------------------------------------------
2700 template < class T, class MFLOAT >
2704 {
2705  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2706  BareField<Vektor<MFLOAT,1U>,1U>& vertSpacings = *(x.get_mesh().VertSpacings);
2707  const NDIndex<1U>& domain = r.getDomain();
2708  Index I = domain[0];
2709  r[I] = (x[I ]*x.get_mesh().Dvc[0] +
2710  x[I+1]*x.get_mesh().Dvc[1])/vertSpacings[I];
2711  return r;
2712 }
2713 //----------------------------------------------------------------------
2714 template < class T, class MFLOAT >
2718 {
2719  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2720  BareField<Vektor<MFLOAT,2U>,2U>& vertSpacings = *(x.get_mesh().VertSpacings);
2721  const NDIndex<2U>& domain = r.getDomain();
2722  Index I = domain[0];
2723  Index J = domain[1];
2724  r[I][J] = (x[I ][J ]*x.get_mesh().Dvc[0] +
2725  x[I+1][J ]*x.get_mesh().Dvc[1] +
2726  x[I ][J+1]*x.get_mesh().Dvc[2] +
2727  x[I+1][J+1]*x.get_mesh().Dvc[3])/vertSpacings[I][J];
2728  return r;
2729 }
2730 //----------------------------------------------------------------------
2731 template < class T, class MFLOAT >
2735 {
2736  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2737  BareField<Vektor<MFLOAT,3U>,3U>& vertSpacings = *(x.get_mesh().VertSpacings);
2738  const NDIndex<3U>& domain = r.getDomain();
2739  Index I = domain[0];
2740  Index J = domain[1];
2741  Index K = domain[2];
2742  r[I][J][K] = (x[I ][J ][K ]*x.get_mesh().Dvc[0] +
2743  x[I+1][J ][K ]*x.get_mesh().Dvc[1] +
2744  x[I ][J+1][K ]*x.get_mesh().Dvc[2] +
2745  x[I+1][J+1][K ]*x.get_mesh().Dvc[3] +
2746  x[I ][J ][K+1]*x.get_mesh().Dvc[4] +
2747  x[I+1][J ][K+1]*x.get_mesh().Dvc[5] +
2748  x[I ][J+1][K+1]*x.get_mesh().Dvc[6] +
2749  x[I+1][J+1][K+1]*x.get_mesh().Dvc[7])/vertSpacings[I][J][K];
2750  return r;
2751 }
2752 //----------------------------------------------------------------------
2753 // Grad Scalar/Cell -> Vektor/Vert
2754 // (cellSpacings[I,J,K]->[I-1,....] 1/20/1998 tjw)
2755 // (reverted to cellSpacings[I-1,J-1,K-1]->[I,....] 2/2/1998 tjw)
2756 //----------------------------------------------------------------------
2757 template < class T, class MFLOAT >
2761 {
2762  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2763  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings = *(x.get_mesh().CellSpacings);
2764  const NDIndex<1U>& domain = r.getDomain();
2765  Index I = domain[0];
2766  r[I] = (x[I-1]*x.get_mesh().Dvc[0] +
2767  x[I ]*x.get_mesh().Dvc[1])/cellSpacings[I];
2768  return r;
2769 }
2770 //----------------------------------------------------------------------
2771 template < class T, class MFLOAT >
2775 {
2776  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2777  BareField<Vektor<MFLOAT,2U>,2U>& cellSpacings = *(x.get_mesh().CellSpacings);
2778  const NDIndex<2U>& domain = r.getDomain();
2779  Index I = domain[0];
2780  Index J = domain[1];
2781  r[I][J] = (x[I-1][J-1]*x.get_mesh().Dvc[0] +
2782  x[I ][J-1]*x.get_mesh().Dvc[1] +
2783  x[I-1][J ]*x.get_mesh().Dvc[2] +
2784  x[I ][J ]*x.get_mesh().Dvc[3])/cellSpacings[I][J];
2785  return r;
2786 }
2787 //----------------------------------------------------------------------
2788 template < class T, class MFLOAT >
2792 {
2793  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2794  BareField<Vektor<MFLOAT,3U>,3U>& cellSpacings = *(x.get_mesh().CellSpacings);
2795  const NDIndex<3U>& domain = r.getDomain();
2796  Index I = domain[0];
2797  Index J = domain[1];
2798  Index K = domain[2];
2799  Vektor<MFLOAT,3U> dvc[1<<3U];
2800  for (unsigned int d=0; d < 1<<3U; d++) dvc[d] = x.get_mesh().Dvc[d];
2801  r[I][J][K] = (x[I-1][J-1][K-1]*dvc[0] +
2802  x[I ][J-1][K-1]*dvc[1] +
2803  x[I-1][J ][K-1]*dvc[2] +
2804  x[I ][J ][K-1]*dvc[3] +
2805  x[I-1][J-1][K ]*dvc[4] +
2806  x[I ][J-1][K ]*dvc[5] +
2807  x[I-1][J ][K ]*dvc[6] +
2808  x[I ][J ][K ]*dvc[7])/
2809  cellSpacings[I][J][K];
2810  return r;
2811 }
2812 
2813 // TJW: I've attempted to update these differential operators from uniform
2814 // cartesian implementations to workfor (nonuniform) Cartesian class, but they
2815 // may really need to get changed in other ways, such as something besides
2816 // simple centered differncing for cell-cell and vert-vert cases. Flag these
2817 // operator implementations since they may be a source of trouble until tested
2818 // and debugged further. The Grad() operators, especially, may be wrong. All
2819 // that being said, I have tested quite a few of these, including the following
2820 // two needed by Tecolote: 1) Div SymTenzor/Cell->Vektor/Vert 2) Grad
2821 // Vektor/Vert->Tenzor/Cell
2822 
2823 // BEGIN FLAGGED DIFFOPS REGION II
2824 
2825 //----------------------------------------------------------------------
2826 // Grad Scalar/Vert -> Vektor/Vert (???right? tjw 1/16/98)
2827 //----------------------------------------------------------------------
2828 template < class T, class MFLOAT >
2832 {
2833  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2834  BareField<Vektor<MFLOAT,1U>,1U>& vertSpacings =
2835  *(x.get_mesh().VertSpacings);
2836  const NDIndex<1U>& domain = r.getDomain();
2837  Index I = domain[0];
2838 
2839  Vektor<MFLOAT,1U> idx;
2840  idx[0] = 1.0;
2841 
2842  r[I] = idx*((x[I+1] - x[I-1])/(vertSpacings[I] + vertSpacings[I-1]));
2843  return r;
2844 }
2845 //----------------------------------------------------------------------
2846 template < class T, class MFLOAT >
2850 {
2851  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2852  BareField<Vektor<MFLOAT,2U>,2U>& vertSpacings =
2853  *(x.get_mesh().VertSpacings);
2854  const NDIndex<2U>& domain = r.getDomain();
2855  Index I = domain[0];
2856  Index J = domain[1];
2857 
2858  Vektor<MFLOAT,2U> idx,idy;
2859  idx[0] = 1.0;
2860  idx[1] = 0.0;
2861  idy[0] = 0.0;
2862  idy[1] = 1.0;
2863 
2864  r[I][J] =
2865  idx*((x[I+1][J ] - x[I-1][J ])/
2866  (vertSpacings[I][J] + vertSpacings[I-1][J])) +
2867  idy*((x[I ][J+1] - x[I ][J-1])/
2868  (vertSpacings[I][J] + vertSpacings[I][J-1]));
2869  return r;
2870 }
2871 //----------------------------------------------------------------------
2872 template < class T, class MFLOAT >
2876 {
2877  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2878  BareField<Vektor<MFLOAT,3U>,3U>& vertSpacings =
2879  *(x.get_mesh().VertSpacings);
2880  const NDIndex<3U>& domain = r.getDomain();
2881  Index I = domain[0];
2882  Index J = domain[1];
2883  Index K = domain[2];
2884 
2885  Vektor<MFLOAT,3U> idx,idy,idz;
2886  idx[0] = 1.0;
2887  idx[1] = 0.0;
2888  idx[2] = 0.0;
2889  idy[0] = 0.0;
2890  idy[1] = 1.0;
2891  idy[2] = 0.0;
2892  idz[0] = 0.0;
2893  idz[1] = 0.0;
2894  idz[2] = 1.0;
2895 
2896  r[I][J][K] =
2897  idx*((x[I+1][J ][K ] - x[I-1][J ][K ])/
2898  (vertSpacings[I][J][K] + vertSpacings[I-1][J][K])) +
2899  idy*((x[I ][J+1][K ] - x[I ][J-1][K ])/
2900  (vertSpacings[I][J][K] + vertSpacings[I][J-1][K])) +
2901  idz*((x[I ][J ][K+1] - x[I ][J ][K-1])/
2902  (vertSpacings[I][J][K] + vertSpacings[I][J][K-1]));
2903  return r;
2904 }
2905 //----------------------------------------------------------------------
2906 // Grad Scalar/Cell -> Vektor/Cell
2907 //----------------------------------------------------------------------
2908 template < class T, class MFLOAT >
2912 {
2913  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2914  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings =
2915  *(x.get_mesh().CellSpacings);
2916  const NDIndex<1U>& domain = r.getDomain();
2917  Index I = domain[0];
2918 
2919  Vektor<MFLOAT,1U> idx;
2920  idx[0] = 1.0;
2921 
2922  r[I] = idx*((x[I+1] - x[I-1])/(cellSpacings[I] + cellSpacings[I+1]));
2923  return r;
2924 }
2925 //----------------------------------------------------------------------
2926 template < class T, class MFLOAT >
2930 {
2931  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2932  BareField<Vektor<MFLOAT,2U>,2U>& cellSpacings =
2933  *(x.get_mesh().CellSpacings);
2934  const NDIndex<2U>& domain = r.getDomain();
2935  Index I = domain[0];
2936  Index J = domain[1];
2937 
2938  Vektor<MFLOAT,2U> idx,idy;
2939  idx[0] = 1.0;
2940  idx[1] = 0.0;
2941  idy[0] = 0.0;
2942  idy[1] = 1.0;
2943 
2944  r[I][J] =
2945  idx*((x[I+1][J ] - x[I-1][J ])/
2946  (cellSpacings[I][J] + cellSpacings[I+1][J])) +
2947  idy*((x[I ][J+1] - x[I ][J-1])/
2948  (cellSpacings[I][J] + cellSpacings[I][J+1]));
2949  return r;
2950 }
2951 //----------------------------------------------------------------------
2952 template < class T, class MFLOAT >
2956 {
2957  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2958  BareField<Vektor<MFLOAT,3U>,3U>& cellSpacings =
2959  *(x.get_mesh().CellSpacings);
2960  const NDIndex<3U>& domain = r.getDomain();
2961  Index I = domain[0];
2962  Index J = domain[1];
2963  Index K = domain[2];
2964 
2965  Vektor<MFLOAT,3U> idx,idy,idz;
2966  idx[0] = 1.0;
2967  idx[1] = 0.0;
2968  idx[2] = 0.0;
2969  idy[0] = 0.0;
2970  idy[1] = 1.0;
2971  idy[2] = 0.0;
2972  idz[0] = 0.0;
2973  idz[1] = 0.0;
2974  idz[2] = 1.0;
2975 
2976  r[I][J][K] =
2977  idx*((x[I+1][J ][K ] - x[I-1][J ][K ])/
2978  (cellSpacings[I][J][K] + cellSpacings[I+1][J][K])) +
2979  idy*((x[I ][J+1][K ] - x[I ][J-1][K ])/
2980  (cellSpacings[I][J][K] + cellSpacings[I][J+1][K])) +
2981  idz*((x[I ][J ][K+1] - x[I ][J ][K-1])/
2982  (cellSpacings[I][J][K] + cellSpacings[I][J][K+1]));
2983  return r;
2984 }
2985 //----------------------------------------------------------------------
2986 // Grad Vektor/Vert -> Tenzor/Cell (???o.p. right thing? tjw 1/20/1998)
2987 //----------------------------------------------------------------------
2988 template < class T, class MFLOAT >
2992 {
2993  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
2994  BareField<Vektor<MFLOAT,1U>,1U>& vS = *(x.get_mesh().VertSpacings);
2995  const NDIndex<1U>& domain = r.getDomain();
2996  Index I = domain[0];
2997  r[I] =
2998  outerProduct(x[I ], x.get_mesh().Dvc[0]/vS[I]) +
2999  outerProduct(x[I+1], x.get_mesh().Dvc[1]/vS[I]);
3000  return r;
3001 }
3002 //----------------------------------------------------------------------
3003 template < class T, class MFLOAT >
3007 {
3008  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
3009  BareField<Vektor<MFLOAT,2U>,2U>& vS = *(x.get_mesh().VertSpacings);
3010  const NDIndex<2U>& domain = r.getDomain();
3011  Index I = domain[0];
3012  Index J = domain[1];
3013  r[I][J] =
3014  outerProduct(x[I ][J ], x.get_mesh().Dvc[0]/vS[I][J]) +
3015  outerProduct(x[I+1][J ], x.get_mesh().Dvc[1]/vS[I][J]) +
3016  outerProduct(x[I ][J+1], x.get_mesh().Dvc[2]/vS[I][J]) +
3017  outerProduct(x[I+1][J+1], x.get_mesh().Dvc[3]/vS[I][J]);
3018  return r;
3019 }
3020 //----------------------------------------------------------------------
3021 template < class T, class MFLOAT >
3025 {
3026  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
3027  BareField<Vektor<MFLOAT,3U>,3U>& vS = *(x.get_mesh().VertSpacings);
3028  const NDIndex<3U>& domain = r.getDomain();
3029  Index I = domain[0];
3030  Index J = domain[1];
3031  Index K = domain[2];
3032  r[I][J][K] =
3033  outerProduct(x[I ][J ][K ], x.get_mesh().Dvc[0]/vS[I][J][K]) +
3034  outerProduct(x[I+1][J ][K ], x.get_mesh().Dvc[1]/vS[I][J][K]) +
3035  outerProduct(x[I ][J+1][K ], x.get_mesh().Dvc[2]/vS[I][J][K]) +
3036  outerProduct(x[I+1][J+1][K ], x.get_mesh().Dvc[3]/vS[I][J][K]) +
3037  outerProduct(x[I ][J ][K+1], x.get_mesh().Dvc[4]/vS[I][J][K]) +
3038  outerProduct(x[I+1][J ][K+1], x.get_mesh().Dvc[5]/vS[I][J][K]) +
3039  outerProduct(x[I ][J+1][K+1], x.get_mesh().Dvc[6]/vS[I][J][K]) +
3040  outerProduct(x[I+1][J+1][K+1], x.get_mesh().Dvc[7]/vS[I][J][K]);
3041 
3042  return r;
3043 }
3044 //----------------------------------------------------------------------
3045 // Grad Vektor/Cell -> Tenzor/Vert (???o.p. right thing? tjw 1/20/1998)
3046 // (cellSpacings[I,J,K]->[I-1,....] 1/20/1998 tjw)
3047 //----------------------------------------------------------------------
3048 template < class T, class MFLOAT >
3052 {
3053  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
3054  BareField<Vektor<MFLOAT,1U>,1U>& cellSpacings = *(x.get_mesh().CellSpacings);
3055  const NDIndex<1U>& domain = r.getDomain();
3056  Index I = domain[0];
3057  r[I] =
3058  outerProduct(x[I-1], x.get_mesh().Dvc[0]/cellSpacings[I-1]) +
3059  outerProduct(x[I ], x.get_mesh().Dvc[1]/cellSpacings[I-1]);
3060  return r;
3061 }
3062 //----------------------------------------------------------------------
3063 template < class T, class MFLOAT >
3067 {
3068  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
3069  BareField<Vektor<MFLOAT,2U>,2U>& cS = *(x.get_mesh().CellSpacings);
3070  const NDIndex<2U>& domain = r.getDomain();
3071  Index I = domain[0];
3072  Index J = domain[1];
3073  r[I][J] =
3074  outerProduct(x[I-1][J-1], x.get_mesh().Dvc[0]/cS[I-1][J-1]) +
3075  outerProduct(x[I ][J-1], x.get_mesh().Dvc[1]/cS[I-1][J-1]) +
3076  outerProduct(x[I-1][J ], x.get_mesh().Dvc[2]/cS[I-1][J-1]) +
3077  outerProduct(x[I ][J ], x.get_mesh().Dvc[3]/cS[I-1][J-1]);
3078  return r;
3079 }
3080 //----------------------------------------------------------------------
3081 template < class T, class MFLOAT >
3085 {
3086  PAssert_EQ(x.get_mesh().hasSpacingFields, true);
3087  BareField<Vektor<MFLOAT,3U>,3U>& cS = *(x.get_mesh().CellSpacings);
3088  const NDIndex<3U>& domain = r.getDomain();
3089  Index I = domain[0];
3090  Index J = domain[1];
3091  Index K = domain[2];
3092  r[I][J][K] =
3093  outerProduct(x[I-1][J-1][K-1], x.get_mesh().Dvc[0]/cS[I-1][J-1][K-1]) +
3094  outerProduct(x[I ][J-1][K-1], x.get_mesh().Dvc[1]/cS[I-1][J-1][K-1]) +
3095  outerProduct(x[I-1][J ][K-1], x.get_mesh().Dvc[2]/cS[I-1][J-1][K-1]) +
3096  outerProduct(x[I ][J ][K-1], x.get_mesh().Dvc[3]/cS[I-1][J-1][K-1]) +
3097  outerProduct(x[I-1][J-1][K ], x.get_mesh().Dvc[4]/cS[I-1][J-1][K-1]) +
3098  outerProduct(x[I ][J-1][K ], x.get_mesh().Dvc[5]/cS[I-1][J-1][K-1]) +
3099  outerProduct(x[I-1][J ][K ], x.get_mesh().Dvc[6]/cS[I-1][J-1][K-1]) +
3100  outerProduct(x[I ][J ][K ], x.get_mesh().Dvc[7]/cS[I-1][J-1][K-1]);
3101  return r;
3102 }
3103 
3104 // END FLAGGED DIFFOPS REGION II
3105 
3106 namespace IPPL {
3107 
3108 //----------------------------------------------------------------------
3109 // Weighted average Cell to Vert
3110 //----------------------------------------------------------------------
3111 template < class T1, class T2, class MFLOAT >
3114  Field<T2,1U,Cartesian<1U,MFLOAT>,Cell>& w,
3115  Field<T1,1U,Cartesian<1U,MFLOAT>,Vert>& r)
3116 {
3117  const NDIndex<1U>& domain = r.getDomain();
3118  Index I = domain[0];
3119  r[I] = (x[I-1]*w[I-1] + x[I ]*w[I ])/(w[I-1] + w[I ]);
3120  return r;
3121 }
3122 //----------------------------------------------------------------------
3123 template < class T1, class T2, class MFLOAT >
3126  Field<T2,2U,Cartesian<2U,MFLOAT>,Cell>& w,
3127  Field<T1,2U,Cartesian<2U,MFLOAT>,Vert>& r)
3128 {
3129  const NDIndex<2U>& domain = r.getDomain();
3130  Index I = domain[0];
3131  Index J = domain[1];
3132 
3133  r[I][J] = (x[I-1][J-1] * w[I-1][J-1] +
3134  x[I ][J-1] * w[I ][J-1] +
3135  x[I-1][J ] * w[I-1][J ] +
3136  x[I ][J ] * w[I ][J ])/
3137  (w[I-1][J-1] +
3138  w[I ][J-1] +
3139  w[I-1][J ] +
3140  w[I ][J ]);
3141  return r;
3142 }
3143 //----------------------------------------------------------------------
3144 template < class T1, class T2, class MFLOAT >
3147  Field<T2,3U,Cartesian<3U,MFLOAT>,Cell>& w,
3148  Field<T1,3U,Cartesian<3U,MFLOAT>,Vert>& r)
3149 {
3150  const NDIndex<3U>& domain = r.getDomain();
3151  Index I = domain[0];
3152  Index J = domain[1];
3153  Index K = domain[2];
3154 
3155  r[I][J][K] = (x[I-1][J-1][K-1] * w[I-1][J-1][K-1] +
3156  x[I ][J-1][K-1] * w[I ][J-1][K-1] +
3157  x[I-1][J ][K-1] * w[I-1][J ][K-1] +
3158  x[I ][J ][K-1] * w[I ][J ][K-1] +
3159  x[I-1][J-1][K ] * w[I-1][J-1][K ] +
3160  x[I ][J-1][K ] * w[I ][J-1][K ] +
3161  x[I-1][J ][K ] * w[I-1][J ][K ] +
3162  x[I ][J ][K ] * w[I ][J ][K ] )/
3163  (w[I-1][J-1][K-1] +
3164  w[I ][J-1][K-1] +
3165  w[I-1][J ][K-1] +
3166  w[I ][J ][K-1] +
3167  w[I-1][J-1][K ] +
3168  w[I ][J-1][K ] +
3169  w[I-1][J ][K ] +
3170  w[I ][J ][K ]);
3171  return r;
3172 }
3173 //----------------------------------------------------------------------
3174 // Weighted average Vert to Cell
3175 // N.B.: won't work except for unit-stride (& zero-base?) Field's.
3176 //----------------------------------------------------------------------
3177 template < class T1, class T2, class MFLOAT >
3180  Field<T2,1U,Cartesian<1U,MFLOAT>,Vert>& w,
3181  Field<T1,1U,Cartesian<1U,MFLOAT>,Cell>& r)
3182 {
3183  const NDIndex<1U>& domain = r.getDomain();
3184  Index I = domain[0];
3185  r[I] = (x[I+1]*w[I+1] + x[I ]*w[I ])/(w[I+1] + w[I ]);
3186  return r;
3187 }
3188 //----------------------------------------------------------------------
3189 template < class T1, class T2, class MFLOAT >
3192  Field<T2,2U,Cartesian<2U,MFLOAT>,Vert>& w,
3193  Field<T1,2U,Cartesian<2U,MFLOAT>,Cell>& r)
3194 {
3195  const NDIndex<2U>& domain = r.getDomain();
3196  Index I = domain[0];
3197  Index J = domain[1];
3198 
3199  r[I][J] = (x[I+1][J+1] * w[I+1][J+1] +
3200  x[I ][J+1] * w[I ][J+1] +
3201  x[I+1][J ] * w[I+1][J ] +
3202  x[I ][J ] * w[I ][J ])/
3203  (w[I+1][J+1] +
3204  w[I ][J+1] +
3205  w[I+1][J ] +
3206  w[I ][J ]);
3207  return r;
3208 }
3209 //----------------------------------------------------------------------
3210 template < class T1, class T2, class MFLOAT >
3213  Field<T2,3U,Cartesian<3U,MFLOAT>,Vert>& w,
3214  Field<T1,3U,Cartesian<3U,MFLOAT>,Cell>& r)
3215 {
3216  const NDIndex<3U>& domain = r.getDomain();
3217  Index I = domain[0];
3218  Index J = domain[1];
3219  Index K = domain[2];
3220 
3221  r[I][J][K] = (x[I+1][J+1][K+1] * w[I+1][J+1][K+1] +
3222  x[I ][J+1][K+1] * w[I ][J+1][K+1] +
3223  x[I+1][J ][K+1] * w[I+1][J ][K+1] +
3224  x[I ][J ][K+1] * w[I ][J ][K+1] +
3225  x[I+1][J+1][K ] * w[I+1][J+1][K ] +
3226  x[I ][J+1][K ] * w[I ][J+1][K ] +
3227  x[I+1][J ][K ] * w[I+1][J ][K ] +
3228  x[I ][J ][K ] * w[I ][J ][K ])/
3229  (w[I+1][J+1][K+1] +
3230  w[I ][J+1][K+1] +
3231  w[I+1][J ][K+1] +
3232  w[I ][J ][K+1] +
3233  w[I+1][J+1][K ] +
3234  w[I ][J+1][K ] +
3235  w[I+1][J ][K ] +
3236  w[I ][J ][K ]);
3237  return r;
3238 }
3239 
3240 //----------------------------------------------------------------------
3241 // Unweighted average Cell to Vert
3242 //----------------------------------------------------------------------
3243 template < class T1, class MFLOAT >
3246  Field<T1,1U,Cartesian<1U,MFLOAT>,Vert>& r)
3247 {
3248  const NDIndex<1U>& domain = r.getDomain();
3249  Index I = domain[0];
3250  r[I] = 0.5*(x[I-1] + x[I ]);
3251  return r;
3252 }
3253 //----------------------------------------------------------------------
3254 template < class T1, class MFLOAT >
3257  Field<T1,2U,Cartesian<2U,MFLOAT>,Vert>& r)
3258 {
3259  const NDIndex<2U>& domain = r.getDomain();
3260  Index I = domain[0];
3261  Index J = domain[1];
3262  r[I][J] = 0.25*(x[I-1][J-1] + x[I ][J-1] + x[I-1][J ] + x[I ][J ]);
3263  return r;
3264 }
3265 //----------------------------------------------------------------------
3266 template < class T1, class MFLOAT >
3269  Field<T1,3U,Cartesian<3U,MFLOAT>,Vert>& r)
3270 {
3271  const NDIndex<3U>& domain = r.getDomain();
3272  Index I = domain[0];
3273  Index J = domain[1];
3274  Index K = domain[2];
3275  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] +
3276  x[I ][J ][K-1] + x[I-1][J-1][K ] + x[I ][J-1][K ] +
3277  x[I-1][J ][K ] + x[I ][J ][K ]);
3278  return r;
3279 }
3280 //----------------------------------------------------------------------
3281 // Unweighted average Vert to Cell
3282 // N.B.: won't work except for unit-stride (& zero-base?) Field's.
3283 //----------------------------------------------------------------------
3284 template < class T1, class MFLOAT >
3287  Field<T1,1U,Cartesian<1U,MFLOAT>,Cell>& r)
3288 {
3289  const NDIndex<1U>& domain = r.getDomain();
3290  Index I = domain[0];
3291  r[I] = 0.5*(x[I+1] + x[I ]);
3292  return r;
3293 }
3294 //----------------------------------------------------------------------
3295 template < class T1, class MFLOAT >
3298  Field<T1,2U,Cartesian<2U,MFLOAT>,Cell>& r)
3299 {
3300  const NDIndex<2U>& domain = r.getDomain();
3301  Index I = domain[0];
3302  Index J = domain[1];
3303  r[I][J] = 0.25*(x[I+1][J+1] + x[I ][J+1] + x[I+1][J ] + x[I ][J ]);
3304  return r;
3305 }
3306 //----------------------------------------------------------------------
3307 template < class T1, class MFLOAT >
3310  Field<T1,3U,Cartesian<3U,MFLOAT>,Cell>& r)
3311 {
3312  const NDIndex<3U>& domain = r.getDomain();
3313  Index I = domain[0];
3314  Index J = domain[1];
3315  Index K = domain[2];
3316  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] +
3317  x[I ][J ][K+1] + x[I+1][J+1][K ] + x[I ][J+1][K ] +
3318  x[I+1][J ][K ] + x[I ][J ][K ]);
3319  return r;
3320 }
3321 
3322 }
3323 
3324 /***************************************************************************
3325  * $RCSfile: Cartesian.cpp,v $ $Author: adelmann $
3326  * $Revision: 1.1.1.1 $ $Date: 2003/01/23 07:40:27 $
3327  * IPPL_VERSION_ID: $Id: Cartesian.cpp,v 1.1.1.1 2003/01/23 07:40:27 adelmann Exp $
3328  ***************************************************************************/
PartBunchBase< T, Dim >::ConstIterator begin(PartBunchBase< T, Dim > const &bunch)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
const unsigned Dim
Tenzor< typename PETEBinaryReturn< T1, T2, OpMultipply >::type, D > outerProduct(const Vektor< T1, D > &v1, const Vektor< T2, D > &v2)
Definition: Tenzor.h:443
void assign(const BareField< T, Dim > &a, RHS b, OP op, ExprTag< true >)
NDIndex< Dim > AddGuardCells(const NDIndex< Dim > &idx, const GuardCellSizes< Dim > &g)
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:84
T::PETE_Expr_t::PETE_Return_t min(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:76
e_dim_tag
Definition: FieldLayout.h:55
@ PARALLEL
Definition: FieldLayout.h:55
Field< T, 1U, Cartesian< 1U, MFLOAT >, Cell > & Div(Field< Vektor< T, 1U >, 1U, Cartesian< 1U, MFLOAT >, Vert > &x, Field< T, 1U, Cartesian< 1U, MFLOAT >, Cell > &r)
Definition: Cartesian.hpp:2192
void PETE_apply(OpMeshPeriodic< T >, T &a, T b)
Definition: Cartesian.hpp:816
Field< Vektor< T, 1U >, 1U, Cartesian< 1U, MFLOAT >, Cell > & Grad(Field< T, 1U, Cartesian< 1U, MFLOAT >, Vert > &x, Field< Vektor< T, 1U >, 1U, Cartesian< 1U, MFLOAT >, Cell > &r)
Definition: Cartesian.hpp:2702
std::complex< double > a
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Inform & endl(Inform &inf)
Definition: Inform.cpp:42
#define ERRORMSG(msg)
Definition: IpplInfo.h:350
#define PAssert_LT(a, b)
Definition: PAssert.h:106
#define PInsist(c, m)
Definition: PAssert.h:120
#define PAssert_EQ(a, b)
Definition: PAssert.h:104
const T * find(const T table[], const std::string &name)
Look up name.
Definition: TFind.h:34
constexpr double e
The value of.
Definition: Physics.h:39
std::string::iterator iterator
Definition: MSLang.h:16
Field< T1, 1U, Cartesian< 1U, MFLOAT >, Vert > & Average(Field< T1, 1U, Cartesian< 1U, MFLOAT >, Cell > &x, Field< T2, 1U, Cartesian< 1U, MFLOAT >, Cell > &w, Field< T1, 1U, Cartesian< 1U, MFLOAT >, Vert > &r)
Definition: Cartesian.hpp:3113
Definition: Offset.h:66
Definition: Tenzor.h:35
Definition: Vektor.h:32
Definition: Field.h:33
NDIndex< Dim > plugBase(const NDIndex< D > &i) const
Definition: NDIndex.h:114
bool touches(const NDIndex< Dim > &) const
NDIndex< Dim > intersect(const NDIndex< Dim > &) const
unsigned rightGuard(unsigned d) const
Definition: BareField.h:149
iterator end() const
Definition: BareField.h:241
iterator_if begin_if()
Definition: BareField.h:100
ac_id_larray::iterator iterator_if
Definition: BareField.h:92
void Uncompress() const
Definition: BareField.hpp:1005
iterator_if end_if()
Definition: BareField.h:101
const GuardCellSizes< Dim > & getGuardCellSizes() const
Definition: BareField.h:147
virtual void fillGuardCells(bool reallyFill=true) const
Definition: BareField.hpp:297
iterator begin() const
Definition: BareField.h:234
unsigned leftGuard(unsigned d) const
Definition: BareField.h:148
Definition: LField.h:58
const NDIndex< Dim > & getOwned() const
Definition: LField.h:99
const NDIndex< Dim > & getAllocated() const
Definition: LField.h:98
const iterator & begin() const
Definition: LField.h:110
Definition: Index.h:237
int stride() const
Definition: IndexInlines.h:121
unsigned int length() const
Definition: IndexInlines.h:131
int first() const
Definition: IndexInlines.h:116
Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > & getDeltaVertexField(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > &) const
Definition: Cartesian.hpp:1861
void get_meshSpacing(unsigned d, MFLOAT *spacings) const
Definition: Cartesian.hpp:787
MFLOAT getCellRangeVolume(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1573
Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Vert > & getVertexPositionField(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Vert > &) const
Definition: Cartesian.hpp:1755
NDIndex< Dim > getVertexBelow(const Vektor< MFLOAT, Dim > &) const
Definition: Cartesian.hpp:1671
Vektor< MFLOAT, Dim > getSurfaceNormal(const NDIndex< Dim > &, unsigned) const
Definition: Cartesian.hpp:1982
void set_meshSpacing(MFLOAT **const del)
Definition: Cartesian.hpp:748
void getSurfaceNormalFields(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > **) const
Definition: Cartesian.hpp:1956
Field< MFLOAT, Dim, Cartesian< Dim, MFLOAT >, Cell > & getCellVolumeField(Field< MFLOAT, Dim, Cartesian< Dim, MFLOAT >, Cell > &) const
Definition: Cartesian.hpp:1520
Vektor< MFLOAT, Dim > getDeltaCell(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1882
Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > & getCellPositionField(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > &) const
Definition: Cartesian.hpp:1802
MFLOAT getCellVolume(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1503
Vektor< MFLOAT, Dim > getVertexPosition(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1732
void set_Dvc()
Definition: Cartesian.hpp:769
Vektor< MFLOAT, Dim > getCellPosition(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1778
void storeSpacingFields()
Definition: Cartesian.hpp:840
void set_MeshBC(unsigned face, MeshBC_E meshBCType)
Definition: Cartesian.hpp:2051
void set_origin(const Vektor< MFLOAT, Dim > &o)
Definition: Cartesian.hpp:723
MeshBC_E * get_MeshBC() const
Definition: Cartesian.hpp:2169
Cartesian()
Definition: Cartesian.h:42
void setup()
Definition: Cartesian.hpp:46
NDIndex< Dim > getNearestVertex(const Vektor< MFLOAT, Dim > &) const
Definition: Cartesian.hpp:1604
Vektor< MFLOAT, Dim > * getSurfaceNormals(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1938
Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Vert > & getDeltaCellField(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Vert > &) const
Definition: Cartesian.hpp:1917
Vektor< MFLOAT, Dim > getDeltaVertex(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1827
Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > & getSurfaceNormalField(Field< Vektor< MFLOAT, Dim >, Dim, Cartesian< Dim, MFLOAT >, Cell > &, unsigned) const
Definition: Cartesian.hpp:2013
void updateMeshSpacingGuards(int face)
Definition: Cartesian.hpp:2075
void print(std::ostream &)
Definition: Cartesian.hpp:1471
Vektor< MFLOAT, Dim > get_origin() const
Definition: Cartesian.hpp:740
void initialize(const NDIndex< Dim > &ndi)
Definition: Cartesian.hpp:382
MFLOAT getVertRangeVolume(const NDIndex< Dim > &) const
Definition: Cartesian.hpp:1542
OpMeshExtrapolate(T &o, T &s)
Definition: Cartesian.hpp:822
Definition: Centering.h:32
Definition: Centering.h:43
Definition: Mesh.h:35
MeshBC_E
Definition: Mesh.h:32
@ Periodic
Definition: Mesh.h:32
@ NoBC
Definition: Mesh.h:32
@ Reflective
Definition: Mesh.h:32