54 "Export data in wall-normal direction from a single point on the "
60 f->m_writeBndFld =
false;
64 "The point to be projected onto the wall to get the \
65 sampling origin. default=[0.5,0,0]");
68 "The direction to project the point onto the wall to \
69 get the sampling origin. default=[0,1,0]");
71 false,
"1.0",
"Distance to limit projection distance to find the \
72 desired sampling origin. defalut=1.0");
74 false,
"0.01",
"Sampling distance along the wall normal at the \
75 sampling origin. default=0.1");
77 false,
"5",
"Number of sampling points along the wall normal. \
80 false,
"0.1",
"The parameter that controls the sampling points' \
81 distribution. d should be in the range (0,inf). d \
82 in (0,0.95] gives controled points; d in (0.95,inf) \
83 gives evenly spaced points");
122 const int nfields =
m_f->m_variables.size();
123 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
124 const int nBndLcoordDim = nCoordDim - 1;
129 std::vector<NekDouble> xorig, searchDir;
131 "Failed to interpret origin coordinates string");
134 "Failed to interpret search direction string");
137 const int nptsH =
m_config[
"nptsH"].as<
int>();
141 for (
int i = 0; i < 3; ++i)
143 orig[i] = (xorig.size() >= (i + 1)) ? xorig[i] : 0.0;
144 projDir[i] = (searchDir.size() >= (i + 1)) ? searchDir[i] : 0.0;
154 if (
m_f->m_numHomogeneousDir == 1)
156 int nPlanes =
m_f->m_exp[0]->GetHomogeneousBasis()->GetZ().size();
158 if (orig[2] < 0.0 || orig[2] > lHom)
165 NekDouble zTmp, zCur = 0.0, distTmp, distCur = 999.0;
166 for (
int i = 0; i <= nPlanes; ++i)
169 distTmp = fabs(orig[2] - zTmp);
170 if (distTmp < distCur)
186 m_f->m_exp[0]->GetGraph());
189 map<int, int> BndRegionMap;
191 for (
auto &breg_it : bregions)
193 BndRegionMap[breg_it.first] = cnt++;
195 int bnd = BndRegionMap[
m_f->m_bndRegionsToWrite[0]];
199 for (
int i = 0; i < nfields; ++i)
201 BndExp[i] =
m_f->m_exp[i]->UpdateBndCondExpansion(bnd);
210 bool isInside =
false;
213 const int nElmts = BndExp[0]->GetNumElmts();
214 for (elmtid = 0; elmtid < nElmts; ++elmtid)
216 bndGeom = BndExp[0]->GetExp(elmtid)->GetGeom();
224 ASSERTL0(isInside,
"Failed to find the sampling origin on the boundary.");
228 const int npts = bndXmap->GetTotPoints();
232 for (
int i = 0; i < nCoordDim; ++i)
235 bndCoeffs[i] = bndGeom->GetCoeffs(i);
236 bndXmap->BwdTrans(bndCoeffs[i], pts[i]);
237 orig[i] = bndXmap->PhysEvaluate(locCoord, pts[i]);
243 m_f->m_exp[0]->GetBoundaryNormals(bnd, normalsQ);
248 int from_nPtsPerElmt = 1;
249 for (
int i = 0; i < nBndLcoordDim; ++i)
251 from_key[i] = BndExp[0]->GetExp(elmtid)->GetBasis(i)->GetPointsKey();
252 from_nPtsPerElmt *= from_key[i].GetNumPoints();
257 int refId = elmtid * from_nPtsPerElmt + 0;
260 normalsRef[i] = normalsQ[i][refId];
275 cout <<
"------ wallNormalData module ------\n";
276 cout <<
"Input point:\n";
277 cout <<
" - [Px,Py,Pz] = [" << xorig[0] <<
", " << xorig[1];
278 if (xorig.size() >= 3)
280 cout <<
", " << xorig[2] <<
"]\n";
284 cout <<
", " << 0.0 <<
"]\n";
286 cout <<
"Projection direction:\n";
287 cout <<
" - [vx,vy,vz] = [" << projDir[0] <<
", " << projDir[1] <<
", "
288 << projDir[2] <<
"]\n";
289 cout <<
"Sampling origin on the wall:\n";
290 cout <<
" - [Ox,Oy,Oz] = [" << orig[0] <<
", " << orig[1] <<
", "
292 cout <<
"Normals at the origin:\n";
293 cout <<
" - [nx,ny,nz] = [" << normals[0] <<
", " << normals[1] <<
", "
294 << normals[2] <<
"]\n";
296 <<
"Ref normals (at quadrature points in the projected element):\n";
297 for (
int i = 0; i < from_nPtsPerElmt; ++i)
299 cout <<
" - " << i <<
": [nx,ny,nz] = ["
300 << -normalsQ[0][elmtid * from_nPtsPerElmt + i] <<
", "
301 << -normalsQ[1][elmtid * from_nPtsPerElmt + i];
304 cout <<
", " << -normalsQ[2][elmtid * from_nPtsPerElmt + i]
318 if (delta > 0 && delta <= 0.95)
327 for (
int i = 1; i < nptsH; ++i)
329 tmp1 = 1.0 - i * tmp2;
330 h[i] = 1 - tanh(tmp1 * tmp4) * tmp5;
334 else if (delta > 0.95)
338 for (
int i = 1; i < nptsH; ++i)
346 ASSERTL0(
false,
"Input error. Delta needs to be greater than 0.0.");
351 for (
int i = 0; i < totVars; ++i)
358 for (
int j = 0; j < nptsH; ++j)
360 ptsH[i][j] = orig[i] + h[j] * normals[i];
388 tmp1 =
Vmath::Dot(3, gloCoord, 1, projDir, 1);
389 Vmath::Smul(3, distToOrig - tmp1, projDir, 1, tmp2,
391 Vmath::Vadd(3, gloCoord, 1, tmp2, 1, projGloCoord, 1);
407 const int nCoordDim = pts.size();
408 const int npts = pts[0].size();
413 for (
int i = 0; i < npts; ++i)
416 for (
int j = 0; j < nCoordDim; ++j)
418 singlePnt[j] = pts[j][i];
422 tmp1 =
Vmath::Dot(nCoordDim, singlePnt, 1, projDir, 1);
423 Vmath::Smul(nCoordDim, distToOrig - tmp1, projDir, 1, tmp2, 1);
424 Vmath::Vadd(nCoordDim, singlePnt, 1, tmp2, 1, singlePnt, 1);
427 for (
int j = 0; j < nCoordDim; ++j)
429 projPts[j][i] = singlePnt[j];
449 const NekDouble npts = projPts[0].size();
453 vec1[0] = projPts[0][0] - projGloCoord[0];
454 vec1[1] = projPts[1][0] - projGloCoord[1];
455 vec2[0] = projPts[0][npts - 1] - projGloCoord[0];
456 vec2[1] = projPts[1][npts - 1] - projGloCoord[1];
463 if ((fabs(vec1[0] + vec2[0]) + fabs(vec1[1] + vec2[1])) < paralTol)
482 const NekDouble npts = projPts[0].size();
485 const int nptsPolygon = 4 * nptsEdge - 4;
487 for (
int i = 0; i < 3; ++i)
491 for (
int j = 0; j < nptsEdge; ++j)
493 ptsPolygon[i][j] = projPts[i][j];
495 for (
int j = 0; j < nptsEdge - 2; ++j)
497 ptsPolygon[i][nptsEdge + j] = projPts[i][(j + 2) * nptsEdge - 1];
499 for (
int j = 0; j < nptsEdge; ++j)
501 ptsPolygon[i][2 * nptsEdge - 2 + j] = projPts[i][npts - 1 - j];
503 for (
int j = 0; j < nptsEdge - 2; ++j)
505 ptsPolygon[i][3 * nptsEdge - 2 + j] =
506 projPts[i][nptsEdge * (nptsEdge - j - 2)];
511 NekDouble angleCos, angleAbs, angleSign, angleSum = 0.0;
515 for (
int i = 0; i < nptsPolygon; ++i)
518 id2 = (id1 == (nptsPolygon - 1)) ? 0 : (id1 + 1);
520 for (
int j = 0; j < 3; ++j)
522 vec1[j] = ptsPolygon[j][id1] - projGloCoord[j];
523 vec2[j] = ptsPolygon[j][id2] - projGloCoord[j];
531 if ((fabs(vec1[0] + vec2[0]) + fabs(vec1[1] + vec2[1]) +
532 fabs(vec1[2] + vec2[2])) < paralTol)
542 vec3[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
543 vec3[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
544 vec3[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
547 angleSign =
Vmath::Dot(3, vec3, 1, projDir, 1) > 0.0 ? 1.0 : -1.0;
555 else if (angleCos < -1.0)
560 angleAbs = acos(angleCos);
561 angleSum += angleSign * angleAbs;
566 angleSum = fabs(angleSum);
567 if (fabs(angleSum - 2.0 * M_PI) < angleTol)
596 const NekDouble iterTol,
const int iterMax)
607 bool isConverge =
false;
608 while (cnt < iterMax)
610 tmpL = bndXmap->PhysEvaluate(etaLR, pts[dirUse[0]]);
611 tmpR = bndXmap->PhysEvaluate(etaLR + 1, pts[dirUse[0]]);
613 if (fabs(gloCoord[dirUse[0]] - tmpL) >=
614 fabs(gloCoord[dirUse[0]] - tmpR))
616 etaLR[0] = 0.5 * (etaLR[0] + etaLR[1]);
620 etaLR[1] = 0.5 * (etaLR[0] + etaLR[1]);
623 if ((etaLR[1] - etaLR[0]) < iterTol)
625 locCoord[0] = 0.5 * (etaLR[0] + etaLR[1]);
636 WARNINGL1(
false,
"Bisection iteration is not converged");
655 bndGeom->GetMetricInfo()->GetJac(bndXmap->GetPointsKeys());
658 scaledTol *= iterTol;
661 const int dir1 = dirUse[0];
662 const int dir2 = dirUse[1];
670 bndXmap->PhysDeriv(pts[dir1], Dx1D1, Dx1D2);
671 bndXmap->PhysDeriv(pts[dir2], Dx2D1, Dx2D2);
678 NekDouble derx1_1, derx1_2, derx2_1, derx2_2, jac;
681 bool isConverge =
false;
684 resid =
sqrt(F1 * F1 + F2 * F2);
685 while (cnt++ < iterMax)
687 x1map = bndXmap->PhysEvaluate(locCoord, pts[dir1]);
688 x2map = bndXmap->PhysEvaluate(locCoord, pts[dir2]);
690 F1 = gloCoord[dir1] - x1map;
691 F2 = gloCoord[dir2] - x2map;
693 if (F1 * F1 + F2 * F2 < scaledTol)
695 resid =
sqrt(F1 * F1 + F2 * F2);
701 derx1_1 = bndXmap->PhysEvaluate(locCoord, Dx1D1);
702 derx1_2 = bndXmap->PhysEvaluate(locCoord, Dx1D2);
703 derx2_1 = bndXmap->PhysEvaluate(locCoord, Dx2D1);
704 derx2_2 = bndXmap->PhysEvaluate(locCoord, Dx2D2);
706 jac = derx2_2 * derx1_1 - derx2_1 * derx1_2;
710 locCoord[0] = locCoord[0] + (derx2_2 * (gloCoord[dir1] - x1map) -
711 derx1_2 * (gloCoord[dir2] - x2map)) /
714 locCoord[1] = locCoord[1] + (-derx2_1 * (gloCoord[dir1] - x1map) +
715 derx1_1 * (gloCoord[dir2] - x2map)) /
719 if (!(std::isfinite(locCoord[0]) && std::isfinite(locCoord[1])))
722 std::ostringstream ss;
723 ss <<
"nan or inf found in NewtonIterForLocCoordOnProjBndElmt in "
725 << bndGeom->GetGlobalID();
729 if (fabs(locCoord[0]) > LcoordDiv || fabs(locCoord[1]) > LcoordDiv)
737 bndXmap->LocCoordToLocCollapsed(locCoord, eta);
739 if (bndGeom->ClampLocCoords(eta, 0.0))
742 x1map = bndXmap->PhysEvaluate(eta, pts[dir1]);
743 x2map = bndXmap->PhysEvaluate(eta, pts[dir2]);
745 F1 = gloCoord[dir1] - x1map;
746 F2 = gloCoord[dir2] - x2map;
748 dist =
sqrt(F1 * F1 + F2 * F2);
759 bndXmap->LocCoordToLocCollapsed(locCoord, collCoords);
762 if ((collCoords[0] >= -1.0 && collCoords[0] <= 1.0) &&
763 (collCoords[1] >= -1.0 && collCoords[1] <= 1.0))
765 std::ostringstream ss;
767 ss <<
"Reached MaxIterations (" << iterMax
768 <<
") in Newton iteration ";
769 ss <<
"Init value (" << setprecision(4) << 0 <<
"," << 0 <<
","
771 ss <<
"Fin value (" << locCoord[0] <<
"," << locCoord[1] <<
","
773 ss <<
"Resid = " << resid <<
" Tolerance = " <<
sqrt(scaledTol);
805 const int npts = bndXmap->GetTotPoints();
806 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
813 for (
int i = 0; i < nCoordDim; ++i)
817 bndCoeffs[i] = bndGeom->GetCoeffs(i);
818 bndXmap->BwdTrans(bndCoeffs[i], pts[i]);
831 for (
int i = 1; i < nCoordDim; ++i)
833 if (fabs(projDir[i]) > fabs(projDir[dirMaxId]))
865 else if (dirMaxId == 1)
885 bool isConverge, isDesired;
888 bndGeom, projGloCoord, projPts, dirUse, locCoord, iterTol);
891 tmp[0] = bndXmap->PhysEvaluate(locCoord, pts[0]) - gloCoord[0];
892 tmp[1] = bndXmap->PhysEvaluate(locCoord, pts[1]) - gloCoord[1];
895 isDesired = (projDist > 0.0) && (projDist < maxDist);
897 return isConverge && isDesired;
910 bool isConverge, isDesired;
914 dirUse, locCoord, dist, iterTol);
918 std::ostringstream ss;
919 ss <<
"Collapsed locCoord out of range.\n"
920 <<
"Newton iteration gives the distance: " << dist;
925 tmp[0] = bndXmap->PhysEvaluate(locCoord, pts[0]) - gloCoord[0];
926 tmp[1] = bndXmap->PhysEvaluate(locCoord, pts[1]) - gloCoord[1];
927 tmp[2] = bndXmap->PhysEvaluate(locCoord, pts[2]) - gloCoord[2];
930 isDesired = (projDist > 0.0) && (projDist < maxDist);
932 return isConverge && isDesired;
952 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
956 int npts = bndXmap->GetTotPoints();
959 for (
int i = 0; i < nCoordDim; ++i)
962 bndCoeffs[i] = bndGeom->GetCoeffs(i);
963 bndXmap->BwdTrans(bndCoeffs[i], pts[i]);
972 bndXmap->PhysDeriv(pts[0], DxD1);
973 bndXmap->PhysDeriv(pts[1], DyD1);
976 dxd1 = bndXmap->PhysEvaluate(locCoord, DxD1);
977 dyd1 = bndXmap->PhysEvaluate(locCoord, DyD1);
978 norm =
sqrt(dxd1 * dxd1 + dyd1 * dyd1);
980 normals[0] = dyd1 / norm;
981 normals[1] = -dxd1 / norm;
993 bndXmap->PhysDeriv(pts[0], DxD1, DxD2);
994 bndXmap->PhysDeriv(pts[1], DyD1, DyD2);
995 bndXmap->PhysDeriv(pts[2], DzD1, DzD2);
997 NekDouble dxd1, dyd1, dzd1, dxd2, dyd2, dzd2;
998 dxd1 = bndXmap->PhysEvaluate(locCoord, DxD1);
999 dxd2 = bndXmap->PhysEvaluate(locCoord, DxD2);
1000 dyd1 = bndXmap->PhysEvaluate(locCoord, DyD1);
1001 dyd2 = bndXmap->PhysEvaluate(locCoord, DyD2);
1002 dzd1 = bndXmap->PhysEvaluate(locCoord, DzD1);
1003 dzd2 = bndXmap->PhysEvaluate(locCoord, DzD2);
1006 n1 = dyd1 * dzd2 - dyd2 * dzd1;
1007 n2 = dzd1 * dxd2 - dzd2 * dxd1;
1008 n3 = dxd1 * dyd2 - dxd2 * dyd1;
1009 norm =
sqrt(n1 * n1 + n2 * n2 + n3 * n3);
1011 normals[0] = n1 / norm;
1012 normals[1] = n2 / norm;
1013 normals[2] = n3 / norm;
#define WARNINGL1(condition, msg)
#define ASSERTL0(condition, msg)
A class that contains algorithms for interpolation between pts fields, expansions and different meshe...
FIELD_UTILS_EXPORT void Interpolate(const T expInField, T &expOutField, NekDouble def_value=0., NekDouble tolerance=NekConstants::kFindDistanceMin)
Interpolate from an expansion to an expansion.
FieldSharedPtr m_f
Field object.
std::map< std::string, ConfigOption > m_config
List of configuration values.
void ProjectPoint(const Array< OneD, const NekDouble > &gloCoord, const Array< OneD, const NekDouble > &projDir, const NekDouble distToOrig, Array< OneD, NekDouble > &projGloCoord)
Project a single point along the given direction to a plane.
static ModuleKey className
bool BndElmtContainsPoint(SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, const NekDouble > &gloCoord, const Array< OneD, const NekDouble > &projDir, Array< OneD, NekDouble > &locCoord, NekDouble &projDist, const NekDouble maxDist=1.0, const NekDouble iterTol=1.0e-8)
Check if a point can be projected onto an oundary element in a given direction. If yes,...
bool NewtonIterForLocCoordOnBndElmt(SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, const NekDouble > &gloCoord, const Array< OneD, const Array< OneD, NekDouble > > &pts, const Array< OneD, const int > &dirUse, Array< OneD, NekDouble > &locCoord, NekDouble &dist, const NekDouble iterTol=1.0e-8, const int iterMax=51)
ProcessWallNormalData(FieldSharedPtr f)
~ProcessWallNormalData() override
bool isInProjectedArea2D(const Array< OneD, const NekDouble > &projGloCoord, const Array< OneD, const Array< OneD, NekDouble > > &projPts, const NekDouble paralTol=1.0e-12)
Determine if the projected point is inside the projected element.
bool isInProjectedArea3D(const Array< OneD, const NekDouble > &projGloCoord, const Array< OneD, const Array< OneD, NekDouble > > &projPts, const Array< OneD, const NekDouble > &projDir, const NekDouble paralTol=1.0e-12, const NekDouble angleTol=1.0e-6)
bool BisectionForLocCoordOnBndElmt(SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, const NekDouble > &gloCoord, const Array< OneD, const Array< OneD, NekDouble > > &pts, const Array< OneD, const int > &dirUse, Array< OneD, NekDouble > &locCoord, const NekDouble iterTol=1.0e-8, const int iterMax=51)
Use iteration to get the locCoord. This routine should be used after we have checked the projected po...
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
void GetNormals(SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, const NekDouble > &locCoord, Array< OneD, NekDouble > &normals)
Get the normals for a given locCoord.
void v_Process(po::variables_map &vm) override
Write mesh to output file.
void ProjectVertices(const Array< OneD, const Array< OneD, NekDouble > > &pts, const Array< OneD, const NekDouble > &projDir, const NekDouble distToOrig, Array< OneD, Array< OneD, NekDouble > > &projPts)
Project a single point along the given direction to a plane.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
const BoundaryRegionCollection & GetBoundaryRegions(void) const
std::shared_ptr< Field > FieldSharedPtr
std::pair< ModuleType, std::string > ModuleKey
ModuleFactory & GetModuleFactory()
static std::map< PtsInfo, int > NullPtsInfoMap
static const NekDouble kNekUnsetDouble
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
std::shared_ptr< Geometry > GeometrySharedPtr
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
void Neg(int n, T *x, const int incx)
Negate x = -x.
T Vsum(int n, const T *x, const int incx)
Subtract return sum(x)
T Dot(int n, const T *w, const T *x)
dot product
void Vadd(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Add vector z = x+y.
void Smul(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Scalar multiply y = alpha*x.
scalarT< T > sqrt(scalarT< T > in)
Represents a command-line configuration option.