OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
ArbitraryDomain.cpp
Go to the documentation of this file.
1 // ------------------------------------------------------------------------
2 // $Version: 1.2.1 $
3 // ------------------------------------------------------------------------
4 // Copyright & License: See Copyright.readme in src directory
5 // ------------------------------------------------------------------------
6 // Class ArbitraryDomain
7 // Interface to iterative solver and boundary geometry
8 // for space charge calculation
9 //
10 // ------------------------------------------------------------------------
11 // $Author: kaman $
12 // $Date: 2014 $
13 // ------------------------------------------------------------------------
14 //#define DEBUG_INTERSECT_RAY_BOUNDARY
15 
16 #ifdef HAVE_SAAMG_SOLVER
19 
20 #include <cmath>
21 #include <iostream>
22 #include <tuple>
23 #include <assert.h>
24 
25 #include <math.h>
26 
27 ArbitraryDomain::ArbitraryDomain( BoundaryGeometry * bgeom,
28  Vector_t nr,
29  Vector_t hr,
30  std::string interpl){
31  bgeom_m = bgeom;
32  minCoords_m = bgeom->getmincoords();
33  maxCoords_m = bgeom->getmaxcoords();
34  geomCentroid_m = (minCoords_m + maxCoords_m)/2.0;
35 
36  // TODO: THis needs to be made into OPTION of the geometry.
37  // A user defined point that is INSIDE with 100% certainty. -DW
38  globalInsideP0_m = Vector_t(0.0, 0.0, -0.13);
39 
40  setNr(nr);
41  for(int i=0; i<3; i++)
42  Geo_hr_m[i] = (maxCoords_m[i] - minCoords_m[i])/nr[i];
43  setHr(Geo_hr_m);
44 
45  startId = 0;
46 
47  if (interpl == "CONSTANT")
48  interpolationMethod = CONSTANT;
49  else if(interpl == "LINEAR")
50  interpolationMethod = LINEAR;
51  else if(interpl == "QUADRATIC")
52  interpolationMethod = QUADRATIC;
53 }
54 
55 ArbitraryDomain::~ArbitraryDomain() {
56  //nothing so far
57 }
58 
59 void ArbitraryDomain::compute(Vector_t hr){
60 
61  setHr(hr);
62 
63  globalMeanR_m = getGlobalMeanR();
64 
65  globalToLocalQuaternion_m = getGlobalToLocalQuaternion();
66  localToGlobalQuaternion_m[0] = globalToLocalQuaternion_m[0];
67  for (int i=1; i<4; i++)
68  localToGlobalQuaternion_m[i] = -globalToLocalQuaternion_m[i];
69 
70  hasGeometryChanged_m = true;
71 
72  IntersectLoX.clear();
73  IntersectHiX.clear();
74  IntersectLoY.clear();
75  IntersectHiY.clear();
76  IntersectLoZ.clear();
77  IntersectHiZ.clear();
78 
79  //calculate intersection
80  Vector_t P, saveP, dir, I;
81  //Reference Point
82  Vector_t P0 = geomCentroid_m;
83 
84  for (int idz = 0; idz < nr[2] ; idz++) {
85  saveP[2] = (idz - (nr[2]-1)/2.0)*hr[2];
86  for (int idy = 0; idy < nr[1] ; idy++) {
87  saveP[1] = (idy - (nr[1]-1)/2.0)*hr[1];
88  for (int idx = 0; idx <nr[0]; idx++) {
89  saveP[0] = (idx - (nr[0]-1)/2.0)*hr[0];
90  P = saveP;
91 
92  rotateWithQuaternion(P, localToGlobalQuaternion_m);
93  P += geomCentroid_m;
94 
95  if (bgeom_m->fastIsInside(P0, P) % 2 == 0) {
96  P0 = P;
97 
98  std::tuple<int, int, int> pos(idx, idy, idz);
99 
100  rotateZAxisWithQuaternion(dir, localToGlobalQuaternion_m);
101  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
102  I -= geomCentroid_m;
103  rotateWithQuaternion(I, globalToLocalQuaternion_m);
104  IntersectHiZ.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[2]));
105  } else {
106 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
107  *gmsg << "zdir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
108 #endif
109  }
110 
111  if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
112  I -= geomCentroid_m;
113  rotateWithQuaternion(I, globalToLocalQuaternion_m);
114  IntersectLoZ.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[2]));
115  } else {
116 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
117  *gmsg << "zdir=-1 " << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
118 #endif
119  }
120 
121  rotateYAxisWithQuaternion(dir, localToGlobalQuaternion_m);
122  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
123  I -= geomCentroid_m;
124  rotateWithQuaternion(I, globalToLocalQuaternion_m);
125  IntersectHiY.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[1]));
126  } else {
127 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
128  *gmsg << "ydir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
129 #endif
130  }
131 
132  if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
133  I -= geomCentroid_m;
134  rotateWithQuaternion(I, globalToLocalQuaternion_m);
135  IntersectLoY.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[1]));
136  } else {
137 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
138  *gmsg << "ydir=-1" << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
139 #endif
140  }
141 
142  rotateXAxisWithQuaternion(dir, localToGlobalQuaternion_m);
143  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
144  I -= geomCentroid_m;
145  rotateWithQuaternion(I, globalToLocalQuaternion_m);
146  IntersectHiX.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[0]));
147  } else {
148 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
149  *gmsg << "xdir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
150 #endif
151  }
152 
153  if (bgeom_m->intersectRayBoundary(P, -dir, I)){
154  I -= geomCentroid_m;
155  rotateWithQuaternion(I, globalToLocalQuaternion_m);
156  IntersectLoX.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[0]));
157  } else {
158 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
159  *gmsg << "xdir=-1 " << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
160 #endif
161  }
162  } else {
163 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
164  *gmsg << "OUTSIDE" << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
165 #endif
166  }
167  }
168  }
169  }
170  IdxMap.clear();
171  CoordMap.clear();
172 
173  int id=0;
174  int idx, idy, idz;
175  for (idz = 0; idz < nr[2]; idz++) {
176  for (idy = 0; idy < nr[1]; idy++) {
177  for (idx = 0; idx < nr[0]; idx++) {
178  if (isInside(idx, idy, idz)) {
179  IdxMap[toCoordIdx(idx, idy, idz)] = id;
180  CoordMap[id] = toCoordIdx(idx, idy, idz);
181  id++;
182  }
183  }
184  }
185  }
186 }
187 
188 void ArbitraryDomain::compute(Vector_t hr, NDIndex<3> localId){
189 
190  INFOMSG(level2 << "* Starting the Boundary Intersection Tests..." << endl);
191 
192  setHr(hr);
193 
194  globalMeanR_m = getGlobalMeanR();
195 
196  globalToLocalQuaternion_m = getGlobalToLocalQuaternion();
197  localToGlobalQuaternion_m[0] = globalToLocalQuaternion_m[0];
198  for (int i=1; i<4; i++)
199  localToGlobalQuaternion_m[i] = -globalToLocalQuaternion_m[i];
200 
201  int zGhostOffsetLeft = (localId[2].first()== 0) ? 0 : 1;
202  int zGhostOffsetRight = (localId[2].last() == nr[2] - 1) ? 0 : 1;
203  int yGhostOffsetLeft = (localId[1].first()== 0) ? 0 : 1;
204  int yGhostOffsetRight = (localId[1].last() == nr[1] - 1) ? 0 : 1;
205  int xGhostOffsetLeft = (localId[0].first()== 0) ? 0 : 1;
206  int xGhostOffsetRight = (localId[0].last() == nr[0] - 1) ? 0 : 1;
207 
208  hasGeometryChanged_m = true;
209 
210  IntersectLoX.clear();
211  IntersectHiX.clear();
212  IntersectLoY.clear();
213  IntersectHiY.clear();
214  IntersectLoZ.clear();
215  IntersectHiZ.clear();
216 
217  // Calculate intersection
218  Vector_t P, dir, I;
219  // Vector_t saveP, saveP_old;
220  Vector_t P0 = globalInsideP0_m;
221 
222  // We cannot assume that the geometry is symmetric about the xy, xz, and yz planes!
223  // In my spiral inflector simulation, this is not the case for z direction for
224  // example (-0.13 to +0.025). -DW
225  for (int idz = localId[2].first()-zGhostOffsetLeft; idz <= localId[2].last()+zGhostOffsetRight; idz++) {
226 
227  //saveP_old[2] = (idz - (nr[2]-1)/2.0)*hr[2];
228  P[2] = minCoords_m[2] + (idz + 0.5) * hr[2];
229 
230  for (int idy = localId[1].first()-yGhostOffsetLeft; idy <= localId[1].last()+yGhostOffsetRight; idy++) {
231 
232  //saveP_old[1] = (idy - (nr[1]-1)/2.0)*hr[1];
233  P[1] = minCoords_m[1] + (idy + 0.5) * hr[1];
234 
235  for (int idx = localId[0].first()-xGhostOffsetLeft; idx <= localId[0].last()+xGhostOffsetRight; idx++) {
236 
237  //saveP_old[0] = (idx - (nr[0]-1)/2.0)*hr[0];
238  P[0] = minCoords_m[0] + (idx + 0.5) * hr[0];
239 
240  // *gmsg << "Now working on point " << saveP << " (original was " << saveP_old << ")" << endl;
241 
242  //P = saveP;
243 
244  //rotateWithQuaternion(P, localToGlobalQuaternion_m);
245  //P += geomCentroid_m; //sorry, this doesn't make sense. -DW
246  //P += globalMeanR_m;
247 
248  if (bgeom_m->fastIsInside(P0, P) % 2 == 0) {
249 
250  // Fill the map with true or false values for very fast isInside tests
251  // during the rest of the fieldsolve.
252  IsInsideMap[toCoordIdx(idx, idy, idz)] = true;
253 
254  // Replace the old reference point with the new point (which we know is
255  // inside because we just tested for it. This makes the algorithm faster
256  // because fastIsInside() creates a number of segments that depends on the
257  // distance between P and P0. Using the previous P as the new P0
258  // assures the smallest possible distance in most cases. -DW
259  P0 = P;
260 
261  std::tuple<int, int, int> pos(idx, idy, idz);
262 
263  //rotateZAxisWithQuaternion(dir, localToGlobalQuaternion_m);
264  dir = Vector_t(0, 0, 1);
265 
266  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
267  //I -= geomCentroid_m;
268  //I -= globalMeanR_m;
269  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
270  IntersectHiZ.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[2]));
271  } else {
272 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
273  *gmsg << "zdir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
274 #endif
275  }
276 
277  if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
278  //I -= geomCentroid_m;
279  //I -= globalMeanR_m;
280  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
281  IntersectLoZ.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[2]));
282  } else {
283 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
284  *gmsg << "zdir=-1 " << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
285 #endif
286  }
287 
288  //rotateYAxisWithQuaternion(dir, localToGlobalQuaternion_m);
289  dir = Vector_t(0, 1, 0);
290 
291  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
292  //I -= geomCentroid_m;
293  //I -= globalMeanR_m;
294  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
295  IntersectHiY.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[1]));
296  } else {
297 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
298  *gmsg << "ydir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
299 #endif
300  }
301 
302  if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
303  //I -= geomCentroid_m;
304  //I -= globalMeanR_m;
305  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
306  IntersectLoY.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[1]));
307  } else {
308 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
309  *gmsg << "ydir=-1" << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
310 #endif
311  }
312 
313  //rotateXAxisWithQuaternion(dir, localToGlobalQuaternion_m);
314  dir = Vector_t(1, 0, 0);
315 
316  if (bgeom_m->intersectRayBoundary(P, dir, I)) {
317  //I -= geomCentroid_m;
318  //I -= globalMeanR_m;
319  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
320  IntersectHiX.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[0]));
321  } else {
322 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
323  *gmsg << "xdir=+1 " << dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
324 #endif
325  }
326 
327  if (bgeom_m->intersectRayBoundary(P, -dir, I)){
328  //I -= geomCentroid_m;
329  //I -= globalMeanR_m;
330  //rotateWithQuaternion(I, globalToLocalQuaternion_m);
331  IntersectLoX.insert(std::pair< std::tuple<int, int, int>, double >(pos, I[0]));
332  } else {
333 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
334  *gmsg << "xdir=-1 " << -dir << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
335 #endif
336  }
337  } else {
338  IsInsideMap[toCoordIdx(idx, idy, idz)] = false;
339 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
340  *gmsg << "OUTSIDE" << " x,y,z= " << idx << "," << idy << "," << idz << " P=" << P <<" I=" << I << endl;
341 #endif
342  }
343  }
344  }
345  }
346 
347  INFOMSG(level2 << "* Finding number of ghost nodes to the left..." << endl);
348 
349  //number of ghost nodes to the left
350  int numGhostNodesLeft = 0;
351  if(localId[2].first() != 0) {
352  for(int idx = 0; idx < nr[0]; idx++) {
353  for(int idy = 0; idy < nr[1]; idy++) {
354  if(isInside(idx, idy, localId[2].first() - zGhostOffsetLeft))
355  numGhostNodesLeft++;
356  }
357  }
358  }
359 
360  INFOMSG(level2 << "* Finding number of xy points in each plane along z..." << endl);
361 
362  //xy points in z plane
363  int numtotal = 0;
364  numXY.clear();
365  for(int idz = localId[2].first(); idz <= localId[2].last(); idz++) {
366  int numxy = 0;
367  for(int idx = 0; idx < nr[0]; idx++) {
368  for(int idy = 0; idy < nr[1]; idy++) {
369  if(isInside(idx, idy, idz))
370  numxy++;
371  }
372  }
373  numXY[idz-localId[2].first()] = numxy;
374  numtotal += numxy;
375  }
376 
377  int startIdx = 0;
378  MPI_Scan(&numtotal, &startIdx, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD);
379  startIdx -= numtotal;
380 
381  // Build up index and coord map
382  IdxMap.clear();
383  CoordMap.clear();
384  int index = startIdx - numGhostNodesLeft;
385 
386  INFOMSG(level2 << "* Building up index and coordinate map..." << endl);
387 
388  for(int idz = localId[2].first() - zGhostOffsetLeft; idz <= localId[2].last() + zGhostOffsetRight; idz++) {
389  for(int idy = 0; idy < nr[1]; idy++) {
390  for(int idx = 0; idx < nr[0]; idx++) {
391  if(isInside(idx, idy, idz)) {
392  IdxMap[toCoordIdx(idx, idy, idz)] = index;
393  CoordMap[index] = toCoordIdx(idx, idy, idz);
394  index++;
395  }
396  }
397  }
398  }
399 
400  INFOMSG(level2 << "* Done." << endl);
401 }
402 
403 // Conversion from (x,y,z) to index in xyz plane
404 inline int ArbitraryDomain::toCoordIdx(int idx, int idy, int idz) {
405  return (idz * nr[1] + idy) * nr[0] + idx;
406 }
407 
408 // Conversion from (x,y,z) to index on the 3D grid
409 int ArbitraryDomain::getIdx(int idx, int idy, int idz) {
410 
411  if(isInside(idx, idy, idz) && idx >= 0 && idy >= 0 && idz >= 0)
412  return IdxMap[toCoordIdx(idx, idy, idz)];
413  else
414  return -1;
415 }
416 
417 // Conversion from a 3D index to (x,y,z)
418 inline void ArbitraryDomain::getCoord(int idxyz, int &idx, int &idy, int &idz) {
419  int id = CoordMap[idxyz];
420  idx = id % (int)nr[0];
421  id /= nr[0];
422  idy = id % (int)nr[1];
423  id /= nr[1];
424  idz = id;
425 }
426 
427 inline bool ArbitraryDomain::isInside(int idx, int idy, int idz) {
428 
429  return IsInsideMap[toCoordIdx(idx, idy, idz)];
430 }
431 
432 /*
433  inline bool ArbitraryDomain::isInside(int idx, int idy, int idz) {
434  Vector_t P;
435 
436  P[0] = minCoords_m[0] + (idx + 0.5) * hr[0];
437  P[1] = minCoords_m[1] + (idy + 0.5) * hr[1];
438  P[2] = minCoords_m[2] + (idz + 0.5) * hr[2];
439 
440  return (bgeom_m->fastIsInside(globalInsideP0_m, P) % 2 == 0);
441  }
442 */
443 
444 /*
445  inline bool ArbitraryDomain::isInside(int idx, int idy, int idz) {
446  Vector_t P;
447 
448  P[0] = (idx - (nr[0]-1)/2.0) * hr[0];
449  P[1] = (idy - (nr[1]-1)/2.0) * hr[1];
450  P[2] = (idz - (nr[2]-1)/2.0) * hr[2];
451 
452  bool ret = false;
453  int countH, countL;
454  std::multimap < std::tuple<int, int, int>, double >::iterator itrH, itrL;
455  std::tuple<int, int, int> coordxyz(idx, idy, idz);
456 
457  //check if z is inside with x,y coords
458  itrH = IntersectHiZ.find(coordxyz);
459  itrL = IntersectLoZ.find(coordxyz);
460 
461  countH = IntersectHiZ.count(coordxyz);
462  countL = IntersectLoZ.count(coordxyz);
463  if(countH == 1 && countL == 1)
464  ret = (P[2] <= itrH->second) && (P[2] >= itrL->second);
465 
466  //check if y is inside with x,z coords
467  itrH = IntersectHiY.find(coordxyz);
468  itrL = IntersectLoY.find(coordxyz);
469 
470  countH = IntersectHiY.count(coordxyz);
471  countL = IntersectLoY.count(coordxyz);
472  if(countH == 1 && countL == 1)
473  ret = ret && (P[1] <= itrH->second) && (P[1] >= itrL->second);
474 
475  //check if x is inside with y,z coords
476  itrH = IntersectHiX.find(coordxyz);
477  itrL = IntersectLoX.find(coordxyz);
478 
479  countH = IntersectHiX.count(coordxyz);
480  countL = IntersectLoX.count(coordxyz);
481  if(countH == 1 && countL == 1)
482  ret = ret && (P[0] <= itrH->second) && (P[0] >= itrL->second);
483 
484  return ret;
485  }
486 */
487 
488 int ArbitraryDomain::getNumXY(int z) {
489 
490  return numXY[z];
491 }
492 
493 void ArbitraryDomain::getBoundaryStencil(int idxyz, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
494  int idx = 0, idy = 0, idz = 0;
495 
496  getCoord(idxyz, idx, idy, idz);
497  getBoundaryStencil(idx, idy, idz, W, E, S, N, F, B, C, scaleFactor);
498 }
499 
500 void ArbitraryDomain::getBoundaryStencil(int idx, int idy, int idz, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
501 
502  scaleFactor = 1.0;
503  // determine which interpolation method we use for points near the boundary
504  switch(interpolationMethod){
505  case CONSTANT:
506  constantInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
507  break;
508  case LINEAR:
509  linearInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
510  break;
511  case QUADRATIC:
512  // QuadraticInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
513  break;
514  }
515 
516  // stencil center value has to be positive!
517  assert(C > 0);
518 }
519 
520 void ArbitraryDomain::constantInterpolation(int idx, int idy, int idz, double& W, double& E, double& S, double& N, double& F, double& B, double& C, double &scaleFactor) {
521 
522  W = -1/(hr[0]*hr[0]);
523  E = -1/(hr[0]*hr[0]);
524  N = -1/(hr[1]*hr[1]);
525  S = -1/(hr[1]*hr[1]);
526  F = -1/(hr[2]*hr[2]);
527  B = -1/(hr[2]*hr[2]);
528  C = 2/(hr[0]*hr[0]) + 2/(hr[1]*hr[1]) + 2/(hr[2]*hr[2]);
529 
530  if(!isInside(idx-1,idy,idz))
531  W = 0.0;
532  if(!isInside(idx+1,idy,idz))
533  E = 0.0;
534 
535  if(!isInside(idx,idy+1,idz))
536  N = 0.0;
537  if(!isInside(idx,idy-1,idz))
538  S = 0.0;
539 
540  if(!isInside(idx,idy,idz-1))
541  F = 0.0;
542  if(!isInside(idx,idy,idz+1))
543  B = 0.0;
544 }
545 
546 void ArbitraryDomain::linearInterpolation(int idx, int idy, int idz, double& W, double& E, double& S, double& N, double& F, double& B, double& C, double &scaleFactor)
547 {
548  scaleFactor = 1;
549 
550  double cx = (idx - (nr[0]-1)/2.0)*hr[0];
551  double cy = (idy - (nr[1]-1)/2.0)*hr[1];
552  double cz = (idz - (nr[2]-1)/2.0)*hr[2];
553 
554  double dx_w=hr[0];
555  double dx_e=hr[0];
556  double dy_n=hr[1];
557  double dy_s=hr[1];
558  double dz_f=hr[2];
559  double dz_b=hr[2];
560  C = 0.0;
561 
562  std::tuple<int, int, int> coordxyz(idx, idy, idz);
563 
564  if (idx == nr[0]-1)
565  dx_e = fabs(IntersectHiX.find(coordxyz)->second - cx);
566  if (idx == 0)
567  dx_w = fabs(IntersectLoX.find(coordxyz)->second - cx);
568  if (idy == nr[1]-1)
569  dy_n = fabs(IntersectHiY.find(coordxyz)->second - cy);
570  if (idy == 0)
571  dy_s = fabs(IntersectLoY.find(coordxyz)->second - cy);
572  if (idz == nr[2]-1)
573  dz_b = fabs(IntersectHiZ.find(coordxyz)->second - cz);
574  if (idz == 0)
575  dz_f = fabs(IntersectLoZ.find(coordxyz)->second - cz);
576 
577  if(dx_w != 0)
578  W = -(dz_f + dz_b) * (dy_n + dy_s) / dx_w;
579  else
580  W = 0;
581  if(dx_e != 0)
582  E = -(dz_f + dz_b) * (dy_n + dy_s) / dx_e;
583  else
584  E = 0;
585  if(dy_n != 0)
586  N = -(dz_f + dz_b) * (dx_w + dx_e) / dy_n;
587  else
588  N = 0;
589  if(dy_s != 0)
590  S = -(dz_f + dz_b) * (dx_w + dx_e) / dy_s;
591  else
592  S = 0;
593  if(dz_f != 0)
594  F = -(dx_w + dx_e) * (dy_n + dy_s) / dz_f;
595  else
596  F = 0;
597  if(dz_b != 0)
598  B = -(dx_w + dx_e) * (dy_n + dy_s) / dz_b;
599  else
600  B = 0;
601 
602  //RHS scaleFactor for current 3D index
603  //0.5* comes from discretiztaion
604  //scaleFactor = 0.5*(dw+de)*(dn+ds)*(df+db);
605  scaleFactor = 0.5;
606  if(dx_w + dx_e != 0)
607  scaleFactor *= (dx_w + dx_e);
608  if(dy_n + dy_s != 0)
609  scaleFactor *= (dy_n + dy_s);
610  if(dz_f + dz_b != 0)
611  scaleFactor *= (dz_f + dz_b);
612 
613  //catch the case where a point lies on the boundary
614  double m1 = dx_w * dx_e;
615  double m2 = dy_n * dy_s;
616  if(dx_e == 0)
617  m1 = dx_w;
618  if(dx_w == 0)
619  m1 = dx_e;
620  if(dy_n == 0)
621  m2 = dy_s;
622  if(dy_s == 0)
623  m2 = dy_n;
624 
625  C = 2 / hr[2];
626  if(dx_w != 0 || dx_e != 0)
627  C *= (dx_w + dx_e);
628  if(dy_n != 0 || dy_s != 0)
629  C *= (dy_n + dy_s);
630  if(dx_w != 0 || dx_e != 0)
631  C += (dz_f + dz_b) * (dy_n + dy_s) * (dx_w + dx_e) / m1;
632  if(dy_n != 0 || dy_s != 0)
633  C += (dz_f + dz_b) * (dx_w + dx_e) * (dy_n + dy_s) / m2;
634 }
635 
636 void ArbitraryDomain::getNeighbours(int id, int &W, int &E, int &S, int &N, int &F, int &B) {
637 
638  int idx = 0, idy = 0, idz = 0;
639 
640  getCoord(id, idx, idy, idz);
641  getNeighbours(idx, idy, idz, W, E, S, N, F, B);
642 }
643 
644 void ArbitraryDomain::getNeighbours(int idx, int idy, int idz, int &W, int &E, int &S, int &N, int &F, int &B) {
645 
646  W = getIdx(idx - 1, idy, idz);
647  E = getIdx(idx + 1, idy, idz);
648  N = getIdx(idx, idy + 1, idz);
649  S = getIdx(idx, idy - 1, idz);
650  F = getIdx(idx, idy, idz - 1);
651  B = getIdx(idx, idy, idz + 1);
652 
653  if(!isInside(idx+1,idy,idz))
654  E = -1;
655 
656  if(!isInside(idx-1,idy,idz))
657  W = -1;
658 
659  if(!isInside(idx,idy+1,idz))
660  N = -1;
661 
662  if(!isInside(idx,idy-1,idz))
663  S = -1;
664 
665  if(!isInside(idx,idy,idz-1))
666  F = -1;
667 
668  if(!isInside(idx,idy,idz+1))
669  B = -1;
670 
671 }
672 
673 
674 inline void ArbitraryDomain::crossProduct(double A[], double B[], double C[]) {
675  C[0] = A[1] * B[2] - A[2] * B[1];
676  C[1] = A[2] * B[0] - A[0] * B[2];
677  C[2] = A[0] * B[1] - A[1] * B[0];
678 }
679 
680 inline void ArbitraryDomain::rotateWithQuaternion(Vector_t & v, Quaternion_t const quaternion) {
681  // rotates a Vector_t (3 elements) using a quaternion.
682  // Flip direction of rotation by quaternionVectorcomponent *= -1
683 
684  Vector_t const quaternionVectorComponent = Vector_t(quaternion(1), quaternion(2), quaternion(3));
685  double const quaternionScalarComponent = quaternion(0);
686 
687  v = 2.0 * dot(quaternionVectorComponent, v) * quaternionVectorComponent
688  + (quaternionScalarComponent * quaternionScalarComponent
689  - dot(quaternionVectorComponent, quaternionVectorComponent)) * v
690  + 2.0 * quaternionScalarComponent * cross(quaternionVectorComponent, v);
691 }
692 
693 inline void ArbitraryDomain::rotateXAxisWithQuaternion(Vector_t & v, Quaternion_t const quaternion) {
694  // rotates the positive xaxis using a quaternion.
695 
696  v(0) = (quaternion(0) * quaternion(0)
697  + quaternion(1) * quaternion(1)
698  - quaternion(2) * quaternion(2)
699  - quaternion(3) * quaternion(3));
700 
701  v(1) = 2.0 * (quaternion(1) * quaternion(2) + quaternion(0) * quaternion(3));
702  v(2) = 2.0 * (quaternion(1) * quaternion(3) - quaternion(0) * quaternion(2));
703 }
704 
705 inline void ArbitraryDomain::rotateYAxisWithQuaternion(Vector_t & v, Quaternion_t const quaternion) {
706  // rotates the positive yaxis using a quaternion.
707 
708  v(0) = 2.0 * (quaternion(1) * quaternion(2) - quaternion(0) * quaternion(3));
709 
710  v(1) = (quaternion(0) * quaternion(0)
711  - quaternion(1) * quaternion(1)
712  + quaternion(2) * quaternion(2)
713  - quaternion(3) * quaternion(3));
714 
715  v(2) = 2.0 * (quaternion(2) * quaternion(3) + quaternion(0) * quaternion(1));
716 }
717 
718 inline void ArbitraryDomain::rotateZAxisWithQuaternion(Vector_t & v, Quaternion_t const quaternion) {
719  // rotates the positive zaxis using a quaternion.
720  v(0) = 2.0 * (quaternion(1) * quaternion(3) + quaternion(0) * quaternion(2));
721  v(1) = 2.0 * (quaternion(2) * quaternion(3) - quaternion(0) * quaternion(1));
722 
723  v(2) = (quaternion(0) * quaternion(0)
724  - quaternion(1) * quaternion(1)
725  - quaternion(2) * quaternion(2)
726  + quaternion(3) * quaternion(3));
727 
728 }
729 #endif //#ifdef HAVE_SAAMG_SOLVER
Definition: TSVMeta.h:24
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
Definition: PETE.h:815
const int nr
Definition: ClassicRandom.h:24
Inform * gmsg
Definition: Main.cpp:21
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Definition: Vector3D.cpp:118
Inform & level2(Inform &inf)
Definition: Inform.cpp:46
Vector_t getmaxcoords()
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Definition: Vector3D.cpp:111
Vector_t getmincoords()
#define INFOMSG(msg)
Definition: IpplInfo.h:397
Vektor< double, 3 > Vector_t
Definition: Vektor.h:6
Inform & endl(Inform &inf)
Definition: Inform.cpp:42