Commit 74dde0f2 authored by frey_m's avatar frey_m

SAAMG: use structs for stencil indices and values

parent d8a653c9
......@@ -383,59 +383,56 @@ int ArbitraryDomain::getNumXY(int z) {
return numXY[z];
}
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)
void ArbitraryDomain::getBoundaryStencil(int idx, int idy, int idz,
StencilValue_t& value, double &scaleFactor)
{
scaleFactor = 1.0;
// determine which interpolation method we use for points near the boundary
switch(interpolationMethod){
case CONSTANT:
constantInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
constantInterpolation(idx,idy,idz,value,scaleFactor);
break;
case LINEAR:
linearInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
linearInterpolation(idx,idy,idz,value,scaleFactor);
break;
case QUADRATIC:
// QuadraticInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
// QuadraticInterpolation(idx,idy,idz,value,scaleFactor);
break;
}
// stencil center value has to be positive!
assert(C > 0);
assert(value.center > 0);
}
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*/)
void ArbitraryDomain::constantInterpolation(int idx, int idy, int idz,
StencilValue_t& value, double& /*scaleFactor*/)
{
W = -1/(hr[0]*hr[0]);
E = -1/(hr[0]*hr[0]);
N = -1/(hr[1]*hr[1]);
S = -1/(hr[1]*hr[1]);
F = -1/(hr[2]*hr[2]);
B = -1/(hr[2]*hr[2]);
C = 2/(hr[0]*hr[0]) + 2/(hr[1]*hr[1]) + 2/(hr[2]*hr[2]);
value.west = -1/(hr[0]*hr[0]);
value.east = -1/(hr[0]*hr[0]);
value.north = -1/(hr[1]*hr[1]);
value.south = -1/(hr[1]*hr[1]);
value.front = -1/(hr[2]*hr[2]);
value.back = -1/(hr[2]*hr[2]);
value.center = 2/(hr[0]*hr[0]) + 2/(hr[1]*hr[1]) + 2/(hr[2]*hr[2]);
if(!isInside(idx-1,idy,idz))
W = 0.0;
value.west = 0.0;
if(!isInside(idx+1,idy,idz))
E = 0.0;
value.east = 0.0;
if(!isInside(idx,idy+1,idz))
N = 0.0;
value.north = 0.0;
if(!isInside(idx,idy-1,idz))
S = 0.0;
value.south = 0.0;
if(!isInside(idx,idy,idz-1))
F = 0.0;
value.front = 0.0;
if(!isInside(idx,idy,idz+1))
B = 0.0;
value.back = 0.0;
}
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)
void ArbitraryDomain::linearInterpolation(int idx, int idy, int idz,
StencilValue_t& value, double &scaleFactor)
{
scaleFactor = 1;
......@@ -449,7 +446,7 @@ void ArbitraryDomain::linearInterpolation(int idx, int idy, int idz, double& W,
double dy_s=hr[1];
double dz_f=hr[2];
double dz_b=hr[2];
C = 0.0;
value.center = 0.0;
std::tuple<int, int, int> coordxyz(idx, idy, idz);
......@@ -467,29 +464,29 @@ void ArbitraryDomain::linearInterpolation(int idx, int idy, int idz, double& W,
dz_f = std::abs(IntersectLoZ.find(coordxyz)->second - cz);
if(dx_w != 0)
W = -(dz_f + dz_b) * (dy_n + dy_s) / dx_w;
value.west = -(dz_f + dz_b) * (dy_n + dy_s) / dx_w;
else
W = 0;
value.west = 0;
if(dx_e != 0)
E = -(dz_f + dz_b) * (dy_n + dy_s) / dx_e;
value.east = -(dz_f + dz_b) * (dy_n + dy_s) / dx_e;
else
E = 0;
value.east = 0;
if(dy_n != 0)
N = -(dz_f + dz_b) * (dx_w + dx_e) / dy_n;
value.north = -(dz_f + dz_b) * (dx_w + dx_e) / dy_n;
else
N = 0;
value.north = 0;
if(dy_s != 0)
S = -(dz_f + dz_b) * (dx_w + dx_e) / dy_s;
value.south = -(dz_f + dz_b) * (dx_w + dx_e) / dy_s;
else
S = 0;
value.south = 0;
if(dz_f != 0)
F = -(dx_w + dx_e) * (dy_n + dy_s) / dz_f;
value.front = -(dx_w + dx_e) * (dy_n + dy_s) / dz_f;
else
F = 0;
value.front = 0;
if(dz_b != 0)
B = -(dx_w + dx_e) * (dy_n + dy_s) / dz_b;
value.back = -(dx_w + dx_e) * (dy_n + dy_s) / dz_b;
else
B = 0;
value.back = 0;
//RHS scaleFactor for current 3D index
//0.5* comes from discretiztaion
......@@ -514,44 +511,43 @@ void ArbitraryDomain::linearInterpolation(int idx, int idy, int idz, double& W,
if(dy_s == 0)
m2 = dy_n;
C = 2 / hr[2];
value.center = 2 / hr[2];
if(dx_w != 0 || dx_e != 0)
C *= (dx_w + dx_e);
value.center *= (dx_w + dx_e);
if(dy_n != 0 || dy_s != 0)
C *= (dy_n + dy_s);
value.center *= (dy_n + dy_s);
if(dx_w != 0 || dx_e != 0)
C += (dz_f + dz_b) * (dy_n + dy_s) * (dx_w + dx_e) / m1;
value.center += (dz_f + dz_b) * (dy_n + dy_s) * (dx_w + dx_e) / m1;
if(dy_n != 0 || dy_s != 0)
C += (dz_f + dz_b) * (dx_w + dx_e) * (dy_n + dy_s) / m2;
value.center += (dz_f + dz_b) * (dx_w + dx_e) * (dy_n + dy_s) / m2;
}
void ArbitraryDomain::getNeighbours(int idx, int idy, int idz, int &W,
int &E, int &S, int &N, int &F, int &B)
void ArbitraryDomain::getNeighbours(int idx, int idy, int idz, StencilIndex_t& index)
{
W = getIdx(idx - 1, idy, idz);
E = getIdx(idx + 1, idy, idz);
N = getIdx(idx, idy + 1, idz);
S = getIdx(idx, idy - 1, idz);
F = getIdx(idx, idy, idz - 1);
B = getIdx(idx, idy, idz + 1);
index.west = getIdx(idx - 1, idy, idz);
index.east = getIdx(idx + 1, idy, idz);
index.north = getIdx(idx, idy + 1, idz);
index.south = getIdx(idx, idy - 1, idz);
index.front = getIdx(idx, idy, idz - 1);
index.back = getIdx(idx, idy, idz + 1);
if(!isInside(idx+1,idy,idz))
E = -1;
index.east = -1;
if(!isInside(idx-1,idy,idz))
W = -1;
index.west = -1;
if(!isInside(idx,idy+1,idz))
N = -1;
index.north = -1;
if(!isInside(idx,idy-1,idz))
S = -1;
index.south = -1;
if(!isInside(idx,idy,idz-1))
F = -1;
index.front = -1;
if(!isInside(idx,idy,idz+1))
B = -1;
index.back = -1;
}
......
......@@ -43,6 +43,8 @@ class BoundaryGeometry;
class ArbitraryDomain : public IrregularDomain {
public:
using IrregularDomain::StencilIndex_t;
using IrregularDomain::StencilValue_t;
ArbitraryDomain(BoundaryGeometry *bgeom, Vector_t nr, Vector_t hr,
std::string interpl);
......@@ -54,13 +56,11 @@ public:
~ArbitraryDomain();
/// returns discretization at (x,y,z)
void getBoundaryStencil(int idx, int idy, int idz, double &W, double &E,
double &S, double &N, double &F, double &B, double &C,
void getBoundaryStencil(int idx, int idy, int idz, StencilValue_t& value,
double &scaleFactor);
/// returns index of neighbours at (x,y,z)
void getNeighbours(int idx, int idy, int idz, int &W,
int &E, int &S, int &N, int &F, int &B);
void getNeighbours(int idx, int idy, int idz, StencilIndex_t& index);
/// returns type of boundary condition
std::string getType() {return "Geometric";}
......@@ -158,17 +158,14 @@ private:
}
// Different interpolation methods for boundary points
void constantInterpolation(int idx, int idy, int idz, double &W, double &E,
double &S, double &N, double &F, double &B,
double &C, double &scaleFactor);
void constantInterpolation(int idx, int idy, int idz, StencilValue_t& value,
double &scaleFactor);
void linearInterpolation(int idx, int idy, int idz, double &W, double &E,
double &S, double &N, double &F, double &B,
double &C, double &scaleFactor);
void linearInterpolation(int idx, int idy, int idz, StencilValue_t& value,
double &scaleFactor);
void quadraticInterpolation(int idx, int idy, int idz, double &W, double &E,
double &S, double &N, double &F, double &B,
double &C, double &scaleFactor);
void quadraticInterpolation(int idx, int idy, int idz, StencilValue_t& value,
double &scaleFactor);
// Rotate positive axes with quaternion -DW
inline void rotateWithQuaternion(Vector_t &v, Quaternion_t const quaternion);
......
This diff is collapsed.
......@@ -69,6 +69,8 @@ Test in which of the 3 parts of the geometry we are in.
class BoxCornerDomain : public IrregularDomain {
public:
using IrregularDomain::StencilIndex_t;
using IrregularDomain::StencilValue_t;
BoxCornerDomain(Vector_t nr, Vector_t hr);
BoxCornerDomain(double A, double B, double C, double Length, double L1, double L2, Vector_t nr, Vector_t hr,
......@@ -76,11 +78,10 @@ public:
~BoxCornerDomain();
/// returns discretization at (x,y,z)
void getBoundaryStencil(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B,
double &C, double &scaleFactor);
void getBoundaryStencil(int x, int y, int z, StencilValue_t& value, double &scaleFactor);
/// returns index of neighbours at (x,y,z)
void getNeighbours(int x, int y, int z, int &W, int &E, int &S, int &N, int &F, int &B);
void getNeighbours(int x, int y, int z, StencilIndex_t& index);
/// returns type of boundary condition
std::string getType() {return "BoxCorner";}
......@@ -232,9 +233,14 @@ private:
}
/// different interpolation methods for boundary points
void constantInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor);
void linearInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor);
void quadraticInterpolation(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor);
void constantInterpolation(int x, int y, int z, StencilValue_t& value,
double &scaleFactor);
void linearInterpolation(int x, int y, int z, StencilValue_t& value,
double &scaleFactor);
void quadraticInterpolation(int x, int y, int z, StencilValue_t& value,
double &scaleFactor);
};
......
......@@ -179,9 +179,7 @@ void EllipticDomain::resizeMesh(Vector_t& origin, Vector_t& hr, const Vector_t&
hr[i] = (mymax[i] - origin[i]) / nr[i];
}
void EllipticDomain::getBoundaryStencil(int x, int y, int z, double &W,
double &E, double &S, double &N,
double &F, double &B, double &C,
void EllipticDomain::getBoundaryStencil(int x, int y, int z, StencilValue_t& value,
double &scaleFactor)
{
scaleFactor = 1.0;
......@@ -189,96 +187,92 @@ void EllipticDomain::getBoundaryStencil(int x, int y, int z, double &W,
// determine which interpolation method we use for points near the boundary
switch (interpolationMethod_m) {
case CONSTANT:
constantInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
constantInterpolation(x, y, z, value, scaleFactor);
break;
case LINEAR:
linearInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
linearInterpolation(x, y, z, value, scaleFactor);
break;
case QUADRATIC:
quadraticInterpolation(x, y, z, W, E, S, N, F, B, C, scaleFactor);
quadraticInterpolation(x, y, z, value, scaleFactor);
break;
}
// stencil center value has to be positive!
assert(C > 0);
assert(value.center > 0);
}
void EllipticDomain::getNeighbours(int x, int y, int z, int &W, int &E,
int &S, int &N, int &F, int &B)
void EllipticDomain::getNeighbours(int x, int y, int z,
StencilIndex_t& index)
{
if (x > 0)
W = getIdx(x - 1, y, z);
index.west = getIdx(x - 1, y, z);
else
W = -1;
index.west = -1;
if (x < nr[0] - 1)
E = getIdx(x + 1, y, z);
index.east = getIdx(x + 1, y, z);
else
E = -1;
index.east = -1;
if (y < nr[1] - 1)
N = getIdx(x, y + 1, z);
index.north = getIdx(x, y + 1, z);
else
N = -1;
index.north = -1;
if (y > 0)
S = getIdx(x, y - 1, z);
index.south = getIdx(x, y - 1, z);
else
S = -1;
index.south = -1;
if (z > 0)
F = getIdx(x, y, z - 1);
index.front = getIdx(x, y, z - 1);
else
F = -1;
index.front = -1;
if (z < nr[2] - 1)
B = getIdx(x, y, z + 1);
index.back = getIdx(x, y, z + 1);
else
B = -1;
index.back = -1;
}
void EllipticDomain::constantInterpolation(int x, int y, int z, double &WV,
double &EV, double &SV, double &NV,
double &FV, double &BV, double &CV,
void EllipticDomain::constantInterpolation(int x, int y, int z, StencilValue_t& value,
double &scaleFactor)
{
scaleFactor = 1.0;
WV = -1.0 / (hr[0] * hr[0]);
EV = -1.0 / (hr[0] * hr[0]);
NV = -1.0 / (hr[1] * hr[1]);
SV = -1.0 / (hr[1] * hr[1]);
FV = -1.0 / (hr[2] * hr[2]);
BV = -1.0 / (hr[2] * hr[2]);
value.west = -1.0 / (hr[0] * hr[0]);
value.east = -1.0 / (hr[0] * hr[0]);
value.north = -1.0 / (hr[1] * hr[1]);
value.south = -1.0 / (hr[1] * hr[1]);
value.front = -1.0 / (hr[2] * hr[2]);
value.back = -1.0 / (hr[2] * hr[2]);
CV = 2.0 / (hr[0] * hr[0])
+ 2.0 / (hr[1] * hr[1])
+ 2.0 / (hr[2] * hr[2]);
value.center = 2.0 / (hr[0] * hr[0])
+ 2.0 / (hr[1] * hr[1])
+ 2.0 / (hr[2] * hr[2]);
// we are a right boundary point
if (!isInside(x + 1, y, z))
EV = 0.0;
value.east = 0.0;
// we are a left boundary point
if (!isInside(x - 1, y, z))
WV = 0.0;
value.west = 0.0;
// we are a upper boundary point
if (!isInside(x, y + 1, z))
NV = 0.0;
value.north = 0.0;
// we are a lower boundary point
if (!isInside(x, y - 1, z))
SV = 0.0;
value.south = 0.0;
// handle boundary condition in z direction
robinBoundaryStencil(z, FV, BV, CV);
robinBoundaryStencil(z, value.front, value.back, value.center);
}
void EllipticDomain::linearInterpolation(int x, int y, int z, double &W,
double &E, double &S, double &N,
double &F, double &B, double &C,
void EllipticDomain::linearInterpolation(int x, int y, int z, StencilValue_t& value,
double &scaleFactor)
{
scaleFactor = 1.0;
......@@ -304,54 +298,53 @@ void EllipticDomain::linearInterpolation(int x, int y, int z, double &W,
double de = hr[0];
double dn = hr[1];
double ds = hr[1];
C = 0.0;
value.center = 0.0;
// we are a right boundary point
if (!isInside(x + 1, y, z)) {
C += 1.0 / ((dx - cx) * de);
E = 0.0;
value.center += 1.0 / ((dx - cx) * de);
value.east = 0.0;
} else {
C += 1.0 / (de * de);
E = -1.0 / (de * de);
value.center += 1.0 / (de * de);
value.east = -1.0 / (de * de);
}
// we are a left boundary point
if (!isInside(x - 1, y, z)) {
C += 1.0 / ((std::abs(dx) - std::abs(cx)) * dw);
W = 0.0;
value.center += 1.0 / ((std::abs(dx) - std::abs(cx)) * dw);
value.west = 0.0;
} else {
C += 1.0 / (dw * dw);
W = -1.0 / (dw * dw);
value.center += 1.0 / (dw * dw);
value.west = -1.0 / (dw * dw);
}
// we are a upper boundary point
if (!isInside(x, y + 1, z)) {
C += 1.0 / ((dy - cy) * dn);
N = 0.0;
value.center += 1.0 / ((dy - cy) * dn);
value.north = 0.0;
} else {
C += 1.0 / (dn * dn);
N = -1.0 / (dn * dn);
value.center += 1.0 / (dn * dn);
value.north = -1.0 / (dn * dn);
}
// we are a lower boundary point
if (!isInside(x, y - 1, z)) {
C += 1.0 / ((std::abs(dy) - std::abs(cy)) * ds);
S = 0.0;
value.center += 1.0 / ((std::abs(dy) - std::abs(cy)) * ds);
value.south = 0.0;
} else {
C += 1.0 / (ds * ds);
S = -1.0 / (ds * ds);
value.center += 1.0 / (ds * ds);
value.south = -1.0 / (ds * ds);
}
// handle boundary condition in z direction
F = -1.0 / (hr[2] * hr[2]);
B = -1.0 / (hr[2] * hr[2]);
C += 2.0 / (hr[2] * hr[2]);
robinBoundaryStencil(z, F, B, C);
value.front = -1.0 / (hr[2] * hr[2]);
value.back = -1.0 / (hr[2] * hr[2]);
value.center += 2.0 / (hr[2] * hr[2]);
robinBoundaryStencil(z, value.front, value.back, value.center);
}
void EllipticDomain::quadraticInterpolation(int x, int y, int z,
double &W, double &E, double &S,
double &N, double &F, double &B, double &C,
StencilValue_t& value,
double &scaleFactor)
{
scaleFactor = 1.0;
......@@ -378,61 +371,61 @@ void EllipticDomain::quadraticInterpolation(int x, int y, int z,
double dn = hr[1];
double ds = hr[1];
W = 0.0;
E = 0.0;
S = 0.0;
N = 0.0;
C = 0.0;
value.west = 0.0;
value.east = 0.0;
value.south = 0.0;
value.north = 0.0;
value.center = 0.0;
// we are a right boundary point
if (!isInside(x + 1, y, z)) {
double s = dx - cx;
C -= 2.0 * (s - 1.0) / (s * de);
E = 0.0;
W += (s - 1.0) / ((s + 1.0) * de);
value.center -= 2.0 * (s - 1.0) / (s * de);
value.east = 0.0;
value.west += (s - 1.0) / ((s + 1.0) * de);
} else {
C += 1.0 / (de * de);
E = -1.0 / (de * de);
value.center += 1.0 / (de * de);
value.east = -1.0 / (de * de);
}
// we are a left boundary point
if (!isInside(x - 1, y, z)) {
double s = std::abs(dx) - std::abs(cx);
C -= 2.0 * (s - 1.0) / (s * de);
W = 0.0;
E += (s - 1.0) / ((s + 1.0) * de);
value.center -= 2.0 * (s - 1.0) / (s * de);
value.west = 0.0;
value.east += (s - 1.0) / ((s + 1.0) * de);
} else {
C += 1.0 / (dw * dw);
W = -1.0 / (dw * dw);
value.center += 1.0 / (dw * dw);
value.west = -1.0 / (dw * dw);
}
// we are a upper boundary point
if (!isInside(x, y + 1, z)) {
double s = dy - cy;
C -= 2.0 * (s - 1.0) / (s * dn);
N = 0.0;
S += (s - 1.0) / ((s + 1.0) * dn);
value.center -= 2.0 * (s - 1.0) / (s * dn);
value.north = 0.0;
value.south += (s - 1.0) / ((s + 1.0) * dn);
} else {
C += 1.0 / (dn * dn);
N = -1.0 / (dn * dn);
value.center += 1.0 / (dn * dn);
value.north = -1.0 / (dn * dn);
}
// we are a lower boundary point
if (!isInside(x, y - 1, z)) {
double s = std::abs(dy) - std::abs(cy);
C -= 2.0 * (s - 1.0) / (s * dn);
S = 0.0;
N += (s - 1.0) / ((s + 1.0) * dn);
value.center -= 2.0 * (s - 1.0) / (s * dn);
value.south = 0.0;
value.north += (s - 1.0) / ((s + 1.0) * dn);
} else {
C += 1.0 / (ds * ds);
S = -1.0 / (ds * ds);
value.center += 1.0 / (ds * ds);
value.south = -1.0 / (ds * ds);
}
// handle boundary condition in z direction
F = -1.0 / (hr[2] * hr[2]);
B = -1.0 / (hr[2] * hr[2]);
C += 2.0 / (hr[2] * hr[2]);
robinBoundaryStencil(z, F, B, C);
value.front = -1.0 / (hr[2] * hr[2]);
value.back = -1.0 / (hr[2] * hr[2]);
value.center += 2.0 / (hr[2] * hr[2]);
robinBoundaryStencil(z, value.front, value.back, value.center);
}
void EllipticDomain::robinBoundaryStencil(int z, double &F, double &B, double &C) {
......
......@@ -39,6 +39,8 @@
class EllipticDomain : public IrregularDomain {
public:
using IrregularDomain::StencilIndex_t;
using IrregularDomain::StencilValue_t;
EllipticDomain(Vector_t nr, Vector_t hr);
......@@ -53,14 +55,11 @@ public:
~EllipticDomain();
/// returns discretization at (x,y,z)
void getBoundaryStencil(int x, int y, int z,
double &W, double &E, double &S,
double &N, double &F, double &B,
double &C, double &scaleFactor);
void getBoundaryStencil(int x, int y, int z, StencilValue_t& values,
double &scaleFactor);
/// returns index of neighbours at (x,y,z)
void getNeighbours(int x, int y, int z, int &W, int &E,
int &S, int &N, int &F, int &B);
void getNeighbours(int x, int y, int z, StencilIndex_t& index);
/// returns type of boundary condition
std::string getType() {return "Elliptic";}
......@@ -150,19 +149,13 @@ private:
}
/// different interpolation methods for boundary points
void constantInterpolation(int x, int y, int z,
double &W, double &E, double &S,