59 "Convert the velocity components from the Cartesian coordinate into "
60 "the body-fitted coordinate.");
71 "The normal direction of the assistant plane, where \
72 the first body-fitted coordinate direction is located. \
73 The assistance plane is defined in point normal form. \
76 ConfigOption(
true,
"0",
"The flag for checking the distance vector \
77 perpendicular to the nearest element or not. It \
78 does not need to be turned on if geometry is \
79 smooth and there is no special consideration of \
80 the body-fitted coordinate system. It would be \
81 helpful to set up a desired coordinate system \
82 based on the surface with with sharp corners, \
83 such as at the presence of a step or gap. \
86 false,
"1.0e-12",
"The distance tolerence to properly find out the \
87 nearest boundary element. It works together with \
88 the CHECKANGLE option to set up the body-fitted \
89 coordinate system near the corner. \
92 true,
"1",
"The flag control whether the body-fitted coordinate \
93 system will be output. Default = true.");
120 const int nFields =
m_f->m_variables.size();
121 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
122 const int nSpaceDim = nCoordDim +
m_f->m_numHomogeneousDir;
123 const int nAddFields = nSpaceDim + 1;
132 const bool isCheckAngle =
m_config[
"checkAngle"].as<
bool>();
133 const bool isOutputBfc =
m_config[
"bfcOut"].as<
bool>();
136 vector<NekDouble> assistDir;
139 "Failed to interpret assistance direction");
142 for (
int i = 0; i < 3; ++i)
144 assistVec[i] = (assistDir.size() > i) ? assistDir[i] : 0.0;
155 ASSERTL0(
false,
"Error. The amplitude of assist vector is smaller than \
156 the geometry tolerence 1.0e-12.");
158 Vmath::Smul(3, 1.0 / norm, assistVec, 1, assistVec, 1);
163 m_f->m_exp[0]->GetGraph());
166 map<int, int> BndRegionMap;
168 for (
auto &breg_it : bregions)
170 BndRegionMap[breg_it.first] = cnt++;
172 int bnd = BndRegionMap[
m_f->m_bndRegionsToWrite[0]];
179 int npoints =
m_f->m_exp[0]->GetNpoints();
182 for (
int i = 0; i < nSpaceDim; ++i)
186 for (
int j = 0; j < nSpaceDim; ++j)
195 isCheckAngle, distTol, iterTol, dirTol,
203 for (
int i = 0; i < nSpaceDim; ++i)
212 for (
int i = 0; i < nSpaceDim; ++i)
214 for (
int j = 0; j < nSpaceDim; ++j)
216 Vmath::Vmul(npoints, vel_car[j], 1, bfcsDir[i][j], 1, vel_tmp, 1);
217 Vmath::Vadd(npoints, vel_tmp, 1, vel_bfc[i], 1, vel_bfc[i], 1);
222 m_f->m_variables.push_back(
"distanceToWall");
223 m_f->m_variables.push_back(
"u_bfc");
224 m_f->m_variables.push_back(
"v_bfc");
227 m_f->m_variables.push_back(
"w_bfc");
229 else if (nSpaceDim == 1)
231 ASSERTL0(
false,
"Velocity in 1D case is already in the body fitted \
232 coordinate. The dimension should be 2 or 3.");
237 m_f->m_exp.resize(nFields + nAddFields);
239 m_f->m_exp[nFields] =
m_f->AppendExpList(
m_f->m_numHomogeneousDir);
240 Vmath::Vcopy(npoints, distance, 1,
m_f->m_exp[nFields]->UpdatePhys(), 1);
241 m_f->m_exp[nFields]->FwdTransLocalElmt(distance,
242 m_f->m_exp[nFields]->UpdateCoeffs());
245 for (
int i = 1; i < nAddFields; ++i)
247 m_f->m_exp[nFields + i] =
m_f->AppendExpList(
m_f->m_numHomogeneousDir);
249 m_f->m_exp[nFields + i]->UpdatePhys(), 1);
250 m_f->m_exp[nFields + i]->FwdTransLocalElmt(
251 vel_bfc[i - 1],
m_f->m_exp[nFields + i]->UpdateCoeffs());
262 m_f->m_variables.push_back(
"bfc_dir0_x");
263 m_f->m_variables.push_back(
"bfc_dir0_y");
266 m_f->m_variables.push_back(
"bfc_dir0_z");
268 m_f->m_variables.push_back(
"bfc_dir1_x");
269 m_f->m_variables.push_back(
"bfc_dir1_y");
272 m_f->m_variables.push_back(
"bfc_dir1_z");
274 m_f->m_variables.push_back(
"bfc_dir2_x");
275 m_f->m_variables.push_back(
"bfc_dir2_y");
276 m_f->m_variables.push_back(
"bfc_dir2_z");
279 int nAddFields_coord = (nSpaceDim == 3) ? 9 : 4;
280 m_f->m_exp.resize(nFields + nAddFields + nAddFields_coord);
283 for (
int i = 0; i < nSpaceDim; ++i)
285 for (
int j = 0; j < nSpaceDim; ++j)
288 m_f->m_exp[nFields + nAddFields + cnt] =
289 m_f->AppendExpList(
m_f->m_numHomogeneousDir);
292 npoints, bfcsDir[i][j], 1,
293 m_f->m_exp[nFields + nAddFields + cnt]->UpdatePhys(), 1);
294 m_f->m_exp[nFields + nAddFields + cnt]->FwdTransLocalElmt(
296 m_f->m_exp[nFields + nAddFields + cnt]->UpdateCoeffs());
317 const int nCoordDim = pts.size();
321 for (
int i = 0; i < bndPts[0].size(); ++i)
325 for (
int j = 0; j < nCoordDim; ++j)
328 (bndPts[j][i] - pts[j][pId]) * (bndPts[j][i] - pts[j][pId]);
330 dist_tmp =
sqrt(dist_tmp);
372 bool isConverge =
false;
373 while (cnt < iterMax)
375 tmpLx = bndXmap->PhysEvaluate(etaLR, pts[0]);
376 tmpLy = bndXmap->PhysEvaluate(etaLR, pts[1]);
377 tmpRx = bndXmap->PhysEvaluate(etaLR + 1, pts[0]);
378 tmpRy = bndXmap->PhysEvaluate(etaLR + 1, pts[1]);
380 distL2 = (tmpLx - inGloCoord[0]) * (tmpLx - inGloCoord[0]) +
381 (tmpLy - inGloCoord[1]) * (tmpLy - inGloCoord[1]);
382 distR2 = (tmpRx - inGloCoord[0]) * (tmpRx - inGloCoord[0]) +
383 (tmpRy - inGloCoord[1]) * (tmpRy - inGloCoord[1]);
385 if (distL2 >= distR2)
387 etaLR[0] = 0.5 * (etaLR[0] + etaLR[1]);
391 etaLR[1] = 0.5 * (etaLR[0] + etaLR[1]);
394 if ((etaLR[1] - etaLR[0]) < iterTol)
396 locCoord[0] = 0.5 * (etaLR[0] + etaLR[1]);
397 gloCoord[0] = 0.5 * (tmpLx + tmpRx);
398 gloCoord[1] = 0.5 * (tmpLy + tmpRy);
399 dist =
sqrt(0.5 * (distL2 + distR2));
410 WARNINGL1(
false,
"Bisection iteration is not converged");
434 bool isConverge =
false;
435 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
438 int nBndPts = bndXmap->GetTotPoints();
442 for (
int i = 0; i < nCoordDim; ++i)
445 bndCoeffs[i] = bndGeom->GetCoeffs(i);
446 bndXmap->BwdTrans(bndCoeffs[i], bndPts[i]);
454 inGloCoord, bndGeom, bndPts, locCoord, gloCoord, dist, iterTol,
460 ASSERTL0(
false,
"Not available at the moment.");
474 vec3[0] = vec1[1] * vec2[2] - vec1[2] * vec2[1];
475 vec3[1] = vec1[2] * vec2[0] - vec1[0] * vec2[2];
476 vec3[2] = vec1[0] * vec2[1] - vec1[1] * vec2[0];
480 1.0 /
sqrt(vec3[0] * vec3[0] + vec3[1] * vec3[1] + vec3[2] * vec3[2]);
482 vec3[0] = vec3[0] * coef;
483 vec3[1] = vec3[1] * coef;
484 vec3[2] = vec3[2] * coef;
512 const int nFields =
m_f->m_variables.size();
513 const int nCoordDim =
m_f->m_exp[0]->GetCoordim(0);
514 const int nSpaceDim = nCoordDim +
m_f->m_numHomogeneousDir;
515 const int nBndLcoordDim = nCoordDim - 1;
519 for (
int i = 0; i < nFields; ++i)
521 BndExp[i] =
m_f->m_exp[i]->UpdateBndCondExpansion(targetBndId);
524 const int nElmts =
m_f->m_exp[0]->GetNumElmts();
525 const int nBndElmts = BndExp[0]->GetNumElmts();
529 m_f->m_exp[0]->GetBoundaryNormals(targetBndId, normalQ);
540 vector<int> bndElmtIds;
541 int bndElmtId, bndElmtId_bak;
542 int phys_offset, bnd_phys_offset;
562 for (
int eId = 0; eId < nElmts; ++eId)
565 nPts =
m_f->m_exp[0]->GetExp(eId)->GetTotPoints();
567 for (
int i = 0; i < nCoordDim; ++i)
574 m_f->m_exp[0]->GetExp(eId)->GetCoords(pts[0], pts[1]);
576 else if (nCoordDim == 3)
578 m_f->m_exp[0]->GetExp(eId)->GetCoords(pts[0], pts[1], pts[2]);
582 phys_offset =
m_f->m_exp[0]->GetPhys_Offset(eId);
585 for (
int pId = 0; pId < nPts; ++pId)
599 for (
int beId = 0; beId < nBndElmts; ++beId)
602 bndGeom = BndExp[0]->GetExp(beId)->GetGeom();
603 bndXmap = bndGeom->GetXmap();
604 nBndPts = bndXmap->GetTotPoints();
606 for (
int i = 0; i < nCoordDim; ++i)
609 bndCoeffs[i] = bndGeom->GetCoeffs(i);
610 bndXmap->BwdTrans(bndCoeffs[i], bndPts[i]);
616 if ((dist_tmp < (distance[phys_offset + pId] - geoTol)) &&
617 (dist_tmp < (distance[phys_offset + pId] - distTol)))
621 distance[phys_offset + pId] = dist_tmp;
623 bndElmtIds.push_back(beId);
625 else if ((dist_tmp < (distance[phys_offset + pId] + geoTol)) ||
626 (dist_tmp < (distance[phys_offset + pId] + distTol)))
631 bndElmtIds.push_back(beId);
643 for (
int i = 0; i < nCoordDim; ++i)
645 inGloCoord[i] = pts[i][pId];
650 distance[phys_offset + pId] = 9999;
656 for (
int i = 0; i < bndElmtIds.size(); ++i)
660 bndGeom = BndExp[0]->GetExp(bndElmtIds[i])->GetGeom();
663 inGloCoord, bndGeom, locCoord_tmp, gloCoord_tmp, dist_tmp,
668 WARNINGL1(
false,
"Bisection iteration is not converged!!!");
676 if (isCheckAngle && (dist_tmp > geoTol))
681 Vmath::Vadd(nCoordDim, inGloCoord, 1, normalChk, 1,
686 normalChk, 1, normalChk, 1);
689 wnd.
GetNormals(bndGeom, locCoord_tmp, normal);
692 bnd_phys_offset = BndExp[0]->GetPhys_Offset(bndElmtIds[i]);
693 for (
int j = 0; j < nCoordDim; ++j)
695 normalRef[j] = normalQ[j][bnd_phys_offset];
698 if (
Vmath::Dot(nCoordDim, normal, normalRef) > 0.0)
704 if (
Vmath::Dot(nCoordDim, normalChk, 1, normal, 1) <
709 if (dist_tmp < dist_bak)
711 bndElmtId_bak = bndElmtIds[i];
714 for (
int j = 0; j < nBndLcoordDim; ++j)
716 locCoord_bak[j] = locCoord_tmp[j];
719 for (
int j = 0; j < 3; ++j)
721 gloCoord_bak[j] = gloCoord_tmp[j];
733 if (dist_tmp < distance[phys_offset + pId])
735 bndElmtId = bndElmtIds[i];
736 distance[phys_offset + pId] = dist_tmp;
738 for (
int j = 0; j < nBndLcoordDim; ++j)
740 locCoord[j] = locCoord_tmp[j];
743 for (
int j = 0; j < 3; ++j)
745 gloCoord[j] = gloCoord_tmp[j];
753 if (bndElmtIds.size() == 0)
755 ASSERTL0(
false,
"No boundary element is found to be the \
756 possible nearest element. Please check.");
759 distance[phys_offset + pId] = dist_bak;
760 bndElmtId = bndElmtId_bak;
762 for (
int i = 0; i < nBndLcoordDim; ++i)
764 locCoord[i] = locCoord_bak[i];
767 for (
int i = 0; i < 3; ++i)
769 gloCoord[i] = gloCoord_bak[i];
773 "The boundary element is not found under given \
774 tolerence. Please check and reset the \
775 tolerence, or just turn off the angle check. \
776 If you would like to continue, the nearest \
777 boundary element is used.");
781 bndGeom = BndExp[0]->GetExp(bndElmtId)->GetGeom();
785 bnd_phys_offset = BndExp[0]->GetPhys_Offset(bndElmtId);
786 for (
int i = 0; i < nCoordDim; ++i)
788 normalRef[i] = normalQ[i][bnd_phys_offset];
792 if (
Vmath::Dot(nCoordDim, normal, normalRef) > 0.0)
810 for (
int i = 0; i < nSpaceDim; ++i)
812 bfcsDir[0][i][phys_offset + pId] = tangential1[i];
813 bfcsDir[1][i][phys_offset + pId] = normal[i];
819 for (
int i = 0; i < 3; ++i)
821 bfcsDir[2][i][phys_offset + pId] = tangential2[i];
838 int spacedim =
m_f->m_exp[0]->GetCoordim(0) +
m_f->m_numHomogeneousDir;
839 int nfields =
m_f->m_variables.size();
840 int npoints =
m_f->m_exp[0]->GetNpoints();
844 vector<string> vars =
m_f->m_exp[0]->GetSession()->GetVariables();
845 if (boost::iequals(vars[0],
"rho") && boost::iequals(vars[1],
"rhou"))
847 var_offset = spacedim + 2;
855 if (
m_f->m_fieldMetaDataMap.count(
"MappingCartesianVel"))
857 if (
m_f->m_fieldMetaDataMap[
"MappingCartesianVel"] ==
"False")
860 for (
int i = 0; i < spacedim; ++i)
863 if (
m_f->m_exp[0]->GetWaveSpace())
865 m_f->m_exp[0]->HomogeneousBwdTrans(
866 npoints,
m_f->m_exp[var_offset + i]->GetPhys(), vel[i]);
875 mapping->ContravarToCartesian(vel, vel);
877 if (
m_f->m_exp[0]->GetWaveSpace())
879 for (
int i = 0; i < spacedim; ++i)
881 m_f->m_exp[0]->HomogeneousFwdTrans(npoints, vel[i], vel[i]);
887 for (
int i = 0; i < spacedim; ++i)
897 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)
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.
~ProcessBodyFittedVelocity() override
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
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 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.
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.