61 "Convert the velocity components from the Cartesian coordinate into "
62 "the body-fitted coordinate.");
73 "The normal direction of the assistant plane, where \
74 the first body-fitted coordinate direction is located. \
75 The assistance plane is defined in point normal form. \
78 ConfigOption(
true,
"0",
"The flag for checking the distance vector \
79 perpendicular to the nearest element or not. It \
80 does not need to be turned on if geometry is \
81 smooth and there is no special consideration of \
82 the body-fitted coordinate system. It would be \
83 helpful to set up a desired coordinate system \
84 based on the surface with with sharp corners, \
85 such as at the presence of a step or gap. \
88 false,
"1.0e-12",
"The distance tolerence to properly find out the \
89 nearest boundary element. It works together with \
90 the CHECKANGLE option to set up the body-fitted \
91 coordinate system near the corner. \
94 true,
"1",
"The flag control whether the body-fitted coordinate \
95 system will be output. Default = true.");
122 const int nFields =
m_f->m_variables.size();
123 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
124 const int nSpaceDim = nCoordDim +
m_f->m_numHomogeneousDir;
125 const int nAddFields = nSpaceDim + 1;
134 const bool isCheckAngle =
m_config[
"checkAngle"].as<
bool>();
135 const bool isOutputBfc =
m_config[
"bfcOut"].as<
bool>();
138 vector<NekDouble> assistDir;
141 "Failed to interpret assistance direction");
144 for (
int i = 0; i < 3; ++i)
146 assistVec[i] = (assistDir.size() > i) ? assistDir[i] : 0.0;
157 ASSERTL0(
false,
"Error. The amplitude of assist vector is smaller than \
158 the geometry tolerence 1.0e-12.");
160 Vmath::Smul(3, 1.0 / norm, assistVec, 1, assistVec, 1);
165 m_f->m_exp[0]->GetGraph());
168 map<int, int> BndRegionMap;
170 for (
auto &breg_it : bregions)
172 BndRegionMap[breg_it.first] = cnt++;
174 int bnd = BndRegionMap[
m_f->m_bndRegionsToWrite[0]];
181 int npoints =
m_f->m_exp[0]->GetNpoints();
184 for (
int i = 0; i < nSpaceDim; ++i)
188 for (
int j = 0; j < nSpaceDim; ++j)
197 isCheckAngle, distTol, iterTol, dirTol,
205 for (
int i = 0; i < nSpaceDim; ++i)
214 for (
int i = 0; i < nSpaceDim; ++i)
216 for (
int j = 0; j < nSpaceDim; ++j)
218 Vmath::Vmul(npoints, vel_car[j], 1, bfcsDir[i][j], 1, vel_tmp, 1);
219 Vmath::Vadd(npoints, vel_tmp, 1, vel_bfc[i], 1, vel_bfc[i], 1);
224 m_f->m_variables.push_back(
"distanceToWall");
225 m_f->m_variables.push_back(
"u_bfc");
226 m_f->m_variables.push_back(
"v_bfc");
229 m_f->m_variables.push_back(
"w_bfc");
231 else if (nSpaceDim == 1)
233 ASSERTL0(
false,
"Velocity in 1D case is already in the body fitted \
234 coordinate. The dimension should be 2 or 3.");
239 m_f->m_exp.resize(nFields + nAddFields);
241 m_f->m_exp[nFields] =
m_f->AppendExpList(
m_f->m_numHomogeneousDir);
242 Vmath::Vcopy(npoints, distance, 1,
m_f->m_exp[nFields]->UpdatePhys(), 1);
243 m_f->m_exp[nFields]->FwdTransLocalElmt(distance,
244 m_f->m_exp[nFields]->UpdateCoeffs());
247 for (
int i = 1; i < nAddFields; ++i)
249 m_f->m_exp[nFields + i] =
m_f->AppendExpList(
m_f->m_numHomogeneousDir);
251 m_f->m_exp[nFields + i]->UpdatePhys(), 1);
252 m_f->m_exp[nFields + i]->FwdTransLocalElmt(
253 vel_bfc[i - 1],
m_f->m_exp[nFields + i]->UpdateCoeffs());
264 m_f->m_variables.push_back(
"bfc_dir0_x");
265 m_f->m_variables.push_back(
"bfc_dir0_y");
268 m_f->m_variables.push_back(
"bfc_dir0_z");
270 m_f->m_variables.push_back(
"bfc_dir1_x");
271 m_f->m_variables.push_back(
"bfc_dir1_y");
274 m_f->m_variables.push_back(
"bfc_dir1_z");
276 m_f->m_variables.push_back(
"bfc_dir2_x");
277 m_f->m_variables.push_back(
"bfc_dir2_y");
278 m_f->m_variables.push_back(
"bfc_dir2_z");
281 int nAddFields_coord = (nSpaceDim == 3) ? 9 : 4;
282 m_f->m_exp.resize(nFields + nAddFields + nAddFields_coord);
285 for (
int i = 0; i < nSpaceDim; ++i)
287 for (
int j = 0; j < nSpaceDim; ++j)
290 m_f->m_exp[nFields + nAddFields + cnt] =
291 m_f->AppendExpList(
m_f->m_numHomogeneousDir);
294 npoints, bfcsDir[i][j], 1,
295 m_f->m_exp[nFields + nAddFields + cnt]->UpdatePhys(), 1);
296 m_f->m_exp[nFields + nAddFields + cnt]->FwdTransLocalElmt(
298 m_f->m_exp[nFields + nAddFields + cnt]->UpdateCoeffs());
319 const int nCoordDim = pts.size();
323 for (
int i = 0; i < bndPts[0].size(); ++i)
327 for (
int j = 0; j < nCoordDim; ++j)
330 (bndPts[j][i] - pts[j][pId]) * (bndPts[j][i] - pts[j][pId]);
332 dist_tmp =
sqrt(dist_tmp);
374 bool isConverge =
false;
375 while (cnt < iterMax)
377 tmpLx = bndXmap->PhysEvaluate(etaLR, pts[0]);
378 tmpLy = bndXmap->PhysEvaluate(etaLR, pts[1]);
379 tmpRx = bndXmap->PhysEvaluate(etaLR + 1, pts[0]);
380 tmpRy = bndXmap->PhysEvaluate(etaLR + 1, pts[1]);
382 distL2 = (tmpLx - inGloCoord[0]) * (tmpLx - inGloCoord[0]) +
383 (tmpLy - inGloCoord[1]) * (tmpLy - inGloCoord[1]);
384 distR2 = (tmpRx - inGloCoord[0]) * (tmpRx - inGloCoord[0]) +
385 (tmpRy - inGloCoord[1]) * (tmpRy - inGloCoord[1]);
387 if (distL2 >= distR2)
389 etaLR[0] = 0.5 * (etaLR[0] + etaLR[1]);
393 etaLR[1] = 0.5 * (etaLR[0] + etaLR[1]);
396 if ((etaLR[1] - etaLR[0]) < iterTol)
398 locCoord[0] = 0.5 * (etaLR[0] + etaLR[1]);
399 gloCoord[0] = 0.5 * (tmpLx + tmpRx);
400 gloCoord[1] = 0.5 * (tmpLy + tmpRy);
401 dist =
sqrt(0.5 * (distL2 + distR2));
412 WARNINGL1(
false,
"Bisection iteration is not converged");
436 bool isConverge =
false;
437 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
440 int nBndPts = bndXmap->GetTotPoints();
444 for (
int i = 0; i < nCoordDim; ++i)
447 bndCoeffs[i] = bndGeom->GetCoeffs(i);
448 bndXmap->BwdTrans(bndCoeffs[i], bndPts[i]);
456 inGloCoord, bndGeom, bndPts, locCoord, gloCoord, dist, iterTol,
462 ASSERTL0(
false,
"Not available at the moment.");
476 vec3[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
477 vec3[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
478 vec3[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
482 1.0 /
sqrt(vec3[0] * vec3[0] + vec3[1] * vec3[1] + vec3[2] * vec3[2]);
484 vec3[0] = vec3[0] * coef;
485 vec3[1] = vec3[1] * coef;
486 vec3[2] = vec3[2] * coef;
514 const int nFields =
m_f->m_variables.size();
515 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
516 const int nSpaceDim = nCoordDim +
m_f->m_numHomogeneousDir;
517 const int nBndLcoordDim = nCoordDim - 1;
521 for (
int i = 0; i < nFields; ++i)
523 BndExp[i] =
m_f->m_exp[i]->UpdateBndCondExpansion(targetBndId);
526 const int nElmts =
m_f->m_exp[0]->GetNumElmts();
527 const int nBndElmts = BndExp[0]->GetNumElmts();
531 m_f->m_exp[0]->GetBoundaryNormals(targetBndId, normalQ);
542 vector<int> bndElmtIds;
543 int bndElmtId, bndElmtId_bak;
544 int phys_offset, bnd_phys_offset;
564 for (
int eId = 0; eId < nElmts; ++eId)
567 nPts =
m_f->m_exp[0]->GetExp(eId)->GetTotPoints();
569 for (
int i = 0; i < nCoordDim; ++i)
576 m_f->m_exp[0]->GetExp(eId)->GetCoords(pts[0], pts[1]);
578 else if (nCoordDim == 3)
580 m_f->m_exp[0]->GetExp(eId)->GetCoords(pts[0], pts[1], pts[2]);
584 phys_offset =
m_f->m_exp[0]->GetPhys_Offset(eId);
587 for (
int pId = 0; pId < nPts; ++pId)
601 for (
int beId = 0; beId < nBndElmts; ++beId)
604 bndGeom = BndExp[0]->GetExp(beId)->GetGeom();
605 bndXmap = bndGeom->GetXmap();
606 nBndPts = bndXmap->GetTotPoints();
608 for (
int i = 0; i < nCoordDim; ++i)
611 bndCoeffs[i] = bndGeom->GetCoeffs(i);
612 bndXmap->BwdTrans(bndCoeffs[i], bndPts[i]);
618 if ((dist_tmp < (distance[phys_offset + pId] - geoTol)) &&
619 (dist_tmp < (distance[phys_offset + pId] - distTol)))
623 distance[phys_offset + pId] = dist_tmp;
625 bndElmtIds.push_back(beId);
627 else if ((dist_tmp < (distance[phys_offset + pId] + geoTol)) ||
628 (dist_tmp < (distance[phys_offset + pId] + distTol)))
633 bndElmtIds.push_back(beId);
645 for (
int i = 0; i < nCoordDim; ++i)
647 inGloCoord[i] = pts[i][pId];
652 distance[phys_offset + pId] = 9999;
658 for (
int i = 0; i < bndElmtIds.size(); ++i)
662 bndGeom = BndExp[0]->GetExp(bndElmtIds[i])->GetGeom();
665 inGloCoord, bndGeom, locCoord_tmp, gloCoord_tmp, dist_tmp,
670 WARNINGL1(
false,
"Bisection iteration is not converged!!!");
678 if (isCheckAngle && (dist_tmp > geoTol))
683 Vmath::Vadd(nCoordDim, inGloCoord, 1, normalChk, 1,
688 normalChk, 1, normalChk, 1);
691 wnd.
GetNormals(bndGeom, locCoord_tmp, normal);
694 bnd_phys_offset = BndExp[0]->GetPhys_Offset(bndElmtIds[i]);
695 for (
int j = 0; j < nCoordDim; ++j)
697 normalRef[j] = normalQ[j][bnd_phys_offset];
700 if (
Vmath::Dot(nCoordDim, normal, normalRef) > 0.0)
706 if (
Vmath::Dot(nCoordDim, normalChk, 1, normal, 1) <
711 if (dist_tmp < dist_bak)
713 bndElmtId_bak = bndElmtIds[i];
716 for (
int j = 0; j < nBndLcoordDim; ++j)
718 locCoord_bak[j] = locCoord_tmp[j];
721 for (
int j = 0; j < 3; ++j)
723 gloCoord_bak[j] = gloCoord_tmp[j];
735 if (dist_tmp < distance[phys_offset + pId])
737 bndElmtId = bndElmtIds[i];
738 distance[phys_offset + pId] = dist_tmp;
740 for (
int j = 0; j < nBndLcoordDim; ++j)
742 locCoord[j] = locCoord_tmp[j];
745 for (
int j = 0; j < 3; ++j)
747 gloCoord[j] = gloCoord_tmp[j];
755 if (bndElmtIds.size() == 0)
757 ASSERTL0(
false,
"No boundary element is found to be the \
758 possible nearest element. Please check.");
761 distance[phys_offset + pId] = dist_bak;
762 bndElmtId = bndElmtId_bak;
764 for (
int i = 0; i < nBndLcoordDim; ++i)
766 locCoord[i] = locCoord_bak[i];
769 for (
int i = 0; i < 3; ++i)
771 gloCoord[i] = gloCoord_bak[i];
775 "The boundary element is not found under given \
776 tolerence. Please check and reset the \
777 tolerence, or just turn off the angle check. \
778 If you would like to continue, the nearest \
779 boundary element is used.");
783 bndGeom = BndExp[0]->GetExp(bndElmtId)->GetGeom();
787 bnd_phys_offset = BndExp[0]->GetPhys_Offset(bndElmtId);
788 for (
int i = 0; i < nCoordDim; ++i)
790 normalRef[i] = normalQ[i][bnd_phys_offset];
794 if (
Vmath::Dot(nCoordDim, normal, normalRef) > 0.0)
812 for (
int i = 0; i < nSpaceDim; ++i)
814 bfcsDir[0][i][phys_offset + pId] = tangential1[i];
815 bfcsDir[1][i][phys_offset + pId] = normal[i];
821 for (
int i = 0; i < 3; ++i)
823 bfcsDir[2][i][phys_offset + pId] = tangential2[i];
840 int spacedim =
m_f->m_exp[0]->GetCoordim(0) +
m_f->m_numHomogeneousDir;
841 int nfields =
m_f->m_variables.size();
842 int npoints =
m_f->m_exp[0]->GetNpoints();
846 vector<string> vars =
m_f->m_exp[0]->GetSession()->GetVariables();
847 if (boost::iequals(vars[0],
"rho") && boost::iequals(vars[1],
"rhou"))
849 var_offset = spacedim + 2;
857 if (
m_f->m_fieldMetaDataMap.count(
"MappingCartesianVel"))
859 if (
m_f->m_fieldMetaDataMap[
"MappingCartesianVel"] ==
"False")
862 for (
int i = 0; i < spacedim; ++i)
865 if (
m_f->m_exp[0]->GetWaveSpace())
867 m_f->m_exp[0]->HomogeneousBwdTrans(
868 npoints,
m_f->m_exp[var_offset + i]->GetPhys(), vel[i]);
877 mapping->ContravarToCartesian(vel, vel);
879 if (
m_f->m_exp[0]->GetWaveSpace())
881 for (
int i = 0; i < spacedim; ++i)
883 m_f->m_exp[0]->HomogeneousFwdTrans(npoints, vel[i], vel[i]);
889 for (
int i = 0; i < spacedim; ++i)
899 for (
int i = 0; i < spacedim && i < nfields; ++i)
#define WARNINGL1(condition, msg)
#define ASSERTL0(condition, msg)
FieldSharedPtr m_f
Field object.
std::map< std::string, ConfigOption > m_config
List of configuration values.
ProcessBodyFittedVelocity(FieldSharedPtr f)
virtual ~ProcessBodyFittedVelocity()
virtual void v_Process(po::variables_map &vm) override
Write mesh to output file.
void GenPntwiseBodyFittedCoordSys(const int targetBndId, const Array< OneD, NekDouble > assistVec, Array< OneD, NekDouble > &distance, Array< OneD, Array< OneD, Array< OneD, NekDouble > > > &bfcsDir, const bool isCheckAngle, const NekDouble distTol=1.0e-12, const NekDouble iterTol=1.0e-12, const NekDouble dirTol=1.0e-4, const NekDouble geoTol=1.0e-12)
At each quadrature point inside the domian, compute the body-fitted coordinate system with respect to...
void GetVelAndConvertToCartSys(Array< OneD, Array< OneD, NekDouble > > &vel)
Get velocity and convert to Cartesian system, if it is still in transformed system....
void ScaledCrosssProduct(const Array< OneD, NekDouble > &vec1, const Array< OneD, NekDouble > &vec2, Array< OneD, NekDouble > &vec3)
Compute the normalized cross product for two 2D vectors. vec3 = vec1 x vec2.
static ModuleKey className
bool LocCoordForNearestPntOnBndElmt_2D(const Array< OneD, const NekDouble > &inGloCoord, SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, Array< OneD, NekDouble > > &pts, Array< OneD, NekDouble > &locCoord, Array< OneD, NekDouble > &gloCoord, NekDouble &dist, const NekDouble iterTol=1.0e-12, const int iterMax=51)
Compute the local coordinate for the nearest point on the given 2D boundary element to the input poin...
static std::shared_ptr< Module > create(FieldSharedPtr f)
Creates an instance of this class.
NekDouble PntToBndElmtPntDistance(const Array< OneD, Array< OneD, NekDouble > > &pts, const int pId, const Array< OneD, Array< OneD, NekDouble > > &bndPts)
Compute the local coordinate for the nearest point on the given 2D boundary element to the input poin...
bool LocCoordForNearestPntOnBndElmt(const Array< OneD, const NekDouble > &inGloCoord, SpatialDomains::GeometrySharedPtr bndGeom, Array< OneD, NekDouble > &locCoord, Array< OneD, NekDouble > &gloCoord, NekDouble &dist, const NekDouble iterTol=1.0e-12, const int iterMax=51)
Compute the local coordinate for the nearest point on the given boundary element to the input point....
static GlobalMapping::MappingSharedPtr GetMapping(FieldSharedPtr f)
This processing module calculates the wall shear stress and adds it as an extra-field to the output f...
void GetNormals(SpatialDomains::GeometrySharedPtr bndGeom, const Array< OneD, const NekDouble > &locCoord, Array< OneD, NekDouble > &normals)
Get the normals for a given locCoord.
tKey RegisterCreatorFunction(tKey idKey, CreatorFunction classCreator, std::string pDesc="")
Register a class with the factory.
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()
GLOBAL_MAPPING_EXPORT typedef std::shared_ptr< Mapping > MappingSharedPtr
A shared pointer to a Mapping object.
std::map< int, BoundaryRegionShPtr > BoundaryRegionCollection
std::shared_ptr< Geometry > GeometrySharedPtr
std::shared_ptr< StdExpansion > StdExpansionSharedPtr
The above copyright notice and this permission notice shall be included.
void Vmul(int n, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Multiply vector z = x*y.
void Neg(int n, T *x, const int incx)
Negate x = -x.
T Dot(int n, const T *w, const T *x)
dot (vector times vector): z = w*x
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.
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
scalarT< T > sqrt(scalarT< T > in)
Represents a command-line configuration option.