50#include <boost/format.hpp>
68 const std::weak_ptr<EquationSystem> &pEquation)
89 [[maybe_unused]]
const unsigned int &pNumForcingFields,
90 const TiXmlElement *pForce)
94 bool singleMode, halfMode;
95 m_session->MatchSolverInfo(
"ModeType",
"SingleMode", singleMode,
false);
96 m_session->MatchSolverInfo(
"ModeType",
"HalfMode", halfMode,
false);
97 if (singleMode || halfMode)
103 m_isRoot = pFields[0]->GetComm()->TreatAsRankZero();
123 for (
int i = 0; i < 3; ++i)
133 for (
int i = 0; i < 3; ++i)
145 int npoints = pFields[0]->GetNpoints();
160 auto equ =
m_equ.lock();
161 ASSERTL0(equ,
"Weak pointer to the equation system is expired");
162 auto FluidEq = std::dynamic_pointer_cast<FluidInterface>(equ);
172 std::string expression)
181 catch (
const std::runtime_error &)
190 const TiXmlElement *funcNameElmt;
192 const TiXmlElement *mssgTagSpecial =
193 pForce->FirstChildElement(
"CIRCULARCYLINDER");
200 m_body.isCircular =
false;
203 funcNameElmt = pForce->FirstChildElement(
"FRAMEVELOCITY");
206 std::string FuncName = funcNameElmt->GetText();
208 "Function '" + FuncName +
"' is not defined in the session.");
212 std::string var =
m_session->GetVariable(i);
213 if (
m_session->DefinesFunction(FuncName, var))
220 std::vector<std::string> linearDispVar = {
"X",
"Y",
"Z"};
221 std::vector<std::string> linearAcceVar = {
"A_x",
"A_y",
"A_z"};
224 if (
m_session->DefinesFunction(FuncName, linearDispVar[i]))
227 m_session->GetFunction(FuncName, linearDispVar[i]);
229 if (
m_session->DefinesFunction(FuncName, linearAcceVar[i]))
232 m_session->GetFunction(FuncName, linearAcceVar[i]);
237 std::vector<std::string> angularVar = {
"Omega_x",
"Omega_y",
"Omega_z"};
238 for (
int i = 0; i < 3; ++i)
240 std::string var = angularVar[i];
241 if (
m_session->DefinesFunction(FuncName, var))
250 std::vector<std::string> angularDispVar = {
"Theta_x",
"Theta_y",
252 std::vector<std::string> angularAccepVar = {
"DOmega_x",
"DOmega_y",
254 for (
int i = 0; i < 3; ++i)
256 if (
m_session->DefinesFunction(FuncName, angularDispVar[i]))
259 m_session->GetFunction(FuncName, angularDispVar[i]);
261 if (
m_session->DefinesFunction(FuncName, angularAccepVar[i]))
264 m_session->GetFunction(FuncName, angularAccepVar[i]);
268 for (
int i = 0; i < 2; ++i)
275 funcNameElmt = pForce->FirstChildElement(
"EXTERNALFORCE");
278 std::string FuncName = funcNameElmt->GetText();
279 if (
m_session->DefinesFunction(FuncName))
281 std::vector<std::string> forceVar = {
"Fx",
"Fy",
"Fz"};
284 std::string var = forceVar[i];
285 if (
m_session->DefinesFunction(FuncName, var))
287 m_body.extForceFunction[i] =
291 std::vector<std::string> momentVar = {
"Mx",
"My",
"Mz"};
292 for (
int i = 0; i < 3; ++i)
294 std::string var = momentVar[i];
295 if (
m_session->DefinesFunction(FuncName, var))
297 m_body.extForceFunction[i + 3] =
305 const TiXmlElement *pivotElmt = pForce->FirstChildElement(
"PIVOTPOINT");
308 std::vector<std::string> values;
309 std::string mssgStr = pivotElmt->GetText();
318 const TiXmlElement *TWSElmt =
319 pForce->FirstChildElement(
"TRAVELINGWAVESPEED");
322 std::vector<std::string> values;
323 std::string mssgStr = TWSElmt->GetText();
337 const TiXmlElement *mssgTag = pForce->FirstChildElement(
"OutputFile");
341 filename = mssgTag->GetText();
347 if (!(filename.length() >= 4 &&
348 filename.substr(filename.length() - 4) ==
".mrf"))
358 <<
"Variables = t, x, ux, ax, y, uy, ay, theta, omega, domega"
363 m_outputStream <<
"Variables = t, x, ux, ax, y, uy, ay, z, uz, az, "
364 "theta, omega, domega"
371 mssgTag = pForce->FirstChildElement(
"OutputFrequency");
374 std::vector<std::string> values;
375 std::string mssgStr = mssgTag->GetText();
379 "OutputFrequency should be greater than zero.");
385 const TiXmlElement *mssgTag;
389 for (
size_t i = 0; i < 3; ++i)
397 for (
int i = 0; i < NumDof; ++i)
401 mssgTag = pForce->FirstChildElement(
"MOTIONPRESCRIBED");
404 std::vector<std::string> values;
405 mssgStr = mssgTag->GetText();
408 "MOTIONPRESCRIBED vector should be of size " +
409 std::to_string(NumDof));
410 for (
int i = 0; i < NumDof; ++i)
430 mssgTag = pForce->FirstChildElement(
"MASS");
432 "Mass matrix is required.");
435 std::vector<std::string> values;
436 mssgStr = mssgTag->GetText();
438 ASSERTL0(values.size() == NumDof * NumDof,
439 "Mass matrix should be of size " + std::to_string(NumDof) +
440 "X" + std::to_string(NumDof));
442 for (
int i = 0; i < NumDof; ++i)
444 for (
int j = 0; j < NumDof; ++j)
453 mssgTag = pForce->FirstChildElement(
"DAMPING");
456 std::vector<std::string> values;
457 mssgStr = mssgTag->GetText();
459 ASSERTL0(values.size() == NumDof * NumDof,
460 "Damping matrix should be of size " + std::to_string(NumDof) +
461 "X" + std::to_string(NumDof));
463 for (
int i = 0; i < NumDof; ++i)
465 for (
int j = 0; j < NumDof; ++j)
474 mssgTag = pForce->FirstChildElement(
"RIGIDITY");
477 std::vector<std::string> values;
478 mssgStr = mssgTag->GetText();
480 ASSERTL0(values.size() == NumDof * NumDof,
481 "Rigidity matrix should be of size " + std::to_string(NumDof) +
482 "X" + std::to_string(NumDof));
484 for (
int i = 0; i < NumDof; ++i)
486 for (
int j = 0; j < NumDof; ++j)
497 if (
m_session->DefinesParameter(
"NewmarkBeta"))
501 if (
m_session->DefinesParameter(
"NewmarkGamma"))
503 gamma =
m_session->GetParameter(
"NewmarkGamma");
510 const NekDouble &time, std::map<int, NekDouble> &Dirs)
517 Dirs[it.first] = it.second->Evaluate(0., 0., 0., time);
519 else if (it.first == 5)
521 Dirs[
m_spacedim] = it.second->Evaluate(0., 0., 0., time);
523 else if (it.first < 9)
525 Dirs[NumDof + it.first - 6] = it.second->Evaluate(0., 0., 0., time);
527 else if (it.first == 11)
529 Dirs[NumDof +
m_spacedim] = it.second->Evaluate(0., 0., 0., time);
531 else if (it.first < 15)
533 Dirs[(NumDof << 1) + it.first - 12] =
534 it.second->Evaluate(0., 0., 0., time);
536 else if (it.first == 17)
539 it.second->Evaluate(0., 0., 0., time);
542 for (
auto i :
m_body.dirDoFs)
544 if (Dirs.find(i) == Dirs.end())
547 Dirs[i + NumDof] = 0.;
548 Dirs[i + (NumDof << 1)] = 0.;
566 std::map<int, NekDouble> Dirs;
578 for (
auto it :
m_body.extForceFunction)
580 m_body.extForceXYZ[it.first] =
581 it.second->Evaluate(0., 0., 0., time);
585 auto equ =
m_equ.lock();
586 ASSERTL0(equ,
"Weak pointer to the equation system is expired");
587 auto FluidEq = std::dynamic_pointer_cast<FluidInterface>(equ);
588 FluidEq->GetAeroForce(forcebody);
595 for (
size_t i = 0; i <
m_body.vel[0].size(); ++i)
630 disp[i] = bodyVel[0][i];
640 vel[i] = bodyVel[1][i];
641 vel[i + 6] = bodyVel[2][i];
652 auto equ =
m_equ.lock();
653 ASSERTL0(equ,
"Weak pointer to the equation system is expired");
654 auto FluidEq = std::dynamic_pointer_cast<FluidInterface>(equ);
655 FluidEq->SetMovingFrameVelocities(
vel, step);
656 FluidEq->SetMovingFrameDisp(disp, step);
663 if (!
m_body.hasFreeMotion)
685 force[i] +=
m_body.extForceXYZ[i];
693 for (
size_t i = 0; i < bodyVel.size(); ++i)
699 for (
int iter = 0; iter < 2; ++iter)
702 for (
size_t i = 0; i < bodyVel.size(); ++i)
704 Vmath::Vcopy(bodyVel[i].size(), bodyVel[i], 1, tmpbodyVel[i],
713 force[i] +=
m_body.extForceXYZ[i];
720 for (
size_t i = 0; i < bodyVel.size(); ++i)
722 Vmath::Vcopy(bodyVel[i].size(), tmpbodyVel[i], 1, bodyVel[i], 1);
743 int npoints = fields[0]->GetNpoints();
744 addRotation(npoints, outarray, -1., inarray, outarray);
756 std::map<int, NekDouble> Dirs;
759 for (
size_t i = 0; i <
m_body.vel.size(); ++i)
778 ASSERTL0(&inarray1 != &outarray,
"inarray1 and outarray "
779 "should not be the same.");
786 if (&inarray0 != &outarray)
788 ASSERTL0(inarray0.size() == outarray.size(),
789 "inarray0 and outarray must have same dimentions");
790 for (
int i = 0; i < inarray0.size(); ++i)
801 Vmath::Svtvp(nPnts, cm, inarray1[1], 1, outarray[0], 1, outarray[0], 1);
802 Vmath::Svtvp(nPnts, cp, inarray1[0], 1, outarray[1], 1, outarray[1], 1);
810 Vmath::Svtvp(nPnts, cp, inarray1[1], 1, outarray[2], 1, outarray[2], 1);
811 Vmath::Svtvp(nPnts, cm, inarray1[2], 1, outarray[1], 1, outarray[1], 1);
819 Vmath::Svtvp(nPnts, cp, inarray1[2], 1, outarray[0], 1, outarray[0], 1);
820 Vmath::Svtvp(nPnts, cm, inarray1[0], 1, outarray[2], 1, outarray[2], 1);
833 int npoints = fields[0]->GetNpoints();
834 if (
m_isH2d && fields[0]->GetWaveSpace())
843 fields[0]->HomogeneousFwdTrans(npoints, tmpphys, tmpcoef);
844 Vmath::Vadd(npoints, tmpcoef, 1, inarray[i], 1, outarray[i], 1);
846 else if (&inarray != &outarray)
854 int npoints0 = npoints;
855 if (
m_isH1d && fields[0]->GetWaveSpace())
857 npoints0 =
m_hasPlane0 ? fields[0]->GetPlane(0)->GetNpoints() : 0;
864 inarray[i], 1, outarray[i], 1);
865 if (&inarray != &outarray && npoints != npoints0)
868 Vmath::Vcopy(npoints - npoints0, inarray[i] + npoints0, 1,
872 else if (&inarray != &outarray)
887 std::map<std::string, std::string> fieldMetaDataMap;
888 std::vector<std::string> strFrameData = {
889 "X",
"Y",
"Z",
"Theta_x",
"Theta_y",
"Theta_z",
890 "U",
"V",
"W",
"Omega_x",
"Omega_y",
"Omega_z",
891 "A_x",
"A_y",
"A_z",
"DOmega_x",
"DOmega_y",
"DOmega_z"};
892 std::map<std::string, NekDouble> fileData;
893 if (
m_session->DefinesFunction(
"InitialConditions"))
895 for (
int i = 0; i <
m_session->GetVariables().size(); ++i)
897 if (
m_session->GetFunctionType(
"InitialConditions",
901 std::string filename =
m_session->GetFunctionFilename(
902 "InitialConditions",
m_session->GetVariable(i));
903 fs::path pfilename(filename);
905 if (fs::is_directory(pfilename))
907 fs::path metafile(
"Info.xml");
908 fs::path fullpath = pfilename / metafile;
913 fld->ImportFieldMetaData(filename, fieldMetaDataMap);
918 if (fieldMetaDataMap.find(
"Time") != fieldMetaDataMap.end())
920 time = std::stod(fieldMetaDataMap[
"Time"]);
923 for (
auto &var : strFrameData)
925 if (fieldMetaDataMap.find(var) !=
926 fieldMetaDataMap.end())
928 fileData[var] = std::stod(fieldMetaDataMap[var]);
931 if (fileData.size() == strFrameData.size())
939 if (
m_session->DefinesCmdLineArgument(
"set-start-time"))
942 m_session->GetCmdLineArgument<std::string>(
"set-start-time"));
944 if (fileData.size() == strFrameData.size())
946 int NumDofm1 =
m_body.vel[0].size() - 1;
949 m_body.vel[0][i] = fileData[strFrameData[i]];
950 m_body.vel[1][i] = fileData[strFrameData[i + 6]];
951 m_body.vel[2][i] = fileData[strFrameData[i + 12]];
953 m_body.vel[0][NumDofm1] = fileData[strFrameData[5]];
954 m_body.vel[1][NumDofm1] = fileData[strFrameData[11]];
955 m_body.vel[2][NumDofm1] = fileData[strFrameData[17]];
957 std::map<int, NekDouble> Dirs;
963 std::map<int, NekDouble> &Dirs)
967 int NumDof =
m_body.vel[0].size();
968 int NumDof2 = NumDof << 1;
969 if (it.first <
m_body.vel[0].size())
971 m_body.vel[1][it.first] = it.second;
973 else if (it.first < NumDof2)
975 m_body.vel[0][it.first - NumDof] = it.second;
979 m_body.vel[2][it.first - NumDof2] = it.second;
987 const TiXmlElement *pForce)
989 std::map<std::string, std::string> vParams;
990 vParams[
"OutputFile"] =
".dummyMRFForceFile";
991 const TiXmlElement *param = pForce->FirstChildElement(
"BOUNDARY");
992 ASSERTL0(param,
"Body surface should be assigned");
994 vParams[
"Boundary"] = param->GetText();
995 const TiXmlElement *pivotElmt = pForce->FirstChildElement(
"PIVOTPOINT");
998 std::string pstr = pivotElmt->GetText();
999 std::replace(pstr.begin(), pstr.end(),
',',
' ');
1000 vParams[
"MomentPoint"] = pstr;
1003 pSession,
m_equ.lock(), vParams);
1005 m_body.aeroforceFilter->Initialise(pFields, 0.0);
1012 std::set<int> DirDoFs)
1024 for (
int i = 0; i <
m_rows; ++i)
1026 if (DirDoFs.find(i) == DirDoFs.end())
1033 if (DirDoFs.find(i) != DirDoFs.end())
1055 for (
int j = 0; j <
m_rows; ++j)
1057 int ind = offset +
m_index[j];
1065 inverseMatrix->SetValue(i, j, value);
1069 inverseMatrix->Invert();
1072 for (
int j = 0; j <
m_rows; ++j)
1076 m_Matrix[i][j] = inverseMatrix->GetValue(i, j);
1085 std::map<int, NekDouble> motionPrescribed)
1087 for (
int i = 0; i <
m_rows; ++i)
1089 if (motionPrescribed.find(i) != motionPrescribed.end())
1094 if (motionPrescribed.find(i2) == motionPrescribed.end())
1098 if (motionPrescribed.find(i0) == motionPrescribed.end())
1103 u[1][i] = motionPrescribed[i];
1104 if (motionPrescribed.find(i2) == motionPrescribed.end())
1106 u[2][i] =
m_coeffs[0] * u[1][i] - bm;
1110 u[2][i] = motionPrescribed[i2];
1112 if (motionPrescribed.find(i0) == motionPrescribed.end())
1114 u[0][i] =
m_coeffs[2] * u[1][i] + bk;
1118 u[0][i] = motionPrescribed[i0];
1126 std::map<int, NekDouble> motionPrescribed)
1151 rhs[i] +=
m_M[i][j] * bm[j] -
m_K[i][j] * bk[j];
1156 rhs[i] -=
m_M[i][j] * u[2][j1] +
m_C[i][j] * u[1][j1] +
1157 m_K[i][j] * u[0][j1];
1164 u[0][j1] =
m_coeffs[2] * u[1][j1] + bk[j];
1165 u[2][j1] =
m_coeffs[0] * u[1][j1] - bm[j];
1188 if (body != inertial && dim > 2)
1190 for (
int i = 2; i < dim; ++i)
1192 inertial[i] = body[i];
1201 NekDouble x = inertial[0], y = inertial[1];
1204 if (body != inertial && dim > 2)
1206 for (
int i = 2; i < dim; ++i)
1208 body[i] = inertial[i];
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
NekDouble Evaluate() const
static std::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
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.
Defines a forcing term to be explicitly applied.
const std::weak_ptr< EquationSystem > m_equ
Weak pointer to equation system using this forcing.
LibUtilities::SessionReaderSharedPtr m_session
Session reader.
SOLVER_UTILS_EXPORT void v_PreApply(const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble &time) override
Compute the moving frame velocity at given time.
void InitBodySolver(const TiXmlElement *pForce)
Array< OneD, NekDouble > m_velxyz
static std::string classNameBody
Name of the class.
Array< OneD, bool > m_hasVel
~ForcingMovingReferenceFrame(void) override
void addRotation(int npoints, const Array< OneD, Array< OneD, NekDouble > > &inarray0, NekDouble angVelScale, const Array< OneD, Array< OneD, NekDouble > > &inarray1, Array< OneD, Array< OneD, NekDouble > > &outarray)
outarray = inarray0 + angVelScale Omega x inarray1
NekDouble EvaluateExpression(std::string expression)
Newmark_BetaSolver m_bodySolver
std::map< int, LibUtilities::EquationSharedPtr > m_frameVelFunction
void SolveBodyMotion(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const Array< OneD, NekDouble > &forcebody, std::map< int, NekDouble > &Dirs)
unsigned int m_outputFrequency
void UpdateFluidInterface(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const int step)
void UpdatePrescribed(const NekDouble &time, std::map< int, NekDouble > &Dirs)
ForcingMovingReferenceFrame(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation)
Array< OneD, NekDouble > m_omegaxyz
void SetInitialConditions()
std::ofstream m_outputStream
Array< OneD, NekDouble > m_pivotPoint
Array< OneD, Array< OneD, NekDouble > > vel
SOLVER_UTILS_EXPORT void v_Apply(const Array< OneD, MultiRegions::ExpListSharedPtr > &fields, const Array< OneD, Array< OneD, NekDouble > > &inarray, Array< OneD, Array< OneD, NekDouble > > &outarray, const NekDouble &time) override
Adds the body force, -Omega X u.
void LoadParameters(const TiXmlElement *pForce)
SOLVER_UTILS_EXPORT void v_InitObject(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields, const TiXmlElement *pForce) override
Initialise the forcing module.
void UpdateFrameVelocity(const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const NekDouble &time)
Updates the forcing array with the current required forcing.
void UpdateBoundaryConditions(NekDouble time)
Set velocity boundary condition at the next time step.
static SOLVER_UTILS_EXPORT ForcingSharedPtr create(const LibUtilities::SessionReaderSharedPtr &pSession, const std::weak_ptr< EquationSystem > &pEquation, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const unsigned int &pNumForcingFields, const TiXmlElement *pForce)
Creates an instance of this class.
struct Nektar::SolverUtils::ForcingMovingReferenceFrame::@2 m_body
Array< OneD, bool > m_hasOmega
Array< OneD, Array< OneD, NekDouble > > m_coords
Array< OneD, NekDouble > m_travelWave
void InitialiseFilter(const LibUtilities::SessionReaderSharedPtr &pSession, const Array< OneD, MultiRegions::ExpListSharedPtr > &pFields, const TiXmlElement *pForce)
void SetNewmarkBeta(NekDouble beta, NekDouble gamma, NekDouble dt, Array< OneD, NekDouble > M, Array< OneD, NekDouble > C, Array< OneD, NekDouble > K, std::set< int > DirDoFs)
Array< OneD, Array< OneD, NekDouble > > m_K
void SolveFree(Array< OneD, Array< OneD, NekDouble > > u, Array< OneD, NekDouble > force)
std::vector< int > m_index
void SolvePrescribed(Array< OneD, Array< OneD, NekDouble > > u, std::map< int, NekDouble > motionPrescribed)
Array< OneD, Array< OneD, NekDouble > > m_Matrix
Array< OneD, Array< OneD, NekDouble > > m_C
void Solve(Array< OneD, Array< OneD, NekDouble > > u, Array< OneD, NekDouble > force, std::map< int, NekDouble > motionPrescribed)
Array< OneD, NekDouble > m_coeffs
Array< OneD, Array< OneD, NekDouble > > m_M
std::shared_ptr< FieldIO > FieldIOSharedPtr
static std::string PortablePath(const fs::path &path)
create portable path on different platforms for std::filesystem path.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
static FieldMetaDataMap NullFieldMetaDataMap
@ beta
Gauss Radau pinned at x=-1,.
static const NekDouble kNekMachineEpsilon
ForcingFactory & GetForcingFactory()
Declaration of the forcing factory singleton.
static Array< OneD, NekDouble > NullNekDouble1DArray
std::shared_ptr< DNekMat > DNekMatSharedPtr
void Svtvp(int n, const T alpha, const T *x, const int incx, const T *y, const int incy, T *z, const int incz)
Svtvp (scalar times vector plus vector): z = alpha*x + y.
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 Sadd(int n, const T alpha, const T *x, const int incx, T *y, const int incy)
Add vector y = alpha + x.
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
scalarT< T > sqrt(scalarT< T > in)