diff --git a/src/Solvers/MGPoissonSolver.cpp b/src/Solvers/MGPoissonSolver.cpp index ddcf129c7ebe3b38e3ae1374d1de41320d266817..e8cd830b4ec19eddd2725fcb4004d56b92cd7bf6 100644 --- a/src/Solvers/MGPoissonSolver.cpp +++ b/src/Solvers/MGPoissonSolver.cpp @@ -40,6 +40,7 @@ #include "ArbitraryDomain.h" #include "EllipticDomain.h" #include "BoxCornerDomain.h" +#include "RectangularDomain.h" #include "Track/Track.h" #include "Physics/Physics.h" @@ -127,6 +128,11 @@ MGPoissonSolver::MGPoissonSolver ( PartBunch *beam, currentGeometry->getL2(), orig_nr_m, hr_m, interpl)); bp_m->compute(itsBunch_m->get_hr()); + } else if (currentGeometry->getTopology() == "RECTANGULAR") { + bp_m = std::unique_ptr<IrregularDomain>( + new RectangularDomain(currentGeometry->getA(), + currentGeometry->getB(), + orig_nr_m, hr_m)); } else { throw OpalException("MGPoissonSolver::MGPoissonSolver", "Geometry not known"); diff --git a/src/Solvers/RectangularDomain.cpp b/src/Solvers/RectangularDomain.cpp index 31f59bbea179968ea17329913ce8a8d05737c2be..fe48a44c84a38167441fd6416afa78a32b8d86b7 100644 --- a/src/Solvers/RectangularDomain.cpp +++ b/src/Solvers/RectangularDomain.cpp @@ -1,6 +1,7 @@ // // Class RectangularDomain -// :FIXME: add brief description +// This class provides a rectangular beam pipe. The mesh adapts to the bunch +// in longitudinal direction. // // Copyright (c) 2008, Yves Ineichen, ETH Zürich, // 2013 - 2015, Tülin Kaman, Paul Scherrer Institut, Villigen PSI, Switzerland @@ -28,20 +29,17 @@ #include "Solvers/RectangularDomain.h" #include "Utilities/OpalException.h" -RectangularDomain::RectangularDomain(Vector_t nr, Vector_t hr) { - setNr(nr); - setHr(hr); - a_m = 0.1; - b_m = 0.1; - nxy_m = nr[0] * nr[1]; -} +RectangularDomain::RectangularDomain(Vector_t nr, Vector_t hr) + : RectangularDomain(0.1, 0.1, nr, hr) +{} -RectangularDomain::RectangularDomain(double a, double b, Vector_t nr, Vector_t hr) { - a_m = a; - b_m = b; +RectangularDomain::RectangularDomain(double a, double b, Vector_t nr, Vector_t hr) + : a_m(a) + , b_m(b) + , nxy_m(nr[0] * nr[1]) +{ setNr(nr); setHr(hr); - nxy_m = nr[0] * nr[1]; } void RectangularDomain::compute(Vector_t hr){ @@ -49,91 +47,55 @@ void RectangularDomain::compute(Vector_t hr){ nxy_m = nr[0] * nr[1]; } +void RectangularDomain::compute(Vector_t hr, NDIndex<3> /*localId*/) { + compute(hr); +} + int RectangularDomain::getNumXY(int /*z*/) { return nxy_m; } -void RectangularDomain::getBoundaryStencil(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) { - - //scaleFactor = 1.0; - - //W = -1/hr[0]*1/hr[0]; - //E = -1/hr[0]*1/hr[0]; - //N = -1/hr[1]*1/hr[1]; - //S = -1/hr[1]*1/hr[1]; - //F = -1/hr[2]*1/hr[2]; - //B = -1/hr[2]*1/hr[2]; - //C = 2/hr[0]*1/hr[0] + 2/hr[1]*1/hr[1] + 2/hr[2]*1/hr[2]; - - scaleFactor = hr[0] * hr[1] * hr[2]; - W = -hr[1] * hr[2] / hr[0]; - E = -hr[1] * hr[2] / hr[0]; - N = -hr[0] * hr[2] / hr[1]; - S = -hr[0] * hr[2] / hr[1]; - F = -hr[0] * hr[1] / hr[2]; - B = -hr[0] * hr[1] / hr[2]; - C = 2 * hr[1] * hr[2] / hr[0] + 2 * hr[0] * hr[2] / hr[1] + 2 * hr[0] * hr[1] / hr[2]; - - if(!isInside(x + 1, y, z)) +void RectangularDomain::getBoundaryStencil(int x, int y, int z, double &W, + double &E, double &S, double &N, + double &F, double &B, double &C, + double &scaleFactor) +{ + scaleFactor = 1.0; + W = -1.0 / (hr[0] * hr[0]); + E = -1.0 / (hr[0] * hr[0]); + N = -1.0 / (hr[1] * hr[1]); + S = -1.0 / (hr[1] * hr[1]); + F = -1.0 / (hr[2] * hr[2]); + B = -1.0 / (hr[2] * hr[2]); + + C = 2.0 / (hr[0] * hr[0]) + + 2.0 / (hr[1] * hr[1]) + + 2.0 / (hr[2] * hr[2]); + + if (!isInside(x + 1, y, z)) E = 0.0; //we are a right boundary point - if(!isInside(x - 1, y, z)) + if (!isInside(x - 1, y, z)) W = 0.0; //we are a left boundary point - if(!isInside(x, y + 1, z)) + if (!isInside(x, y + 1, z)) N = 0.0; //we are a upper boundary point - if(!isInside(x, y - 1, z)) + if (!isInside(x, y - 1, z)) S = 0.0; //we are a lower boundary point //dirichlet - if(z == 0) + if (z == 0) F = 0.0; - if(z == nr[2] - 1) - B = 0.0; - - if(false /*z == 0 || z == nr[2]-1*/) { - - //case where we are on the Robin BC in Z-direction - //where we distinguish two cases - //IFF: this values should not matter because they - //never make it into the discretization matrix - if(z == 0) - F = 0.0; - else - B = 0.0; - - //add contribution of Robin discretization to center point - //d the distance between the center of the bunch and the boundary - //double cx = (x-(nr[0]-1)/2)*hr[0]; - //double cy = (y-(nr[1]-1)/2)*hr[1]; - //double cz = hr[2]*(nr[2]-1); - //double d = sqrt(cx*cx+cy*cy+cz*cz); - double d = hr[2] * (nr[2] - 1) / 2; - //cout << cx << " " << cy << " " << cz << " " << 2/(d*hr[2]) << endl; - C += 2 / (d * hr[2]); - //C += 2/((hr[2]*(nr[2]-1)/2.0) * hr[2]); - - //scale all stencil-points in z-plane with 0.5 (Neumann discretization) - W /= 2.0; - E /= 2.0; - N /= 2.0; - S /= 2.0; - C /= 2.0; - scaleFactor *= 0.5; - } - - //simple check if center value of stencil is positive -#ifdef DEBUG - if(C <= 0) - throw OpalException("RectangularDomain::getBoundaryStencil", - "Stencil C is <= 0! This case should never occure!"); -#endif + if (z == nr[2] - 1) + B = 0.0; } -void RectangularDomain::getBoundaryStencil(int idx, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor) { - +void RectangularDomain::getBoundaryStencil(int idx, double &W, double &E, + double &S, double &N, double &F, + double &B, double &C, double &scaleFactor) +{ int x = 0, y = 0, z = 0; getCoord(idx, x, y, z); @@ -141,8 +103,9 @@ void RectangularDomain::getBoundaryStencil(int idx, double &W, double &E, double } -void RectangularDomain::getNeighbours(int idx, double &W, double &E, double &S, double &N, double &F, double &B) { - +void RectangularDomain::getNeighbours(int idx, int &W, int &E, int &S, + int &N, int &F, int &B) +{ int x = 0, y = 0, z = 0; getCoord(idx, x, y, z); @@ -150,622 +113,52 @@ void RectangularDomain::getNeighbours(int idx, double &W, double &E, double &S, } -void RectangularDomain::getNeighbours(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B) { - - if(x > 0) +void RectangularDomain::getNeighbours(int x, int y, int z, int &W, int &E, + int &S, int &N, int &F, int &B) +{ + if (x > 0) W = getIdx(x - 1, y, z); else W = -1; - if(x < nr[0] - 1) + if (x < nr[0] - 1) E = getIdx(x + 1, y, z); else E = -1; - if(y < nr[1] - 1) + if (y < nr[1] - 1) N = getIdx(x, y + 1, z); else N = -1; - if(y > 0) + if (y > 0) S = getIdx(x, y - 1, z); else S = -1; - if(z > 0) + if (z > 0) F = getIdx(x, y, z - 1); else F = -1; - if(z < nr[2] - 1) + if (z < nr[2] - 1) B = getIdx(x, y, z + 1); else B = -1; } -/* -void MGPoissonSolver::getNeighbours(const int idx, int& W, int& E, int& S, int& N, int& F, int& B, int& numOutOfDomain) -{ - - int ixy, iz, iy, ix; - int nx = nr_m[0]; - int ny = nr_m[1]; - int nz = nr_m[2]; - int nxy = nx*ny; - ixy = idx % nxy; - - ix = ixy % nx; - iy = (ixy - ix) / nx; - iz = (idx - ixy) / nxy; - numOutOfDomain = 0; - - if (iz == 0) - {F = -1; numOutOfDomain++;} - else - F = idx - nxy; - if (iz == nz - 1) - {B = -1; numOutOfDomain++;} - else - B = idx + nxy; - - if (ix == 0) - {W = -1; numOutOfDomain++;} - else - W = ixy - 1; - if (ix == nx - 1) - {E = -1; numOutOfDomain++;} - else - E = ixy + 1; - - if (iy == 0) - {S = -1; numOutOfDomain++;} - else - S = ixy - nx; - if (iy == ny - 1) - {N = -1; numOutOfDomain++;} - else - N = ixy + nx; - - int cor = iz * nxy; - switch(W) { - case -1: break; - default: W += cor; - } - switch(E) { - case -1: break; - default: E += cor; - } - switch(S) { - case -1: break; - default: S += cor; - } - switch(N) { - case -1: break; - default: N += cor; - } - -} - -//at the moment this stencil has neumann everywhere except on the z=0 plane (Dirichlet) -//this code is experimental/not-optimized/not-final at the moment -inline Epetra_CrsMatrix* MGPoissonSolver::stencil3DOneSidedDirichlet(Vector_t hr) +void RectangularDomain::resizeMesh(Vector_t& origin, Vector_t& hr, const Vector_t& rmin, + const Vector_t& rmax, double dh) { - Epetra_CrsMatrix* Matrix = new Epetra_CrsMatrix(Copy, *Map, 7); - - Vector_t hr2 = hr*hr; - double a = 2*(1/hr2[0]+1/hr2[1]+1/hr2[2]); - double b = -1/hr2[0]; - double d = -1/hr2[1]; - double f = -1/hr2[2]; - - int NumMyElements = Map->NumMyElements(); - int* MyGlobalElements = Map->MyGlobalElements(); - - int W, E, S, N, F, B, numout; - std::vector<double> Values(6); - std::vector<int> Indices(6); - - for (int i = 0 ; i < NumMyElements ; ++i) - { - getNeighbours(MyGlobalElements[i], W, E, S, N, F, B, numout); - - int NumEntries = 0; - double diag = a; - - if(F != -1) { - - switch(numout) { - - case 3: { - if(W == -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.25*b; - } - - if(E == -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.25*b; - } - - if(N == -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.25*d; - } - - if(S == -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.25*d; - } - - if(B == -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = 0.25*f; - } - - if(F == -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = 0.25*f; - } - - diag *= 0.125; - - if(NumEntries != 3) - cout << "ERROR: while calc corners in stencil" << endl; - - break; - - } - case 2: { - - if(W != -1 && E != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.25*b; - Indices[NumEntries] = E; - Values[NumEntries++] = 0.25*b; - } - if(E == -1 && W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - } - if(W == -1 && E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - - - if(N != -1 && S != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.25*d; - Indices[NumEntries] = S; - Values[NumEntries++] = 0.25*d; - } - if(S == -1 && N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - if(N == -1 && S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - - - if(B != -1 && F != -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = 0.25*f; - Indices[NumEntries] = F; - Values[NumEntries++] = 0.25*f; - } - if(B == -1 && F != -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = 0.5*f; - } - if(F == -1 && B != -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = 0.5*f; - } - - diag *= 0.25; - - if(NumEntries != 4) - cout << "ERROR: while calc edge stencil elements" << endl; - - break; - } - case 1: { - - - if(W != -1 && E != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - if(E == -1 && W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = b; - } - if(W == -1 && E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = b; - } - - - if(N != -1 && S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - if(S == -1 && N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = d; - } - if(N == -1 && S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = d; - } - - - if(B != -1 && F != -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = 0.5*f; - Indices[NumEntries] = B; - Values[NumEntries++] = 0.5*f; - } - if(B == -1 && F != -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } - if(F == -1 && B != -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } - - diag *= 0.5; - - if(NumEntries != 5) - cout << "ERROR: calc surface elements of stencil" << endl; - - break; - } - - case 0: { - if(W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = b; - } if(E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = b; - } if(S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = d; - } if(N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = d; - } if(F != -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } if(B != -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } - - break; - } - default: { - cout << "ERROR CREATING THE STENCIL: points out of domain (" << numout << ") is >3 OR <0" << endl; - } - } - } else { - //F == -1 --> this is our dirichlet boundary surface - switch(numout) { - case 3: { - - if(W == -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - - if(E == -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - } - - if(N == -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - - if(S == -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - - Indices[NumEntries] = B; - Values[NumEntries++] = 0.25*f; - - if(NumEntries != 3) - cout << "ERROR: calc corner (below) elements of stencil" << endl; - - diag *= 0.25; - break; - - } - case 2:{ - - if(W != -1 && E != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - if(W == -1 && E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = b; - } - - if(E == -1 && W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = b; - } - - if(N != -1 && S != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - if(N == -1 && S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = d; - } - - if(S == -1 && N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = d; - } - - Indices[NumEntries] = B; - Values[NumEntries++] = 0.25*f; - - if(NumEntries != 4) - cout << "ERROR: calc edge (below) elements of stencil" << endl; - - diag *= 0.25; - break; - - } - case 1:{ - - Indices[NumEntries] = E; - Values[NumEntries++] = b; - - Indices[NumEntries] = W; - Values[NumEntries++] = b; - - Indices[NumEntries] = S; - Values[NumEntries++] = d; - - Indices[NumEntries] = N; - Values[NumEntries++] = d; - - Indices[NumEntries] = B; - Values[NumEntries++] = f; - - if(NumEntries != 5) - cout << "ERROR: calc surface (below) elements of stencil: " << NumEntries << endl; - - break; - - } - default: { - cout << "error in dirichlet surface!" << endl; - } - } - } - // put the off-diagonal entries - Matrix->InsertGlobalValues(MyGlobalElements[i], NumEntries, - &Values[0], &Indices[0]); - - // Put in the diagonal entry - Matrix->InsertGlobalValues(MyGlobalElements[i], 1, - &diag, MyGlobalElements + i); - - } - Matrix->FillComplete(); - Matrix->OptimizeStorage(); - - return(Matrix); -} - -//stencil for longitudinal neumann and transversal dirichlet BC -//this code is experimental/not-optimized/not-final at the moment -inline Epetra_CrsMatrix* MGPoissonSolver::stencil3DLongitudinalNeumann(Vector_t hr) -{ - Epetra_CrsMatrix* Matrix = new Epetra_CrsMatrix(Copy, *Map, 7); - - Vector_t hr2 = hr*hr; - double a = 2*(1/hr2[0]+1/hr2[1]+1/hr2[2]); - double b = -1/hr2[0]; - double d = -1/hr2[1]; - double f = -1/hr2[2]; - - int NumMyElements = Map->NumMyElements(); - int* MyGlobalElements = Map->MyGlobalElements(); - - int W, E, S, N, F, B, numout; - std::vector<double> Values(6); - std::vector<int> Indices(6); - - for (int i = 0 ; i < NumMyElements ; ++i) - { - getNeighbours(MyGlobalElements[i], W, E, S, N, F, B, numout); - - int NumEntries = 0; - double diag = a; - //numout = 0; - - //transversal direction: if below == -1 || above == -1 ===> NEUMANN - //else dirichlet: - if(F != -1 && B != -1) - numout = 0; - - //only on left longitudinal end open bc -- else dirichlet - //if(F != -1) - // numout = 0; - - switch(numout) { - - case 3: { - if(W == -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - - if(E == -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - } - - if(N == -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - - if(S == -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - - if(B == -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } - - if(F == -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } - - diag *= 0.5; - - if(NumEntries != 3) - cout << "ERROR: while calc corners in stencil" << endl; - - break; - - } - case 2: { //edges - - if(E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - if(W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - } - - if(S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - if(N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - - if(B == -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } - if(F == -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } - - diag *= 0.5; - - if(NumEntries != 4) - cout << "ERROR: while calc edge stencil elements" << endl; - - break; - } - case 1: { - - if(E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = 0.5*b; - } - if(W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = 0.5*b; - } - - if(S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = 0.5*d; - } - if(N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = 0.5*d; - } - - if(B == -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } - if(F == -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } - - diag *= 0.5; - - if(NumEntries != 5) - cout << "ERROR: calc surface elements of stencil" << endl; - - break; - } - - case 0: { //interior points (& dirichlet) - if(W != -1) { - Indices[NumEntries] = W; - Values[NumEntries++] = b; - } if(E != -1) { - Indices[NumEntries] = E; - Values[NumEntries++] = b; - } if(S != -1) { - Indices[NumEntries] = S; - Values[NumEntries++] = d; - } if(N != -1) { - Indices[NumEntries] = N; - Values[NumEntries++] = d; - } if(F != -1) { - Indices[NumEntries] = F; - Values[NumEntries++] = f; - } if(B != -1) { - Indices[NumEntries] = B; - Values[NumEntries++] = f; - } + // apply bounding box increment, i.e., "BBOXINCR" input argument + double zsize = rmax[2] - rmin[2]; - break; - } - default: { - cout << "ERROR CREATING THE STENCIL: points out of domain (" << numout << ") is >3 OR <0" << endl; - } - } - // put the off-diagonal entries - Matrix->InsertGlobalValues(MyGlobalElements[i], NumEntries, - &Values[0], &Indices[0]); + setMinMaxZ(rmin[2] - zsize * (1.0 + dh), + rmax[2] + zsize * (1.0 + dh)); - // Put in the diagonal entry - Matrix->InsertGlobalValues(MyGlobalElements[i], 1, - &diag, MyGlobalElements + i); + origin = Vector_t(-a_m, -b_m, getMinZ()); - } - Matrix->FillComplete(); - Matrix->OptimizeStorage(); + Vector_t mymax = Vector_t(a_m, b_m, getMaxZ()); - return(Matrix); + for (int i = 0; i < 3; ++i) + hr[i] = (mymax[i] - origin[i]) / nr[i]; } -*/ #endif //#ifdef HAVE_SAAMG_SOLVER \ No newline at end of file diff --git a/src/Solvers/RectangularDomain.h b/src/Solvers/RectangularDomain.h index 03c8d9eba81de79d503efd509a566c732e403837..2fd853b92cbd9fea262331bad85798da961fdf92 100644 --- a/src/Solvers/RectangularDomain.h +++ b/src/Solvers/RectangularDomain.h @@ -1,6 +1,7 @@ // // Class RectangularDomain -// :FIXME: add brief description +// This class provides a rectangular beam pipe. The mesh adapts to the bunch +// in longitudinal direction. // // Copyright (c) 2008, Yves Ineichen, ETH Zürich, // 2013 - 2015, Tülin Kaman, Paul Scherrer Institut, Villigen PSI, Switzerland @@ -36,44 +37,64 @@ public: /// constructor RectangularDomain(Vector_t nr, Vector_t hr); + /// constructor RectangularDomain(double a, double b, Vector_t nr, Vector_t hr); /// calculates intersection with the beam pipe void compute(Vector_t hr); + void compute(Vector_t hr, NDIndex<3> /*localId*/); + /// returns number of nodes in xy plane (here independent of z coordinate) int getNumXY(int z); + /// 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, double &W, double &E, + double &S, double &N, double &F, double &B, + double &C, double &scaleFactor); + /// returns discretization at 3D index - void getBoundaryStencil(int idx, double &W, double &E, double &S, double &N, double &F, double &B, double &C, double &scaleFactor); + void getBoundaryStencil(int idx, double &W, double &E, double &S, + double &N, double &F, double &B, double &C, + double &scaleFactor); + /// returns index of neighbours at (x,y,z) using IrregularDomain::getNeighbours; - void getNeighbours(int x, int y, int z, double &W, double &E, double &S, double &N, double &F, double &B); + + void getNeighbours(int x, int y, int z, int &W, int &E, + int &S, int &N, int &F, int &B); + /// returns index of neighbours at 3D index - void getNeighbours(int idx, double &W, double &E, double &S, double &N, double &F, double &B); + void getNeighbours(int idx, int &W, int &E, int &S, + int &N, int &F, int &B); + + bool hasGeometryChanged() { return false; } + + void resizeMesh(Vector_t& origin, Vector_t& hr, const Vector_t& rmin, + const Vector_t& rmax, double dh); + /// returns type of boundary condition std::string getType() {return "Rectangular";} + /// queries if a given (x,y,z) coordinate lies inside the domain inline bool isInside(int x, int y, int /*z*/) { - double xx = (x - (nr[0] - 1) / 2.0) * hr[0]; - double yy = (y - (nr[1] - 1) / 2.0) * hr[1]; - return (xx <= a_m && yy < b_m); + double xx = std::abs(-a_m + hr[0] * (x + 0.5)); + double yy = std::abs(-b_m + hr[1] * (y + 0.5)); + return (xx < a_m && yy < b_m); } void setB_m(double b) {b_m = b;} void setA_m(double a) {a_m = a;} double getXRangeMin() { return -a_m; } - double getXRangeMax() { return a_m; } + double getXRangeMax() { return a_m; } double getYRangeMin() { return -b_m; } - double getYRangeMax() { return b_m; } + double getYRangeMax() { return b_m; } double getZRangeMin() { return getMinZ(); } double getZRangeMax() { return getMaxZ(); } - int getStartIdx() {return 0;} private: @@ -86,7 +107,7 @@ private: /// conversion from (x,y,z) to index on the 3D grid inline int getIdx(int x, int y, int z) { - if(isInside(x, y, z) && x >= 0 && y >= 0 && z >= 0) + if (isInside(x, y, z) && x >= 0 && y >= 0 && z >= 0) return y * nr[0] + x + z * nxy_m; else return -1; diff --git a/src/Structure/BoundaryGeometry.cpp b/src/Structure/BoundaryGeometry.cpp index 745575119412a94e83f862502a549ceef2cf49ce..8c59c6e2f421c9324cd40fade1e929e72de321ef 100644 --- a/src/Structure/BoundaryGeometry.cpp +++ b/src/Structure/BoundaryGeometry.cpp @@ -721,7 +721,7 @@ BoundaryGeometry::BoundaryGeometry() : itsAttr[TOPO] = Attributes::makeString ("TOPO", - "BOX, BOXCORNER, ELLIPTIC if FGEOM is selected topo is over-written ", + "RECTANGULAR, BOXCORNER, ELLIPTIC if FGEOM is selected topo is over-written ", "ELLIPTIC"); itsAttr[LENGTH] = Attributes::makeReal diff --git a/src/Structure/BoundaryGeometry.h b/src/Structure/BoundaryGeometry.h index 081863ab6bd83ed0e7bf50ca40caf62a2e804cac..549b2e45ea0754c3632409bcff13b73dbc0878bb 100644 --- a/src/Structure/BoundaryGeometry.h +++ b/src/Structure/BoundaryGeometry.h @@ -317,7 +317,7 @@ private: A, // major semi-axis of elliptic tube B, // minor semi-axis of ellitpic tube C, // in case of BOXCORNER hight of corner - TOPO, // BOX, BOXCORNER, ELLIPTIC if FGEOM is selected topo is over-written + TOPO, // RECTANGULAR, BOXCORNER, ELLIPTIC if FGEOM is selected topo is over-written ZSHIFT, // Shift in z direction XYZSCALE, // Multiplicative scaling factor for coordinates XSCALE, // Multiplicative scaling factor for x-coordinates