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