16 #ifdef HAVE_SAAMG_SOLVER
34 geomCentroid_m = (minCoords_m + maxCoords_m)/2.0;
38 globalInsideP0_m =
Vector_t(0.0, 0.0, -0.13);
41 for(
int i=0; i<3; i++)
42 Geo_hr_m[i] = (maxCoords_m[i] - minCoords_m[i])/nr[i];
47 if (interpl ==
"CONSTANT")
48 interpolationMethod = CONSTANT;
49 else if(interpl ==
"LINEAR")
50 interpolationMethod = LINEAR;
51 else if(interpl ==
"QUADRATIC")
52 interpolationMethod = QUADRATIC;
55 ArbitraryDomain::~ArbitraryDomain() {
59 void ArbitraryDomain::compute(
Vector_t hr){
63 globalMeanR_m = getGlobalMeanR();
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];
70 hasGeometryChanged_m =
true;
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];
92 rotateWithQuaternion(P, localToGlobalQuaternion_m);
95 if (bgeom_m->fastIsInside(P0, P) % 2 == 0) {
98 std::tuple<int, int, int> pos(idx, idy, idz);
100 rotateZAxisWithQuaternion(dir, localToGlobalQuaternion_m);
101 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
103 rotateWithQuaternion(I, globalToLocalQuaternion_m);
104 IntersectHiZ.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[2]));
106 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
107 *
gmsg <<
"zdir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
111 if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
113 rotateWithQuaternion(I, globalToLocalQuaternion_m);
114 IntersectLoZ.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[2]));
116 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
117 *
gmsg <<
"zdir=-1 " << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
121 rotateYAxisWithQuaternion(dir, localToGlobalQuaternion_m);
122 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
124 rotateWithQuaternion(I, globalToLocalQuaternion_m);
125 IntersectHiY.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[1]));
127 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
128 *
gmsg <<
"ydir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
132 if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
134 rotateWithQuaternion(I, globalToLocalQuaternion_m);
135 IntersectLoY.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[1]));
137 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
138 *
gmsg <<
"ydir=-1" << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
142 rotateXAxisWithQuaternion(dir, localToGlobalQuaternion_m);
143 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
145 rotateWithQuaternion(I, globalToLocalQuaternion_m);
146 IntersectHiX.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[0]));
148 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
149 *
gmsg <<
"xdir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
153 if (bgeom_m->intersectRayBoundary(P, -dir, I)){
155 rotateWithQuaternion(I, globalToLocalQuaternion_m);
156 IntersectLoX.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[0]));
158 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
159 *
gmsg <<
"xdir=-1 " << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
163 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
164 *
gmsg <<
"OUTSIDE" <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
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);
194 globalMeanR_m = getGlobalMeanR();
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];
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;
208 hasGeometryChanged_m =
true;
210 IntersectLoX.clear();
211 IntersectHiX.clear();
212 IntersectLoY.clear();
213 IntersectHiY.clear();
214 IntersectLoZ.clear();
215 IntersectHiZ.clear();
225 for (
int idz = localId[2].first()-zGhostOffsetLeft; idz <= localId[2].last()+zGhostOffsetRight; idz++) {
228 P[2] = minCoords_m[2] + (idz + 0.5) * hr[2];
230 for (
int idy = localId[1].first()-yGhostOffsetLeft; idy <= localId[1].last()+yGhostOffsetRight; idy++) {
233 P[1] = minCoords_m[1] + (idy + 0.5) * hr[1];
235 for (
int idx = localId[0].first()-xGhostOffsetLeft; idx <= localId[0].last()+xGhostOffsetRight; idx++) {
238 P[0] = minCoords_m[0] + (idx + 0.5) * hr[0];
248 if (bgeom_m->fastIsInside(P0, P) % 2 == 0) {
252 IsInsideMap[toCoordIdx(idx, idy, idz)] =
true;
261 std::tuple<int, int, int> pos(idx, idy, idz);
266 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
270 IntersectHiZ.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[2]));
272 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
273 *
gmsg <<
"zdir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
277 if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
281 IntersectLoZ.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[2]));
283 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
284 *
gmsg <<
"zdir=-1 " << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
291 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
295 IntersectHiY.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[1]));
297 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
298 *
gmsg <<
"ydir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
302 if (bgeom_m->intersectRayBoundary(P, -dir, I)) {
306 IntersectLoY.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[1]));
308 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
309 *
gmsg <<
"ydir=-1" << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
316 if (bgeom_m->intersectRayBoundary(P, dir, I)) {
320 IntersectHiX.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[0]));
322 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
323 *
gmsg <<
"xdir=+1 " << dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
327 if (bgeom_m->intersectRayBoundary(P, -dir, I)){
331 IntersectLoX.insert(std::pair< std::tuple<int, int, int>,
double >(pos, I[0]));
333 #ifdef DEBUG_INTERSECT_RAY_BOUNDARY
334 *
gmsg <<
"xdir=-1 " << -dir <<
" x,y,z= " << idx <<
"," << idy <<
"," << idz <<
" P=" << P <<
" I=" << I <<
endl;
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;
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))
360 INFOMSG(
level2 <<
"* Finding number of xy points in each plane along z..." <<
endl);
365 for(
int idz = localId[2].first(); idz <= localId[2].last(); idz++) {
367 for(
int idx = 0; idx < nr[0]; idx++) {
368 for(
int idy = 0; idy < nr[1]; idy++) {
369 if(isInside(idx, idy, idz))
373 numXY[idz-localId[2].first()] = numxy;
378 MPI_Scan(&numtotal, &startIdx, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD);
379 startIdx -= numtotal;
384 int index = startIdx - numGhostNodesLeft;
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);
404 inline int ArbitraryDomain::toCoordIdx(
int idx,
int idy,
int idz) {
405 return (idz * nr[1] + idy) * nr[0] + idx;
409 int ArbitraryDomain::getIdx(
int idx,
int idy,
int idz) {
411 if(isInside(idx, idy, idz) && idx >= 0 && idy >= 0 && idz >= 0)
412 return IdxMap[toCoordIdx(idx, idy, idz)];
418 inline void ArbitraryDomain::getCoord(
int idxyz,
int &idx,
int &idy,
int &idz) {
419 int id = CoordMap[idxyz];
420 idx =
id % (int)nr[0];
422 idy =
id % (int)nr[1];
427 inline bool ArbitraryDomain::isInside(
int idx,
int idy,
int idz) {
429 return IsInsideMap[toCoordIdx(idx, idy, idz)];
488 int ArbitraryDomain::getNumXY(
int z) {
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;
496 getCoord(idxyz, idx, idy, idz);
497 getBoundaryStencil(idx, idy, idz, W, E, S, N, F, B, C, scaleFactor);
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) {
504 switch(interpolationMethod){
506 constantInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
509 linearInterpolation(idx,idy,idz,W,E,S,N,F,B,C,scaleFactor);
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) {
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]);
530 if(!isInside(idx-1,idy,idz))
532 if(!isInside(idx+1,idy,idz))
535 if(!isInside(idx,idy+1,idz))
537 if(!isInside(idx,idy-1,idz))
540 if(!isInside(idx,idy,idz-1))
542 if(!isInside(idx,idy,idz+1))
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)
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];
562 std::tuple<int, int, int> coordxyz(idx, idy, idz);
565 dx_e =
fabs(IntersectHiX.find(coordxyz)->second - cx);
567 dx_w =
fabs(IntersectLoX.find(coordxyz)->second - cx);
569 dy_n =
fabs(IntersectHiY.find(coordxyz)->second - cy);
571 dy_s =
fabs(IntersectLoY.find(coordxyz)->second - cy);
573 dz_b =
fabs(IntersectHiZ.find(coordxyz)->second - cz);
575 dz_f =
fabs(IntersectLoZ.find(coordxyz)->second - cz);
578 W = -(dz_f + dz_b) * (dy_n + dy_s) / dx_w;
582 E = -(dz_f + dz_b) * (dy_n + dy_s) / dx_e;
586 N = -(dz_f + dz_b) * (dx_w + dx_e) / dy_n;
590 S = -(dz_f + dz_b) * (dx_w + dx_e) / dy_s;
594 F = -(dx_w + dx_e) * (dy_n + dy_s) / dz_f;
598 B = -(dx_w + dx_e) * (dy_n + dy_s) / dz_b;
607 scaleFactor *= (dx_w + dx_e);
609 scaleFactor *= (dy_n + dy_s);
611 scaleFactor *= (dz_f + dz_b);
614 double m1 = dx_w * dx_e;
615 double m2 = dy_n * dy_s;
626 if(dx_w != 0 || dx_e != 0)
628 if(dy_n != 0 || dy_s != 0)
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;
636 void ArbitraryDomain::getNeighbours(
int id,
int &W,
int &E,
int &S,
int &N,
int &F,
int &B) {
638 int idx = 0, idy = 0, idz = 0;
640 getCoord(
id, idx, idy, idz);
641 getNeighbours(idx, idy, idz, W, E, S, N, F, B);
644 void ArbitraryDomain::getNeighbours(
int idx,
int idy,
int idz,
int &W,
int &E,
int &S,
int &N,
int &F,
int &B) {
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);
653 if(!isInside(idx+1,idy,idz))
656 if(!isInside(idx-1,idy,idz))
659 if(!isInside(idx,idy+1,idz))
662 if(!isInside(idx,idy-1,idz))
665 if(!isInside(idx,idy,idz-1))
668 if(!isInside(idx,idy,idz+1))
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];
680 inline void ArbitraryDomain::rotateWithQuaternion(
Vector_t & v,
Quaternion_t const quaternion) {
684 Vector_t const quaternionVectorComponent =
Vector_t(quaternion(1), quaternion(2), quaternion(3));
685 double const quaternionScalarComponent = quaternion(0);
687 v = 2.0 *
dot(quaternionVectorComponent, v) * quaternionVectorComponent
688 + (quaternionScalarComponent * quaternionScalarComponent
689 -
dot(quaternionVectorComponent, quaternionVectorComponent)) * v
690 + 2.0 * quaternionScalarComponent *
cross(quaternionVectorComponent, v);
693 inline void ArbitraryDomain::rotateXAxisWithQuaternion(
Vector_t & v,
Quaternion_t const quaternion) {
696 v(0) = (quaternion(0) * quaternion(0)
697 + quaternion(1) * quaternion(1)
698 - quaternion(2) * quaternion(2)
699 - quaternion(3) * quaternion(3));
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));
705 inline void ArbitraryDomain::rotateYAxisWithQuaternion(
Vector_t & v,
Quaternion_t const quaternion) {
708 v(0) = 2.0 * (quaternion(1) * quaternion(2) - quaternion(0) * quaternion(3));
710 v(1) = (quaternion(0) * quaternion(0)
711 - quaternion(1) * quaternion(1)
712 + quaternion(2) * quaternion(2)
713 - quaternion(3) * quaternion(3));
715 v(2) = 2.0 * (quaternion(2) * quaternion(3) + quaternion(0) * quaternion(1));
718 inline void ArbitraryDomain::rotateZAxisWithQuaternion(
Vector_t & v,
Quaternion_t const 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));
723 v(2) = (quaternion(0) * quaternion(0)
724 - quaternion(1) * quaternion(1)
725 - quaternion(2) * quaternion(2)
726 + quaternion(3) * quaternion(3));
729 #endif //#ifdef HAVE_SAAMG_SOLVER
PETE_TUTree< FnFabs, typename T::PETE_Expr_t > fabs(const PETE_Expr< T > &l)
double dot(const Vector3D &lhs, const Vector3D &rhs)
Vector dot product.
Inform & level2(Inform &inf)
Vector3D cross(const Vector3D &lhs, const Vector3D &rhs)
Vector cross product.
Vektor< double, 3 > Vector_t
Inform & endl(Inform &inf)