OPAL (Object Oriented Parallel Accelerator Library)  2.2.0
OPAL
BoxCornerDomain.cpp
Go to the documentation of this file.
1 #ifdef HAVE_SAAMG_SOLVER
3 
4 #include <map>
5 #include <string>
6 #include <cmath>
7 #include <iostream>
8 #include <assert.h>
9 
10 //FIXME: ORDER HOW TO TRAVERSE NODES IS FIXED, THIS SHOULD BE MORE GENERIC! (PLACES MARKED)
11 
12 extern Inform *gmsg;
13 
14 BoxCornerDomain::BoxCornerDomain(Vector_t nr, Vector_t hr) {
15  setNr(nr);
16  setHr(hr);
17 }
18 
19 BoxCornerDomain::BoxCornerDomain(double A, double B, double C, double Length, double L1, double L2, Vector_t nr, Vector_t hr, std::string interpl) {
20  A_m = A;
21  B_m = B;
22  C_m = C;
23  Length_m = Length;
24  L1_m = L1;
25  L2_m = L2;
26 
27  setNr(nr);
28  setHr(hr);
29 
30  if(interpl == "CONSTANT")
31  interpolationMethod = CONSTANT;
32  else if(interpl == "LINEAR")
33  interpolationMethod = LINEAR;
34  else if(interpl == "QUADRATIC")
35  interpolationMethod = QUADRATIC;
36 
37  if(Ippl::getNodes() == 1) {
38  *gmsg << " Write BoxCorner data to file boxcorner.dat" << endl;
39  std::string file("boxcorner.dat");
40  os_m.open(file.c_str());
41  if(os_m.bad()) {
42  *gmsg << "Unable to open output file " << file << endl;
43  }
44  //os_m << "# ...." << endl;
45  }
46 }
47 
48 BoxCornerDomain::~BoxCornerDomain() {
49  //nothing so far
50 }
51 
52 
53 // for this geometry we only have to calculate the intersection on
54 // all x-y-planes
55 // for the moment we center the box corner geometry around the center of the grid
56 // hr holds the grid-spacings (boundary ellipse embedded in hr-grid)
57 
58 void BoxCornerDomain::compute(Vector_t hr){
59 
60  //there is nothing to be done if the mesh spacings have not changed
61  // if(hr[0] == getHr()[0] && hr[1] == getHr()[1] && hr[2] == getHr()[2]) {
62  // hasGeometryChanged_m = false;
63  // return;
64  // }
65 
66  setHr(hr);
67  hasGeometryChanged_m = true;
68 
69  double bL= getB(getMinZ());
70  double bH= getB(getMaxZ());
71 
72  actBMin_m = -B_m;
73  actBMax_m = std::max(bL,bH);
74 
75  INFOMSG(" BoxCorner L= " << Length_m << " L1= " << L1_m << " L2= " << L2_m << " A= " << A_m << " B= " << B_m << " C= " << C_m
76  << " bL= " << bL << " bH= " << bH << " actBMin= " << actBMin_m << " actBMax=max(bL,bH)= " << actBMax_m << endl);
77 
78  //reset number of points inside domain
79 
80  // clear previous coordinate maps
81  IdxMap.clear();
82  CoordMap.clear();
83  //clear previous intersection points
84  IntersectYDir.clear();
85  IntersectXDir.clear();
86 
87  // build a index and coordinate map
88  int idx = 0;
89  int x, y, z;
90  for(x = 0; x < nr[0]; x++) {
91  for(y = 0; y < nr[1]; y++) {
92  for(z = 0; z < nr[2]; z++) {
93  if(isInside(x, y, z)) {
94  IdxMap[toCoordIdx(x, y, z)] = idx;
95  CoordMap[idx++] = toCoordIdx(x, y, z);
96  }
97  }
98  }
99  }
100 
101  //XXX: calculate intersection on the fly
102  /*
103  switch(interpolationMethod) {
104 
105  case CONSTANT:
106  break;
107  case LINEAR:
108  case QUADRATIC:
109 
110  // calculate intersection
111 
112  for(int z = 0; z < nr[2]; z++) {
113 
114  for(int x = 0; x < nr[0]; x++) {
115  // the x coordinate does not change in the CornerBox geometry
116  std::pair<int, int> pos(x, z);
117  IntersectXDir.insert(std::pair< std::pair<int, int>, double >(pos, 0.5*A_m));
118  IntersectXDir.insert(std::pair< std::pair<int, int>, double >(pos, -0.5*A_m));
119  }
120 
121  for(int y = 0; y < nr[1]; y++) {
122  std::pair<int, int> pos(y, z);
123  double yt = getB(z*hr[2]);
124  double yb = -0.5*B_m;
125  IntersectXDir.insert(std::pair< std::pair<int, int>, double >(pos, yt));
126  IntersectXDir.insert(std::pair< std::pair<int, int>, double >(pos, yb));
127  }
128  }
129  }
130  */
131 }
132 
133 void BoxCornerDomain::compute(Vector_t hr, NDIndex<3> localId){
134 }
135 
136 void BoxCornerDomain::getBoundaryStencil(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
137 
138  // determine which interpolation method we use for points near the boundary
139  switch(interpolationMethod) {
140  case CONSTANT:
141  constantInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
142  break;
143  case LINEAR:
144  linearInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
145  break;
146  case QUADRATIC:
147  quadraticInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
148  break;
149  }
150 
151  // stencil center value has to be positive!
152  assert(C > 0);
153 }
154 
155 void BoxCornerDomain::getBoundaryStencil(int idx, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
156 
157 
158  int x = 0, y = 0, z = 0;
159  getCoord(idx, x, y, z);
160  getBoundaryStencil(x, y, z, W, E, S, N, F, B, C, scaleFactor);
161 }
162 
163 
164 void BoxCornerDomain::getNeighbours(int idx, int &W, int &E, int &S, int &N, int &F, int &B) {
165 
166  int x = 0, y = 0, z = 0;
167  getCoord(idx, x, y, z);
168  getNeighbours(x, y, z, W, E, S, N, F, B);
169 
170 }
171 
172 void BoxCornerDomain::getNeighbours(int x, int y, int z, int &W, int &E, int &S, int &N, int &F, int &B) {
173 
174  if(x > 0)
175  W = getIdx(x - 1, y, z);
176  else
177  W = -1;
178  if(x < nr[0] - 1)
179  E = getIdx(x + 1, y, z);
180  else
181  E = -1;
182 
183  if(y < nr[1] - 1)
184  N = getIdx(x, y + 1, z);
185  else
186  N = -1;
187  if(y > 0)
188  S = getIdx(x, y - 1, z);
189  else
190  S = -1;
191 
192  if(z > 0)
193  F = getIdx(x, y, z - 1);
194  else
195  F = -1;
196  if(z < nr[2] - 1)
197  B = getIdx(x, y, z + 1);
198  else
199  B = -1;
200 
201 }
202 
203 void BoxCornerDomain::constantInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
204 
205  scaleFactor = 1.0;
206 
207  W = -1 / hr[0] * 1 / hr[0];
208  E = -1 / hr[0] * 1 / hr[0];
209  N = -1 / hr[1] * 1 / hr[1];
210  S = -1 / hr[1] * 1 / hr[1];
211  F = -1 / hr[2] * 1 / hr[2];
212  B = -1 / hr[2] * 1 / hr[2];
213  C = 2 / hr[0] * 1 / hr[0] + 2 / hr[1] * 1 / hr[1] + 2 / hr[2] * 1 / hr[2];
214 
215  // we are a right boundary point
216  if(!isInside(x + 1, y, z))
217  E = 0.0;
218 
219  // we are a left boundary point
220  if(!isInside(x - 1, y, z))
221  W = 0.0;
222 
223  // we are a upper boundary point
224  if(!isInside(x, y + 1, z))
225  N = 0.0;
226 
227  // we are a lower boundary point
228  if(!isInside(x, y - 1, z))
229  S = 0.0;
230 
231  if(z == 1 || z == nr[2] - 2) {
232 
233  // case where we are on the Robin BC in Z-direction
234  // where we distinguish two cases
235  // IFF: this values should not matter because they
236  // never make it into the discretization matrix
237  if(z == 1)
238  F = 0.0;
239  else
240  B = 0.0;
241 
242  // add contribution of Robin discretization to center point
243  // d the distance between the center of the bunch and the boundary
244  //double cx = (x-(nr[0]-1)/2)*hr[0];
245  //double cy = (y-(nr[1]-1)/2)*hr[1];
246  //double cz = hr[2]*(nr[2]-1);
247  //double d = sqrt(cx*cx+cy*cy+cz*cz);
248  double d = hr[2] * (nr[2] - 1) / 2;
249  C += 2 / (d * hr[2]);
250  //C += 2/((hr[2]*(nr[2]-1)/2.0) * hr[2]);
251 
252  // scale all stencil-points in z-plane with 0.5 (Robin discretization)
253  W /= 2.0;
254  E /= 2.0;
255  N /= 2.0;
256  S /= 2.0;
257  C /= 2.0;
258  scaleFactor *= 0.5;
259  }
260 
261 }
262 
263 void BoxCornerDomain::linearInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
264 
265  scaleFactor = 1.0;
266 
267  double cx = x * hr[0] - (nr[0] - 1) * hr[0] / 2.0;
268  double cy = y * hr[1] - (nr[1] - 1) * hr[1] / 2.0;
269 
270  //XXX: calculate intersection on the fly
271  /*
272  multimap< pair<int, int>, double >::iterator it;
273  pair< multimap< pair<int, int>, double>::iterator, multimap< pair<int, int>, double>::iterator > ret;
274 
275  double dx = 0.0;
276  std::pair<int, int> coordxz(x, z);
277  ret = IntersectXDir.equal_range(coordxz);
278  if(cx < 0)
279  it++;
280  dx = it->second;
281 
282  double dy = 0.0;
283  std::pair<int, int> coordyz(y, z);
284  ret = IntersectYDir.equal_range(coordyz);
285  if(cy < 0)
286  it++;
287  dy = it->second;
288  */
289 
290  double dw = hr[0];
291  double de = hr[0];
292  double dn = hr[1];
293  double ds = hr[1];
294  C = 0.0;
295 
296  //we are a right boundary point
297  if(!isInside(x + 1, y, z)) {
298  double dx = getXIntersection(cx, z);
299  C += 1 / ((dx - cx) * de);
300  E = 0.0;
301  } else {
302  C += 1 / (de * de);
303  E = -1 / (de * de);
304  }
305 
306  //we are a left boundary point
307  if(!isInside(x - 1, y, z)) {
308  double dx = getXIntersection(cx, z);
309  C += 1 / ((std::abs(dx) - std::abs(cx)) * dw);
310  W = 0.0;
311  } else {
312  C += 1 / (dw * dw);
313  W = -1 / (dw * dw);
314  }
315 
316  //we are a upper boundary point
317  if(!isInside(x, y + 1, z)) {
318  double dy = getYIntersection(cy, z);
319  C += 1 / ((dy - cy) * dn);
320  N = 0.0;
321  } else {
322  C += 1 / (dn * dn);
323  N = -1 / (dn * dn);
324  }
325 
326  //we are a lower boundary point
327  if(!isInside(x, y - 1, z)) {
328  double dy = getYIntersection(cy, z);
329  C += 1 / ((std::abs(dy) - std::abs(cy)) * ds);
330  S = 0.0;
331  } else {
332  C += 1 / (ds * ds);
333  S = -1 / (ds * ds);
334  }
335 
336  F = -1 / (hr[2] * hr[2]);
337  B = -1 / (hr[2] * hr[2]);
338  C += 2 / (hr[2] * hr[2]);
339 
340  // handle boundary condition in z direction
341  if(z == 0 || z == nr[2] - 1) {
342 
343  // case where we are on the NEUMAN BC in Z-direction
344  // where we distinguish two cases
345  if(z == 0)
346  F = 0.0;
347  else
348  B = 0.0;
349 
350  //hr[2]*(nr2[2]-1)/2 = radius
351  double d = hr[2] * (nr[2] - 1) / 2;
352  C += 2 / (d * hr[2]);
353 
354  W /= 2.0;
355  E /= 2.0;
356  N /= 2.0;
357  S /= 2.0;
358  C /= 2.0;
359  scaleFactor *= 0.5;
360 
361  }
362 
363 }
364 
365 //FIXME: this probably needs some cleanup/rewriting
366 void BoxCornerDomain::quadraticInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) {
367 
368  double cx = (x - (nr[0] - 1) / 2.0) * hr[0];
369  double cy = (y - (nr[1] - 1) / 2.0) * hr[1];
370 
371  double dx = getXIntersection(cx, z);
372  double dy = getYIntersection(cy, z);
373 
374  //XXX: calculate intersection on the fly
375  /*
376  multimap< pair<int, int>, double >::iterator it;
377  pair< multimap< pair<int, int>, double>::iterator, multimap< pair<int, int>, double>::iterator > ret;
378 
379  double dx = 0.0;
380  std::pair<int, int> coordxz(x, z);
381  ret = IntersectXDir.equal_range(coordxz);
382  if(cx < 0)
383  it++;
384  dx = it->second;
385 
386  double dy = 0.0;
387  std::pair<int, int> coordyz(y, z);
388  ret = IntersectYDir.equal_range(coordyz);
389  if(cy < 0)
390  it++;
391  dy = it->second;
392  */
393 
394  double dw = hr[0];
395  double de = hr[0];
396  double dn = hr[1];
397  double ds = hr[1];
398  W = 1.0;
399  E = 1.0;
400  N = 1.0;
401  S = 1.0;
402  F = 1.0;
403  B = 1.0;
404  C = 0.0;
405 
406  //TODO: = cx+hr[0] > dx && cx > 0
407  //if((x-nr[0]/2.0+1)*hr[0] > dx && cx > 0) {
410  //de = dx-cx;
411  //}
412 
413  //if((x-nr[0]/2.0-1)*hr[0] < dx && cx < 0) {
416  //dw = std::abs(dx)-std::abs(cx);
417  //}
418 
419  //if((y-nr[1]/2.0+1)*hr[1] > dy && cy > 0) {
422  //dn = dy-cy;
423  //}
424 
425  //if((y-nr[1]/2.0-1)*hr[1] < dy && cy < 0) {
428  //ds = std::abs(dy)-std::abs(cy);
429  //}
430 
431  //TODO: = cx+hr[0] > dx && cx > 0
432  //if((x-nr[0]/2.0+1)*hr[0] > dx && cx > 0) {
433  //we are a right boundary point
434  if(!isInside(x + 1, y, z)) {
435  de = dx - cx;
436  E = 0.0;
437  }
438 
439  //if((x-nr[0]/2.0-1)*hr[0] < dx && cx < 0) {
440  //we are a left boundary point
441  if(!isInside(x - 1, y, z)) {
442  dw = std::abs(dx) - std::abs(cx);
443  W = 0.0;
444  }
445 
446  //if((y-nr[1]/2.0+1)*hr[1] > dy && cy > 0) {
447  //we are a upper boundary point
448  if(!isInside(x, y + 1, z)) {
449  dn = dy - cy;
450  N = 0.0;
451  }
452 
453  //if((y-nr[1]/2.0-1)*hr[1] < dy && cy < 0) {
454  //we are a lower boundary point
455  if(!isInside(x, y - 1, z)) {
456  ds = std::abs(dy) - std::abs(cy);
457  S = 0.0;
458  }
459 
460  //2/dw*(dw_de)
461  W *= -1.0 / (dw * (dw + de));
462  E *= -1.0 / (de * (dw + de));
463  N *= -1.0 / (dn * (dn + ds));
464  S *= -1.0 / (ds * (dn + ds));
465  F = -1 / (hr[2] * (hr[2] + hr[2]));
466  B = -1 / (hr[2] * (hr[2] + hr[2]));
467 
468  //TODO: problem when de,dw,dn,ds == 0
469  //is NOT a regular BOUND PT
470  C += 1 / de * 1 / dw;
471  C += 1 / dn * 1 / ds;
472  C += 1 / hr[2] * 1 / hr[2];
473  scaleFactor = 0.5;
474 
475 
476  //for regular gridpoints no problem with symmetry, just boundary
477  //z direction is right
478  //implement isLastInside(dir)
479  //we have LOCAL x,y coordinates!
480 
481  /*
482  if(dw != 0 && !wIsB)
483  W = -1/dw * (dn+ds) * 2*hr[2];
484  else
485  W = 0;
486  if(de != 0 && !eIsB)
487  E = -1/de * (dn+ds) * 2*hr[2];
488  else
489  E = 0;
490  if(dn != 0 && !nIsB)
491  N = -1/dn * (dw+de) * 2*hr[2];
492  else
493  N = 0;
494  if(ds != 0 && !sIsB)
495  S = -1/ds * (dw+de) * 2*hr[2];
496  else
497  S = 0;
498  F = -(dw+de)*(dn+ds)/hr[2];
499  B = -(dw+de)*(dn+ds)/hr[2];
500  */
501 
502  //if(dw != 0)
503  //W = -2*hr[2]*(dn+ds)/dw;
504  //else
505  //W = 0;
506  //if(de != 0)
507  //E = -2*hr[2]*(dn+ds)/de;
508  //else
509  //E = 0;
510  //if(dn != 0)
511  //N = -2*hr[2]*(dw+de)/dn;
512  //else
513  //N = 0;
514  //if(ds != 0)
515  //S = -2*hr[2]*(dw+de)/ds;
516  //else
517  //S = 0;
518  //F = -(dw+de)*(dn+ds)/hr[2];
519  //B = -(dw+de)*(dn+ds)/hr[2];
520 
523  //scaleFactor = 0.5*(dw+de)*(dn+ds)*(2*hr[2]);
524 
525  // catch the case where a point lies on the boundary
526  //FIXME: do this more elegant!
527  //double m1 = dw*de;
528  //double m2 = dn*ds;
529  //if(de == 0)
530  //m1 = dw;
531  //if(dw == 0)
532  //m1 = de;
533  //if(dn == 0)
534  //m2 = ds;
535  //if(ds == 0)
536  //m2 = dn;
539  //C = 2/hr[2];
540  //if(dw != 0 || de != 0)
541  //C *= (dw+de);
542  //if(dn != 0 || ds != 0)
543  //C *= (dn+ds);
544  //if(dw != 0 || de != 0)
545  //C += (2*hr[2])*(dn+ds)*(dw+de)/m1;
546  //if(dn != 0 || ds != 0)
547  //C += (2*hr[2])*(dw+de)*(dn+ds)/m2;
548 
549  //handle Neumann case
550  //if(z == 0 || z == nr[2]-1) {
551 
552  //if(z == 0)
553  //F = 0.0;
554  //else
555  //B = 0.0;
556 
558  //W = W/2.0;
559  //E = E/2.0;
560  //N = N/2.0;
561  //S = S/2.0;
562  //C /= 2.0;
563 
564  //scaleFactor /= 2.0;
565  //}
566 
567  // handle boundary condition in z direction
568  if(z == 0 || z == nr[2] - 1) {
569 
570  // case where we are on the NEUMAN BC in Z-direction
571  // where we distinguish two cases
572  if(z == 0)
573  F = 0.0;
574  else
575  B = 0.0;
576 
577  //C += 2/((hr[2]*(nr[2]-1)/2.0) * hr[2]);
578  //hr[2]*(nr2[2]-1)/2 = radius
579  double d = hr[2] * (nr[2] - 1) / 2;
580  C += 2 / (d * hr[2]);
581 
582  W /= 2.0;
583  E /= 2.0;
584  N /= 2.0;
585  S /= 2.0;
586  C /= 2.0;
587  scaleFactor /= 2.0;
588 
589  }
590 }
591 
592 
593 #endif //#ifdef HAVE_SAAMG_SOLVER
static int getNodes()
Definition: IpplInfo.cpp:773
PETE_TUTree< FnAbs, typename T::PETE_Expr_t > abs(const PETE_Expr< T > &l)
Definition: TSVMeta.h:24
T::PETE_Expr_t::PETE_Return_t max(const PETE_Expr< T > &expr, NDIndex< D > &loc)
Definition: ReductionLoc.h:123
const int nr
Definition: ClassicRandom.h:24
Inform * gmsg
Definition: Main.cpp:21
#define INFOMSG(msg)
Definition: IpplInfo.h:397
Definition: Inform.h:41
Inform & endl(Inform &inf)
Definition: Inform.cpp:42