OPAL (Object Oriented Parallel Accelerator Library)  2024.1
OPAL
IrregularDomain.cpp
Go to the documentation of this file.
1 //
2 // Class IrregularDomain
3 // Defines a common abstract interface for different types of boundaries.
4 //
5 // Copyright (c) 2008, Yves Ineichen, ETH Zürich,
6 // 2013 - 2015, Tülin Kaman, Paul Scherrer Institut, Villigen PSI, Switzerland
7 // 2017 - 2020, Paul Scherrer Institut, Villigen PSI, Switzerland
8 // All rights reserved
9 //
10 // Implemented as part of the master thesis
11 // "A Parallel Multigrid Solver for Beam Dynamics"
12 // and the paper
13 // "A fast parallel Poisson solver on irregular domains applied to beam dynamics simulations"
14 // (https://doi.org/10.1016/j.jcp.2010.02.022)
15 //
16 // This file is part of OPAL.
17 //
18 // OPAL is free software: you can redistribute it and/or modify
19 // it under the terms of the GNU General Public License as published by
20 // the Free Software Foundation, either version 3 of the License, or
21 // (at your option) any later version.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with OPAL. If not, see <https://www.gnu.org/licenses/>.
25 //
26 
28 
29 #include "Utility/PAssert.h"
31 
33  const std::string& interpl)
34  : nr_m(nr)
35  , hr_m(hr)
36 {
37  if (interpl == "CONSTANT")
39  else if (interpl == "LINEAR")
41  else if (interpl == "QUADRATIC")
43 }
44 
45 
46 void IrregularDomain::getNeighbours(int x, int y, int z, StencilIndex_t& index) const
47 {
48  index.west = -1;
49  index.east = -1;
50  index.south = -1;
51  index.north = -1;
52  index.front = -1;
53  index.back = -1;
54 
55  if (x > 0 && isInside(x - 1, y, z))
56  index.west = getIdx(x - 1, y, z);
57 
58  if (x < nr_m[0] - 1 && isInside(x + 1, y, z))
59  index.east = getIdx(x + 1, y, z);
60 
61  if (y > 0 && isInside(x, y - 1, z))
62  index.south = getIdx(x, y - 1, z);
63 
64  if (y < nr_m[1] - 1 && isInside(x, y + 1, z))
65  index.north = getIdx(x, y + 1, z);
66 
67  if (z > 0 && isInside(x, y, z - 1))
68  index.front = getIdx(x, y, z - 1);
69 
70  if (z < nr_m[2] - 1 && isInside(x, y, z + 1))
71  index.back = getIdx(x, y, z + 1);
72 }
73 
74 
75 void IrregularDomain::getNeighbours(int id, StencilIndex_t& index) const {
76  int x = 0, y = 0, z = 0;
77  getCoord(id, x, y, z);
78  getNeighbours(x, y, z, index);
79 }
80 
81 
82 void IrregularDomain::getCoord(int idx, int& x, int& y, int& z) const {
83  int xy = coordAccess(idx);
84  x = xy % nr_m[0];
85  y = (xy - x) / nr_m[0];
86  z = idx / getNumXY();
87 }
88 
89 int IrregularDomain::getIdx(int x, int y, int z) const {
90  if (x < 0 || y < 0 || z < 0 || !isInside(x, y, z))
91  return -1;
92  return indexAccess(x, y, z);
93 }
94 
95 void IrregularDomain::getBoundaryStencil(int x, int y, int z, StencilValue_t& value,
96  double &scaleFactor) const
97 {
98  scaleFactor = 1.0;
99 
100  // determine which interpolation method we use for points near the boundary
101  switch (interpolationMethod_m) {
102  case CONSTANT:
103  constantInterpolation(x, y, z, value, scaleFactor);
104  break;
105  case LINEAR:
106  linearInterpolation(x, y, z, value, scaleFactor);
107  break;
108  case QUADRATIC:
109  quadraticInterpolation(x, y, z, value, scaleFactor);
110  break;
111  }
112 
113  // stencil center value has to be positive!
114  PAssert(value.center > 0);
115 }
116 
117 
119  double &scaleFactor) const
120 {
121  int idx = 0, idy = 0, idz = 0;
122  getCoord(id, idx, idy, idz);
123  getBoundaryStencil(idx, idy, idz, value, scaleFactor);
124 }
125 
126 
128  const Vector_t& /*rmin*/, const Vector_t& /*rmax*/,
129  double /*dh*/)
130 {
131  origin = min_m;
132  for (int i = 0; i < 3; i++)
133  hr[i] = (max_m[i] - min_m[i]) / nr_m[i];
134 };
135 
136 
137 void IrregularDomain::constantInterpolation(int /*idx*/, int /*idy*/, int /*idz*/,
138  StencilValue_t& /*value*/, double &/*scaleFactor*/) const
139 {
140  throw OpalException("IrregularDomain::constantInterpolation()",
141  "No constant interpolation method Implemented!");
142 }
143 
144 
145 void IrregularDomain::linearInterpolation(int /*idx*/, int /*idy*/, int /*idz*/,
146  StencilValue_t& /*value*/, double &/*scaleFactor*/) const
147 {
148  throw OpalException("IrregularDomain::linearInterpolation()",
149  "No linear interpolation method Implemented!");
150 }
151 
152 
153 void IrregularDomain::quadraticInterpolation(int /*idx*/, int /*idy*/, int /*idz*/,
154  StencilValue_t& /*value*/, double &/*scaleFactor*/) const
155 {
156  throw OpalException("IrregularDomain::quadraticInterpolation()",
157  "No quadratic interpolation method Implemented!");
158 }
virtual bool isInside(int x, int y, int z) const =0
virtual int indexAccess(int x, int y, int z) const =0
IntVector_t nr_m
number of mesh points in each direction
IrregularDomain(const IntVector_t &nr, const Vector_t &hr, const std::string &interpl)
virtual int coordAccess(int idx) const =0
void getNeighbours(int x, int y, int z, StencilIndex_t &index) const
int interpolationMethod_m
interpolation type
The base class for all OPAL exceptions.
Definition: OpalException.h:28
virtual void quadraticInterpolation(int x, int y, int z, StencilValue_t &value, double &scaleFactor) const
virtual void constantInterpolation(int x, int y, int z, StencilValue_t &value, double &scaleFactor) const
different interpolation methods for boundary points
virtual int getNumXY() const
int getIdx(int x, int y, int z) const
Conversion from (x,y,z) to index on the 3D grid.
virtual void resizeMesh(Vector_t &origin, Vector_t &hr, const Vector_t &, const Vector_t &, double)
void getBoundaryStencil(int x, int y, int z, StencilValue_t &value, double &scaleFactor) const
virtual void linearInterpolation(int x, int y, int z, StencilValue_t &value, double &scaleFactor) const
virtual void getCoord(int idx, int &x, int &y, int &z) const
Conversion from a 3D index to (x,y,z)
#define PAssert(c)
Definition: PAssert.h:102
const int nr
Definition: ClassicRandom.h:24