Nektar++
Loading...
Searching...
No Matches
RigidSolver.cpp
Go to the documentation of this file.
1///////////////////////////////////////////////////////////////////////////////
2//
3// File: RigidSolver.cpp
4//
5// For more information, please see: http://www.nektar.info
6//
7// The MIT License
8//
9// Copyright (c) 2006 Division of Applied Mathematics, Brown University (USA),
10// Department of Aeronautics, Imperial College London (UK), and Scientific
11// Computing and Imaging Institute, University of Utah (USA).
12//
13// Permission is hereby granted, free of charge, to any person obtaining a
14// copy of this software and associated documentation files (the "Software"),
15// to deal in the Software without restriction, including without limitation
16// the rights to use, copy, modify, merge, publish, distribute, sublicense,
17// and/or sell copies of the Software, and to permit persons to whom the
18// Software is furnished to do so, subject to the following conditions:
19//
20// The above copyright notice and this permission notice shall be included
21// in all copies or substantial portions of the Software.
22//
23// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29// DEALINGS IN THE SOFTWARE.
30//
31// Description: Solving the absolute flow in a moving body frame,
32// by adding (U0 + Omega X (x - x0)) . grad u - Omega X u
33// as the body force.
34// U0 is the translational velocity of the body frame.
35// Omega is the angular velocity.
36// x0 is the rotation pivot in the body frame.
37// All vectors use the basis of the body frame.
38// Translational motion is allowed for all dimensions.
39// Rotation is not allowed for 1D, 2DH1D, 3DH2D.
40// Rotation in z direction is allowed for 2D and 3DH1D.
41// Rotation in 3 directions are allowed for 3D.
42// TODO: add suport for 3D rotation using Quaternion
43///////////////////////////////////////////////////////////////////////////////
44
51#include <boost/format.hpp>
52
53namespace Nektar
54{
55
59{
60 bool isH1d, isH2d;
61 session->MatchSolverInfo("Homogeneous", "1D", isH1d, false);
62 session->MatchSolverInfo("Homogeneous", "2D", isH2d, false);
63 bool singleMode, halfMode;
64 session->MatchSolverInfo("ModeType", "SingleMode", singleMode, false);
65 session->MatchSolverInfo("ModeType", "HalfMode", halfMode, false);
66 if (singleMode || halfMode)
67 {
68 isH1d = false;
69 }
70 int expdim = isH2d ? 1 : pField->GetGraph()->GetMeshDimension();
71 m_spacedim = expdim + (isH1d ? 1 : 0) + (isH2d ? 2 : 0);
72 m_isRoot = pField->GetComm()->TreatAsRankZero();
73 m_index = 1;
74 m_currentTime = -1.;
77 TiXmlElement *pSolver = session->GetElement("Nektar/RIGIDSOLVER");
78 LoadParameters(session, pSolver);
79 InitBodySolver(session, pSolver, pivot);
81}
82
84{
85 // Count free translational DoFs
86 int nFreeTrans = 0;
87 bool freeX = false;
88
89 for (int i = 0; i < m_spacedim; ++i)
90 {
91 if (m_dirDoFs.find(i) == m_dirDoFs.end())
92 {
93 ++nFreeTrans;
94 if (i == 0)
95 {
96 freeX = true;
97 }
98 }
99 }
100 if (!m_hasRotation)
101 {
102 m_solveType = 0; // inertial frame
103 }
104 else if (nFreeTrans == 1 && freeX)
105 {
106 m_solveType = 1; // with given rotation and only x free
107 if (m_spacedim >= 2)
108 {
109 m_dirDoFs.erase(1);
110 }
111 }
112 else if ((nFreeTrans == 2 || nFreeTrans == 0) && m_hasRotation)
113 {
114 m_solveType = 2; // full planar rigid solver (rotation involved)
115 }
116 else
117 {
118 ASSERTL0(false, "Unsupported rigid motion: this solver supports only "
119 "(i) translation-only motion, "
120 "(ii) x-only translation with optional rotation, or "
121 "(iii) full planar rigid-body motion.");
122 }
123 if (m_hasRotation)
124 {
126 // m_K should be zero
127 NekDouble sum = 0;
128 for (size_t i = 0; i < m_K.size(); ++i)
129 {
130 sum += fabs(m_K[i]);
131 }
132 for (size_t i = 0; i < m_C.size(); ++i)
133 {
134 sum += fabs(m_C[i]);
135 }
137 "C, K should be zero [in body frame solver].");
138 }
139}
140
141void RigidSolver::SetMovableDoFs(std::vector<bool> &moveDoFs)
142{
143 for (const auto &it : m_frameVelFunction)
144 {
145 if (it.first < 6)
146 {
147 moveDoFs[it.first] = true;
148 }
149 }
150 for (int i = 0; i < m_spacedim; ++i)
151 {
152 if (m_dirDoFs.find(i) == m_dirDoFs.end())
153 {
154 moveDoFs[i] = true;
155 }
156 }
157 if (m_dirDoFs.find(m_spacedim) == m_dirDoFs.end())
158 {
159 moveDoFs[5] = true;
160 }
161 if (moveDoFs[5])
162 {
163 // since m_frameVelFunction is defined in inerital frame
164 // motions in 2 directions occur if there is rotation
165 if (moveDoFs[0] || moveDoFs[1])
166 {
167 moveDoFs[0] = true;
168 moveDoFs[1] = true;
169 }
170 }
171}
172
174 const LibUtilities::SessionReaderSharedPtr session, std::string expression)
175{
176 NekDouble value = 0.;
177 try
178 {
179 LibUtilities::Equation expession(session->GetInterpreter(), expression);
180 value = expession.Evaluate();
181 }
182 catch (const std::runtime_error &)
183 {
184 NEKERROR(ErrorUtil::efatal, "Error evaluating expression" + expression);
185 }
186 return value;
187}
188
190 const bool allowzero, const LibUtilities::SessionReaderSharedPtr session,
191 const std::string &FuncName, const std::string &var,
192 std::map<int, LibUtilities::EquationSharedPtr> &result, const int i)
193{
194 if (session->DefinesFunction(FuncName, var))
195 {
197 session->GetFunction(FuncName, var);
198 if (allowzero || "0" != equ->GetExpression())
199 {
200 result[i] = equ;
201 }
202 }
203}
204
207 const TiXmlElement *pSolver)
208{
209 const TiXmlElement *funcNameElmt;
210 // load frame velocity
211 funcNameElmt = pSolver->FirstChildElement("FRAMEVELOCITY");
212 if (funcNameElmt)
213 {
214 std::string FuncName = funcNameElmt->GetText();
215 ASSERTL0(session->DefinesFunction(FuncName),
216 "Function '" + FuncName + "' is not defined in the session.");
217 // linear velocity
218 for (int i = 0; i < m_spacedim; ++i)
219 {
220 std::string var = session->GetVariable(i);
221 ParserFunctionToMap(false, session, FuncName, var,
223 }
224 // linear displacement and acceleration
225 std::vector<std::string> linearDispVar = {"X", "Y", "Z"};
226 std::vector<std::string> linearAcceVar = {"A_x", "A_y", "A_z"};
227 for (int i = 0; i < m_spacedim; ++i)
228 {
229 ParserFunctionToMap(true, session, FuncName, linearDispVar[i],
230 m_frameVelFunction, i + 6);
231 ParserFunctionToMap(true, session, FuncName, linearAcceVar[i],
232 m_frameVelFunction, i + 12);
233 }
234 // angular velocities
235 std::vector<std::string> angularVar = {"Omega_x", "Omega_y", "Omega_z"};
236 m_hasRotation = false;
237 for (int i = 0; i < 3; ++i)
238 {
239 std::string var = angularVar[i];
240 ParserFunctionToMap(false, session, FuncName, var,
241 m_frameVelFunction, i + 3);
243 m_frameVelFunction.end();
244 }
245 // angular displacement and acceleration
246 std::vector<std::string> angularDispVar = {"Theta_x", "Theta_y",
247 "Theta_z"};
248 std::vector<std::string> angularAccepVar = {"DOmega_x", "DOmega_y",
249 "DOmega_z"};
250 for (int i = 0; i < 3; ++i)
251 {
252 ParserFunctionToMap(true, session, FuncName, angularDispVar[i],
253 m_frameVelFunction, i + 3 + 6);
254 ParserFunctionToMap(true, session, FuncName, angularAccepVar[i],
255 m_frameVelFunction, i + 3 + 12);
256 }
257 }
258
259 // load external force
260 funcNameElmt = pSolver->FirstChildElement("EXTERNALFORCE");
261 if (funcNameElmt)
262 {
263 std::string FuncName = funcNameElmt->GetText();
264 if (session->DefinesFunction(FuncName))
265 {
266 std::vector<std::string> forceVar = {"Fx", "Fy", "Fz"};
267 for (int i = 0; i < m_spacedim; ++i)
268 {
269 std::string var = forceVar[i];
270 ParserFunctionToMap(false, session, FuncName, var,
272 }
273 std::vector<std::string> momentVar = {"Mx", "My", "Mz"};
274 for (int i = 0; i < 3; ++i)
275 {
276 std::string var = momentVar[i];
277 ParserFunctionToMap(false, session, FuncName, var,
278 m_extForceFunction, i + 3);
279 }
280 }
281 }
282
283 // OutputFile
284 const TiXmlElement *mssgTag = pSolver->FirstChildElement("OutputFile");
285 std::string filename;
286 if (mssgTag)
287 {
288 filename = mssgTag->GetText();
289 }
290 else
291 {
292 filename = session->GetSessionName();
293 }
294 if (!(filename.length() >= 4 &&
295 filename.substr(filename.length() - 4) == ".mrf"))
296 {
297 filename += ".mrf";
298 }
299 if (m_isRoot)
300 {
301 m_outputStream.open(filename.c_str());
302 if (m_spacedim == 2)
303 {
305 << "Variables = t, x, ux, ax, y, uy, ay, theta, omega, domega"
306 << std::endl;
307 }
308 else if (m_spacedim == 3)
309 {
310 m_outputStream << "Variables = t, x, ux, ax, y, uy, ay, z, uz, az, "
311 "theta, omega, domega"
312 << std::endl;
313 }
314 }
315
316 // output frequency
318 mssgTag = pSolver->FirstChildElement("OutputFrequency");
319 if (mssgTag)
320 {
321 std::vector<std::string> values;
322 std::string mssgStr = mssgTag->GetText();
323 m_outputFrequency = round(EvaluateExpression(session, mssgStr));
324 }
326 "OutputFrequency should be greater than zero.");
327}
328
331 const TiXmlElement *pSolver, Array<OneD, NekDouble> pivot)
332{
333 int NumDof = m_spacedim + 1;
334 const TiXmlElement *mssgTag;
335 std::string mssgStr;
336 // allocate memory and initialise
338 for (size_t i = 0; i < 3; ++i)
339 {
340 m_vel[i] = Array<OneD, NekDouble>(NumDof, 0.);
341 }
342 // read prescribed motion DoFs
343 m_dirDoFs.clear();
344 for (int i = 0; i < NumDof; ++i)
345 {
346 m_dirDoFs.insert(i);
347 }
348 mssgTag = pSolver->FirstChildElement("MOTIONPRESCRIBED");
349 if (mssgTag)
350 {
351 std::vector<std::string> values;
352 mssgStr = mssgTag->GetText();
353 ParseUtils::GenerateVector(mssgStr, values);
354 ASSERTL0(values.size() == NumDof,
355 "MOTIONPRESCRIBED vector should be of size " +
356 std::to_string(NumDof));
357 for (int i = 0; i < NumDof; ++i)
358 {
359 if (EvaluateExpression(session, values[i]) == 0)
360 {
361 m_dirDoFs.erase(i);
362 }
363 }
364 }
367 m_hasFreeMotion = m_dirDoFs.size() < NumDof;
368 // read mass matrix
369 m_M = Array<OneD, NekDouble>(NumDof * NumDof, 0.);
370 mssgTag = pSolver->FirstChildElement("MASS");
371 ASSERTL0(m_dirDoFs.size() == NumDof || mssgTag, "Mass matrix is required.");
372 if (mssgTag)
373 {
374 std::vector<std::string> values;
375 mssgStr = mssgTag->GetText();
376 ParseUtils::GenerateVector(mssgStr, values);
377 ASSERTL0(values.size() == 1, "Mass matrix should be a scalar.");
378 m_mass = EvaluateExpression(session, values[0]);
379 for (int i = 0; i < m_spacedim; ++i)
380 {
381 m_M[i + i * NumDof] = m_mass;
382 }
383 }
384 mssgTag = pSolver->FirstChildElement("ROTATIONINERTIA");
385 if (mssgTag)
386 {
387 std::vector<std::string> values;
388 mssgStr = mssgTag->GetText();
389 ParseUtils::GenerateVector(mssgStr, values);
390 ASSERTL0(values.size() == 1, "Inertia should be a scalar.");
391 m_rotaionInertia = EvaluateExpression(session, values[0]);
392 m_M[NumDof * NumDof - 1] = m_rotaionInertia;
393 }
394 // read damping matrix
395 m_C = Array<OneD, NekDouble>(NumDof * NumDof, 0.);
396 mssgTag = pSolver->FirstChildElement("DAMPING");
397 if (mssgTag)
398 {
399 std::vector<std::string> values;
400 mssgStr = mssgTag->GetText();
401 ParseUtils::GenerateVector(mssgStr, values);
402 ASSERTL0(values.size() == NumDof * NumDof,
403 "Damping matrix should be of size " + std::to_string(NumDof) +
404 "X" + std::to_string(NumDof));
405 int count = 0;
406 for (int i = 0; i < NumDof; ++i)
407 {
408 for (int j = 0; j < NumDof; ++j)
409 {
410 m_C[count] = EvaluateExpression(session, values[count]);
411 ++count;
412 }
413 }
414 }
415 // read rigidity matrix
416 m_K = Array<OneD, NekDouble>(NumDof * NumDof, 0.);
417 mssgTag = pSolver->FirstChildElement("RIGIDITY");
418 if (mssgTag)
419 {
420 std::vector<std::string> values;
421 mssgStr = mssgTag->GetText();
422 ParseUtils::GenerateVector(mssgStr, values);
423 ASSERTL0(values.size() == NumDof * NumDof,
424 "Rigidity matrix should be of size " + std::to_string(NumDof) +
425 "X" + std::to_string(NumDof));
426 int count = 0;
427 for (int i = 0; i < NumDof; ++i)
428 {
429 for (int j = 0; j < NumDof; ++j)
430 {
431 m_K[count] = EvaluateExpression(session, values[count]);
432 ++count;
433 }
434 }
435 }
436 // read pivot point
437 mssgTag = pSolver->FirstChildElement("PIVOTPOINT");
439 if (mssgTag)
440 {
441 std::vector<std::string> values;
442 mssgStr = mssgTag->GetText();
443 ParseUtils::GenerateVector(mssgStr, values);
444 ASSERTL0(values.size() == m_spacedim,
445 "PIVOTPOINT vector should be of size " +
446 std::to_string(m_spacedim));
447 for (int i = 0; i < m_spacedim; ++i)
448 {
449 m_pivot[i] = EvaluateExpression(session, values[i]);
450 }
451 }
452 Vmath::Vcopy(m_spacedim, m_pivot, 1, pivot, 1);
453 // read the distance between pivotpoint and masscenter
454 mssgTag = pSolver->FirstChildElement("PIVOTDISTANCE");
455 m_pivotdistance = 0.;
456 if (mssgTag)
457 {
458 std::vector<std::string> values;
459 mssgStr = mssgTag->GetText();
460 ParseUtils::GenerateVector(mssgStr, values);
461 ASSERTL0(values.size() == 1, "PivotDistance should be a scalar.");
462 m_pivotdistance = EvaluateExpression(session, values[0]);
463 }
464 // read Newmark Beta paramters
465 m_timestep = session->GetParameter("TimeStep");
466 m_beta = 0.25;
467 m_gamma = 0.51;
468 if (session->DefinesParameter("NewmarkBeta"))
469 {
470 m_beta = session->GetParameter("NewmarkBeta");
471 }
472 if (session->DefinesParameter("NewmarkGamma"))
473 {
474 m_gamma = session->GetParameter("NewmarkGamma");
475 }
476}
477
479 std::map<int, NekDouble> &Dirs)
480{
481 int NumDof = m_spacedim + 1;
482 for (auto it : m_frameVelFunction)
483 {
484 if (it.first < 3)
485 {
486 Dirs[it.first] = it.second->Evaluate(0., 0., 0., time);
487 }
488 else if (it.first == 5)
489 {
490 Dirs[m_spacedim] = it.second->Evaluate(0., 0., 0., time);
491 }
492 else if (it.first < 9)
493 {
494 Dirs[NumDof + it.first - 6] = it.second->Evaluate(0., 0., 0., time);
495 }
496 else if (it.first == 11)
497 {
498 Dirs[NumDof + m_spacedim] = it.second->Evaluate(0., 0., 0., time);
499 }
500 else if (it.first < 15)
501 {
502 Dirs[(NumDof << 1) + it.first - 12] =
503 it.second->Evaluate(0., 0., 0., time);
504 }
505 else if (it.first == 17)
506 {
507 Dirs[(NumDof << 1) + m_spacedim] =
508 it.second->Evaluate(0., 0., 0., time);
509 }
510 }
511 for (auto i : m_dirDoFs)
512 {
513 if (Dirs.find(i) == Dirs.end())
514 {
515 Dirs[i] = 0.;
516 Dirs[i + NumDof] = 0.;
517 Dirs[i + (NumDof << 1)] = 0.;
518 }
519 }
520}
521
523{
524 for (int i = 0; i < 6; ++i)
525 {
526 m_oldFvis[i] = force[6 + i];
527 }
528}
529
530/**
531 * @brief Updates the forcing array with the current required forcing.
532 * @param pFields
533 * @param time
534 */
536 const NekDouble &time,
537 Array<OneD, NekDouble> &MRFData)
538{
539 if (m_currentTime >= time)
540 {
541 return;
542 }
543
544 for (int i = 0; i < 6; ++i)
545 {
546 aeroforce[i] +=
547 2. * aeroforce[6 + i] - m_oldFvis[i]; // extrapolate viscous
548 m_oldFvis[i] = aeroforce[6 + i];
549 }
550 m_currentTime = time;
551 std::map<int, NekDouble> Dirs;
552 UpdatePrescribed(time, Dirs);
553 // compute the velocites whoes functions are provided in inertial frame
554 if (m_hasFreeMotion)
555 {
556 for (auto it : m_extForceFunction)
557 {
558 m_extForceXYZ[it.first] = it.second->Evaluate(0., 0., 0., time);
559 }
560 }
561 SolveBodyMotion(m_vel, aeroforce, Dirs);
563 if (m_hasRotation)
564 {
565 // update inertial position of the body
567 for (size_t i = 0; i < m_vel.size(); ++i)
568 {
569 tmpVel[i] = Array<OneD, NekDouble>(m_vel[i].size());
570 Vmath::Vcopy(m_vel[i].size(), m_vel[i], 1, tmpVel[i], 1);
571 }
572 Array<OneD, NekDouble> angle(3, 0.);
573 angle[2] = tmpVel[0][m_spacedim];
574 m_frame.SetAngle(angle);
575 m_frame.BodyToInerital(m_spacedim, tmpVel[1], tmpVel[1]);
576 m_frame.BodyToInerital(m_spacedim, tmpVel[2], tmpVel[2]);
577 tmpVel[2][0] -= tmpVel[1][m_spacedim] * tmpVel[1][1];
578 tmpVel[2][1] += tmpVel[1][m_spacedim] * tmpVel[1][0];
580 m_timestep * (tmpVel[1][0] + 0.5 * m_timestep * tmpVel[2][0]);
582 m_timestep * (tmpVel[1][1] + 0.5 * m_timestep * tmpVel[2][1]);
583 tmpVel[0][0] = m_inertialPosition[0];
584 tmpVel[0][1] = m_inertialPosition[1];
585 }
586 if (m_isRoot && m_index % m_outputFrequency == 0)
587 {
588 if (!m_hasRotation)
589 {
590 tmpVel = m_vel;
591 }
592 m_outputStream << boost::format("%25.19e") % time << " ";
593 for (size_t i = 0; i < tmpVel[0].size(); ++i)
594 {
595 m_outputStream << boost::format("%25.19e") % tmpVel[0][i] << " "
596 << boost::format("%25.19e") % tmpVel[1][i] << " "
597 << boost::format("%25.19e") % tmpVel[2][i] << " ";
598 }
599 m_outputStream << std::endl;
600 }
601 // set displacements at the current time step
602 UpdateMRFData(MRFData);
603 ++m_index;
604}
605
607{
608 /// MRFData:
609 /// X, Y, Z, Theta_x, Theta_y, Theta_z, [inertial frame 0-5]
610 /// U, V, W, Omega_x, Omega_y, Omega_z, [body frame 6-11]
611 /// A_x, A_y, A_z, DOmega_x, DOmega_y, DOmega_z, [body frame 12-17]
612 /// pivot_x, pivot_y, pivot_z, [body frame]
613 for (int i = 0; i < 18; ++i)
614 {
615 MRFData[i] = 0.0;
616 }
617
618 if (m_hasRotation)
619 {
620 MRFData[0] = m_inertialPosition[0];
621 MRFData[1] = m_inertialPosition[1];
622 }
623 else
624 {
625 MRFData[0] = m_vel[0][0];
626 MRFData[1] = m_vel[0][1];
627 }
628
629 if (m_hasRotation)
630 {
631 MRFData[5] = m_vel[0][m_spacedim];
632 }
633
634 for (int i = 0; i < m_spacedim; ++i)
635 {
636 MRFData[i + 6] = m_vel[1][i];
637 MRFData[i + 12] = m_vel[2][i];
638 }
639
640 if (m_hasRotation)
641 {
642 MRFData[11] = m_vel[1][m_spacedim];
643 MRFData[17] = m_vel[2][m_spacedim];
644 }
645}
646
648 const Array<OneD, NekDouble> &forcebody,
649 std::map<int, NekDouble> &Dirs)
650{
651 if (0 == m_solveType)
652 {
653 SolveInertialFrame(bodyVel, forcebody, Dirs);
654 }
655 else if (1 == m_solveType)
656 {
657 SolveRotOneFree(bodyVel, forcebody, Dirs);
658 }
659 else if (2 == m_solveType)
660 {
661 SolveBodyFrame(bodyVel, forcebody, Dirs);
662 }
663 else
664 {
665 ASSERTL0(false, "Unsupported rigid solver type.");
666 }
667}
668
671 const Array<OneD, NekDouble> &forcebody, std::map<int, NekDouble> &Dirs)
672{
673 // only translational motion or prescribed tranlation with rotational
674 // solve in absolute frame and transform to body frame
675 m_bodySolver.SolvePrescribed(bodyVel, Dirs);
676 if (m_hasFreeMotion)
677 {
678 Array<OneD, NekDouble> force(6, 0.);
679 for (int i = 0; i < m_spacedim; ++i)
680 {
681 force[i] = forcebody[i] + m_extForceXYZ[i];
682 }
683 force[m_spacedim] = forcebody[5] + m_extForceXYZ[5];
684 m_bodySolver.SolveFreeFixMat(bodyVel, force);
685 }
686}
687
688// with rotational and one free tranlation
690 const Array<OneD, NekDouble> &forcebody,
691 std::map<int, NekDouble> &Dirs)
692{
693 // one direction free
694 NekDouble uy = 0.;
695 if (Dirs.find(1) != Dirs.end())
696 {
697 uy = Dirs[1];
698 Dirs.erase(1);
699 }
700 m_bodySolver.SolvePrescribed(bodyVel, Dirs);
701 Array<OneD, NekDouble> force(6, 0.), angle(3, 0.);
702 angle[2] = bodyVel[0][m_spacedim];
703 m_frame.SetAngle(angle);
705 for (int i = 0; i < m_spacedim; ++i)
706 {
707 force[i] = forcebody[i] + force[i];
708 }
709 force[0] += m_mass * bodyVel[1][m_spacedim] * bodyVel[1][m_spacedim] *
711 force[1] -= m_mass * bodyVel[2][m_spacedim] * m_pivotdistance;
712 m_bodySolver.SolveOneFree(bodyVel, force, angle, uy, m_mass);
713}
714
715// with rotational and all free tranlation
717 const Array<OneD, NekDouble> &forcebody,
718 std::map<int, NekDouble> &Dirs)
719{
720 m_bodySolver.SolvePrescribed(bodyVel, Dirs); // at most 1 rotation
721 Array<OneD, NekDouble> force(6, 0.), angle(3, 0.);
722 if (!m_hasFreeMotion)
723 {
724 angle[2] = bodyVel[0][m_spacedim];
725 m_frame.SetAngle(angle);
726 m_frame.IneritalToBody(m_spacedim, bodyVel[1], bodyVel[1]);
727 m_frame.IneritalToBody(m_spacedim, bodyVel[2], bodyVel[2]);
728 bodyVel[2][0] += bodyVel[1][m_spacedim] * bodyVel[1][1];
729 bodyVel[2][1] -= bodyVel[1][m_spacedim] * bodyVel[1][0];
730 return;
731 }
732 if (m_dirDoFs.find(m_spacedim) != m_dirDoFs.end())
733 {
734 // known rotation
735 angle[2] = bodyVel[0][m_spacedim];
736 m_frame.SetAngle(angle);
738 for (int i = 0; i < m_spacedim; ++i)
739 {
740 force[i] = forcebody[i] + force[i];
741 }
742 force[0] += m_mass * bodyVel[1][m_spacedim] * bodyVel[1][m_spacedim] *
744 force[1] -= m_mass * bodyVel[2][m_spacedim] * m_pivotdistance;
745 m_bodySolver.SolveFreeVarMat(bodyVel, force, m_mass);
746 }
747 else
748 {
749 // all free
750 Array<OneD, Array<OneD, NekDouble>> tmpbodyVel(bodyVel.size());
751 for (size_t i = 0; i < bodyVel.size(); ++i)
752 {
753 tmpbodyVel[i] = Array<OneD, NekDouble>(bodyVel[i].size());
754 Vmath::Vcopy(bodyVel[i].size(), bodyVel[i], 1, tmpbodyVel[i], 1);
755 }
756 for (int iter = 0; iter < 2; ++iter)
757 {
758 if (iter > 0)
759 {
760 for (size_t i = 0; i < bodyVel.size(); ++i)
761 {
762 Vmath::Vcopy(bodyVel[i].size() - 1, bodyVel[i], 1,
763 tmpbodyVel[i], 1);
764 }
765 }
766 angle[2] = tmpbodyVel[0][m_spacedim];
767 m_frame.SetAngle(angle);
769 for (int i = 0; i < m_spacedim; ++i)
770 {
771 force[i] = forcebody[i] + force[i];
772 }
773 force[m_spacedim] = forcebody[5] + m_extForceXYZ[5];
774 m_bodySolver.SolveFreeVarMat(tmpbodyVel, force, m_mass);
775 }
776 // copy final results
777 for (size_t i = 0; i < bodyVel.size(); ++i)
778 {
779 Vmath::Vcopy(bodyVel[i].size(), tmpbodyVel[i], 1, bodyVel[i], 1);
780 }
781 }
782}
783
786 const NekDouble mass)
787{
790 double *dMatrix = new double[m_motionDofs * m_motionDofs];
791 int *ipiv = new int[m_motionDofs];
792 double *drhs = new double[m_motionDofs];
793 int info;
794
795 for (int j = 0; j < m_motionDofs; ++j)
796 {
797 int j1 = m_index[j];
798 bm[j] = m_coeffs[0] * u[1][j1] + m_coeffs[1] * u[2][j1];
799 bk[j] = u[0][j1] + m_coeffs[3] * u[1][j1] + m_coeffs[4] * u[2][j1];
800 }
802 for (int i = 0; i < m_motionDofs; ++i)
803 {
804 rhs[i] = force[m_index[i]];
805 for (int j = 0; j < m_motionDofs; ++j)
806 {
807 rhs[i] += m_M[i][j] * bm[j] - m_K[i][j] * bk[j];
808 }
809 for (int j = m_motionDofs; j < m_rows; ++j)
810 {
811 int j1 = m_index[j];
812 rhs[i] -= m_M[i][j] * u[2][j1] + m_C[i][j] * u[1][j1] +
813 m_K[i][j] * u[0][j1];
814 }
815 }
816 for (int i = 0; i < m_motionDofs; ++i)
817 {
818 drhs[i] = rhs[i];
819 for (int j = 0; j < m_motionDofs; ++j)
820 {
821 dMatrix[j * m_motionDofs + i] = m_Matrix[i][j];
822 }
823 }
824 dMatrix[1] += mass * u[1][m_rows - 1];
825 dMatrix[m_motionDofs] += -mass * u[1][m_rows - 1];
826
828 info);
829 Lapack::Dgetrs('N', m_motionDofs, 1, dMatrix, m_motionDofs, ipiv, drhs,
830 m_motionDofs, info);
831 for (int j = 0; j < m_motionDofs; ++j)
832 {
833 int j1 = m_index[j];
834 u[1][j1] = drhs[j];
835 }
836
837 for (int j = 0; j < m_motionDofs; ++j)
838 {
839 int j1 = m_index[j];
840 u[0][j1] = m_coeffs[2] * u[1][j1] + bk[j];
841 u[2][j1] = m_coeffs[0] * u[1][j1] - bm[j];
842 }
843
844 delete[] dMatrix;
845 delete[] drhs;
846 delete[] ipiv;
847}
848
850{
851 int NumDof = m_spacedim + 1;
852 if (AddedMass.size() >= NumDof * NumDof)
853 {
854 Vmath::Vadd(NumDof * NumDof, AddedMass, 1, m_M, 1, m_M, 1);
855 }
858}
859
863{
864 NekDouble time = 0.;
865 std::map<std::string, std::string> fieldMetaDataMap;
866 std::vector<std::string> strFrameData = {
867 "X", "Y", "Z", "Theta_x", "Theta_y", "Theta_z",
868 "U", "V", "W", "Omega_x", "Omega_y", "Omega_z",
869 "A_x", "A_y", "A_z", "DOmega_x", "DOmega_y", "DOmega_z"};
870 std::map<std::string, NekDouble> fileData;
871 if (session->DefinesFunction("InitialConditions"))
872 {
873 for (int i = 0; i < session->GetVariables().size(); ++i)
874 {
875 if (session->GetFunctionType("InitialConditions",
876 session->GetVariable(i)) ==
878 {
879 std::string filename = session->GetFunctionFilename(
880 "InitialConditions", session->GetVariable(i));
881 fs::path pfilename(filename);
882 // redefine path for parallel file which is in directory
883 if (fs::is_directory(pfilename))
884 {
885 fs::path metafile("Info.xml");
886 fs::path fullpath = pfilename / metafile;
887 filename = LibUtilities::PortablePath(fullpath);
888 }
890 LibUtilities::FieldIO::CreateForFile(session, filename);
891 fld->ImportFieldMetaData(filename, fieldMetaDataMap);
892
893 // check to see if time is defined
894 if (fieldMetaDataMap != LibUtilities::NullFieldMetaDataMap)
895 {
896 if (fieldMetaDataMap.find("Time") != fieldMetaDataMap.end())
897 {
898 time = std::stod(fieldMetaDataMap["Time"]);
899 }
900 fileData.clear();
901 for (auto &var : strFrameData)
902 {
903 if (fieldMetaDataMap.find(var) !=
904 fieldMetaDataMap.end())
905 {
906 fileData[var] = std::stod(fieldMetaDataMap[var]);
907 }
908 }
909 if (fileData.size() == strFrameData.size())
910 {
911 break;
912 }
913 }
914 }
915 }
916 }
917 if (session->DefinesCmdLineArgument("set-start-time"))
918 {
919 time = std::stod(
920 session->GetCmdLineArgument<std::string>("set-start-time"));
921 }
922 if (fileData.size() == strFrameData.size())
923 {
924 int NumDofm1 = m_vel[0].size() - 1;
925 for (int i = 0; i < m_spacedim; ++i)
926 {
927 m_vel[0][i] = fileData[strFrameData[i]];
928 m_vel[1][i] = fileData[strFrameData[i + 6]];
929 m_vel[2][i] = fileData[strFrameData[i + 12]];
930 }
931 m_vel[0][NumDofm1] = fileData[strFrameData[5]];
932 m_vel[1][NumDofm1] = fileData[strFrameData[11]];
933 m_vel[2][NumDofm1] = fileData[strFrameData[17]];
934 if (m_hasRotation)
935 {
936 m_inertialPosition[0] = m_vel[0][0];
937 m_inertialPosition[1] = m_vel[0][1];
938 }
939 }
940 std::map<int, NekDouble> Dirs;
941 UpdatePrescribed(time, Dirs);
943 UpdateMRFData(MRFData);
944 // output initial status for rigid body
945 if (m_isRoot)
946 {
948 if (m_hasRotation)
949 {
951 for (size_t i = 0; i < m_vel.size(); ++i)
952 {
953 tmpVel[i] = Array<OneD, NekDouble>(m_vel[i].size());
954 Vmath::Vcopy(m_vel[i].size(), m_vel[i], 1, tmpVel[i], 1);
955 }
956 // transform u, du to body frame
957 Array<OneD, NekDouble> angle(3, 0.);
958 angle[2] = tmpVel[0][m_spacedim];
959 m_frame.SetAngle(angle);
960 m_frame.BodyToInerital(m_spacedim, tmpVel[1], tmpVel[1]);
961 m_frame.BodyToInerital(m_spacedim, tmpVel[2], tmpVel[2]);
962 tmpVel[2][0] -= tmpVel[1][m_spacedim] * tmpVel[1][1];
963 tmpVel[2][1] += tmpVel[1][m_spacedim] * tmpVel[1][0];
964 tmpVel[0][0] = m_inertialPosition[0];
965 tmpVel[0][1] = m_inertialPosition[1];
966 }
967 else
968 {
969 tmpVel = m_vel;
970 }
971 m_outputStream << boost::format("%25.19e") % time << " ";
972 for (size_t i = 0; i < tmpVel[0].size(); ++i)
973 {
974 m_outputStream << boost::format("%25.19e") % tmpVel[0][i] << " "
975 << boost::format("%25.19e") % tmpVel[1][i] << " "
976 << boost::format("%25.19e") % tmpVel[2][i] << " ";
977 }
978 m_outputStream << std::endl;
979 }
980}
981
984 std::map<std::string, std::string> &vParams)
985{
986 TiXmlElement *pForce = session->GetElement("Nektar/RIGIDSOLVER");
987 const TiXmlElement *param = pForce->FirstChildElement("BOUNDARY");
988 ASSERTL0(param, "Body surface should be assigned");
989
990 vParams["Boundary"] = param->GetText();
991 const TiXmlElement *pivotElmt = pForce->FirstChildElement("PIVOTPOINT");
992 if (pivotElmt)
993 {
994 std::string pstr = pivotElmt->GetText();
995 std::replace(pstr.begin(), pstr.end(), ',', ' ');
996 vParams["MomentPoint"] = pstr;
997 }
998}
999
1000void RigidSolver::SetInitialConditions(std::map<int, NekDouble> &Dirs)
1001{
1002 for (auto it : Dirs)
1003 {
1004 int NumDof = m_vel[0].size();
1005 int NumDof2 = NumDof << 1;
1006 if (it.first < m_vel[0].size())
1007 {
1008 m_vel[1][it.first] = it.second;
1009 }
1010 else if (it.first < NumDof2)
1011 {
1012 m_vel[0][it.first - NumDof] = it.second;
1013 }
1014 else
1015 {
1016 m_vel[2][it.first - NumDof2] = it.second;
1017 }
1018 }
1019}
1020
1025 std::set<int> DirDoFs, int solveType)
1026{
1028 m_coeffs[0] = 1. / (gamma * dt);
1029 m_coeffs[1] = 1. / gamma - 1.;
1030 m_coeffs[2] = beta * dt / gamma;
1031 m_coeffs[3] = dt * (1. - beta / gamma);
1032 m_coeffs[4] = (0.5 - beta / gamma) * dt * dt;
1033
1034 m_rows = sqrt(M.size());
1035 m_index.resize(m_rows, -1);
1036 m_motionDofs = 0;
1037 for (int i = 0; i < m_rows; ++i)
1038 {
1039 if (DirDoFs.find(i) == DirDoFs.end())
1040 {
1041 m_index[m_motionDofs++] = i;
1042 }
1043 }
1044 for (int i = 0, count = m_motionDofs; i < m_rows; ++i)
1045 {
1046 if (DirDoFs.find(i) != DirDoFs.end())
1047 {
1048 m_index[count++] = i;
1049 }
1050 }
1051 if (1 == solveType)
1052 {
1054 "2 Dofs if body is free only in x direction.");
1055 }
1056 if (m_motionDofs)
1057 {
1062 DNekMatSharedPtr inverseMatrix =
1064 m_motionDofs, 0.0, eFULL);
1065 for (int i = 0; i < m_motionDofs; ++i)
1066 {
1070 int offset = m_index[i] * m_rows;
1071 for (int j = 0; j < m_rows; ++j)
1072 {
1073 int ind = offset + m_index[j];
1074 m_M[i][j] = M[ind];
1075 m_C[i][j] = C[ind];
1076 m_K[i][j] = K[ind];
1077 NekDouble value =
1078 m_coeffs[0] * M[ind] + C[ind] + m_coeffs[2] * K[ind];
1079 if (j < m_motionDofs)
1080 {
1081 inverseMatrix->SetValue(i, j, value);
1082 }
1083 }
1084 }
1085
1087 if (solveType == 0)
1088 {
1089 inverseMatrix->Invert();
1090 }
1091 for (int i = 0; i < m_motionDofs; ++i)
1092 {
1094 for (int j = 0; j < m_rows; ++j)
1095 {
1096 if (j < m_motionDofs)
1097 {
1098 m_Matrix[i][j] = inverseMatrix->GetValue(i, j);
1099 }
1100 }
1101 }
1102 }
1103}
1104
1107 std::map<int, NekDouble> motionPrescribed)
1108{
1109 for (int i = 0; i < m_rows; ++i)
1110 {
1111 if (motionPrescribed.find(i) != motionPrescribed.end())
1112 {
1113 int i0 = i + m_rows;
1114 int i2 = i0 + m_rows;
1115 NekDouble bm = 0., bk = 0.;
1116 if (motionPrescribed.find(i2) == motionPrescribed.end())
1117 {
1118 bm = m_coeffs[0] * u[1][i] + m_coeffs[1] * u[2][i];
1119 }
1120 if (motionPrescribed.find(i0) == motionPrescribed.end())
1121 {
1122 bk = u[0][i] + m_coeffs[3] * u[1][i] + m_coeffs[4] * u[2][i];
1123 }
1124
1125 u[1][i] = motionPrescribed[i];
1126 if (motionPrescribed.find(i2) == motionPrescribed.end())
1127 {
1128 u[2][i] = m_coeffs[0] * u[1][i] - bm;
1129 }
1130 else
1131 {
1132 u[2][i] = motionPrescribed[i2];
1133 }
1134 if (motionPrescribed.find(i0) == motionPrescribed.end())
1135 {
1136 u[0][i] = m_coeffs[2] * u[1][i] + bk;
1137 }
1138 else
1139 {
1140 u[0][i] = motionPrescribed[i0];
1141 }
1142 }
1143 }
1144}
1145
1148{
1149 if (m_motionDofs)
1150 {
1153 for (int j = 0; j < m_motionDofs; ++j)
1154 {
1155 int j1 = m_index[j];
1156 bm[j] = m_coeffs[0] * u[1][j1] + m_coeffs[1] * u[2][j1];
1157 bk[j] = u[0][j1] + m_coeffs[3] * u[1][j1] + m_coeffs[4] * u[2][j1];
1158 }
1160 for (int i = 0; i < m_motionDofs; ++i)
1161 {
1162 rhs[i] = force[m_index[i]];
1163 for (int j = 0; j < m_motionDofs; ++j)
1164 {
1165 rhs[i] += m_M[i][j] * bm[j] - m_K[i][j] * bk[j];
1166 }
1167 for (int j = m_motionDofs; j < m_rows; ++j)
1168 {
1169 int j1 = m_index[j];
1170 rhs[i] -= m_M[i][j] * u[2][j1] + m_C[i][j] * u[1][j1] +
1171 m_K[i][j] * u[0][j1];
1172 }
1173 }
1174 for (int j = 0; j < m_motionDofs; ++j)
1175 {
1176 int j1 = m_index[j];
1177 u[1][j1] = Vmath::Dot(m_motionDofs, m_Matrix[j], 1, rhs, 1);
1178 u[0][j1] = m_coeffs[2] * u[1][j1] + bk[j];
1179 u[2][j1] = m_coeffs[0] * u[1][j1] - bm[j];
1180 }
1181 }
1182}
1183
1184/**
1185 * e_x \cdot M [du0, du1, du2] + m (e_x \times Omega) \cdot u = F \cdot e_x
1186 * e_x = (c, -s, 0)
1187 * (c M00 - s M10, c M01 - s M11, c M02 - s M 12) [du0, du1, du2]^T +
1188 * (-s Omega, -c Omega, 0) [u0, u1, u2]^T =
1189 * c F0 - s F1
1190 * equation 2, e_y \cdot (u0, u1) = uy = s * u0 + c * u1
1191 **/
1194 const Array<OneD, NekDouble> theta,
1195 const NekDouble uy, const NekDouble mass)
1196{
1197 int iOmega = m_rows - 1;
1198 NekDouble c = cos(theta[2]), s = sin(theta[2]);
1199 NekDouble C00, C01, C10, C11, M0, M1, M2, F0, F1;
1200 M0 = c * m_M[0][0] - s * m_M[1][0];
1201 M1 = c * m_M[0][1] - s * m_M[1][1];
1202 M2 = c * m_M[0][iOmega] - s * m_M[1][iOmega];
1203 C00 = m_coeffs[0] * M0 - s * u[1][iOmega] * mass;
1204 C01 = m_coeffs[0] * M1 - c * u[1][iOmega] * mass;
1205 C10 = s;
1206 C11 = c;
1207 F1 = uy;
1208 // F0
1211 for (int j = 0; j < m_motionDofs; ++j)
1212 {
1213 bm[j] = m_coeffs[0] * u[1][j] + m_coeffs[1] * u[2][j];
1214 bk[j] = u[0][j] + m_coeffs[3] * u[1][j] + m_coeffs[4] * u[2][j];
1215 }
1216 F0 = c * force[0] - s * force[1];
1217 F0 = F0 + M0 * bm[0] + M1 * bm[1] - M2 * u[2][iOmega];
1218 // solve
1219 NekDouble det = 1. / (C00 * C11 - C01 * C10);
1220 u[1][0] = det * (C11 * F0 - C01 * F1);
1221 u[1][1] = det * (-C10 * F0 + C00 * F1);
1222 for (int j = 0; j < m_motionDofs; ++j)
1223 {
1224 u[0][j] = m_coeffs[2] * u[1][j] + bk[j];
1225 u[2][j] = m_coeffs[0] * u[1][j] - bm[j];
1226 }
1227}
1228
1233
1235{
1236 m_matrix[0] = cos(theta[2]);
1237 m_matrix[1] = sin(theta[2]);
1238}
1239
1241 const Array<OneD, NekDouble> &body,
1242 Array<OneD, NekDouble> &inertial)
1243{
1244 NekDouble xi = body[0], eta = body[1];
1245 inertial[0] = xi * m_matrix[0] - eta * m_matrix[1];
1246 inertial[1] = eta * m_matrix[0] + xi * m_matrix[1];
1247 if (body != inertial && dim > 2)
1248 {
1249 for (int i = 2; i < dim; ++i)
1250 {
1251 inertial[i] = body[i];
1252 }
1253 }
1254}
1255
1257 const Array<OneD, NekDouble> &inertial,
1259{
1260 NekDouble x = inertial[0], y = inertial[1];
1261 body[0] = x * m_matrix[0] + y * m_matrix[1];
1262 body[1] = y * m_matrix[0] - x * m_matrix[1];
1263 if (body != inertial && dim > 2)
1264 {
1265 for (int i = 2; i < dim; ++i)
1266 {
1267 body[i] = inertial[i];
1268 }
1269 }
1270}
1271
1272} // namespace Nektar
#define ASSERTL0(condition, msg)
#define NEKERROR(type, msg)
Assert Level 0 – Fundamental assert which is used whether in FULLDEBUG, DEBUG or OPT compilation mode...
void SetAngle(const Array< OneD, NekDouble > theta)
Array< OneD, NekDouble > m_matrix
void IneritalToBody(const int dim, const Array< OneD, NekDouble > &inertial, Array< OneD, NekDouble > &body)
void BodyToInerital(const int dim, const Array< OneD, NekDouble > &body, Array< OneD, NekDouble > &inertial)
static std::shared_ptr< FieldIO > CreateForFile(const LibUtilities::SessionReaderSharedPtr session, const std::string &filename)
Construct a FieldIO object for a given input filename.
Definition FieldIO.cpp:223
static std::shared_ptr< DataType > AllocateSharedPtr(const Args &...args)
Allocate a shared pointer from the memory pool.
Array< OneD, Array< OneD, NekDouble > > m_M
Definition RigidSolver.h:86
Array< OneD, Array< OneD, NekDouble > > m_Matrix
Definition RigidSolver.h:85
void SolveFreeVarMat(Array< OneD, Array< OneD, NekDouble > > u, Array< OneD, NekDouble > force, const NekDouble mass)
void SolveOneFree(Array< OneD, Array< OneD, NekDouble > > u, Array< OneD, NekDouble > force, const Array< OneD, NekDouble > theta, const NekDouble uy, const NekDouble mass)
void SolveFreeFixMat(Array< OneD, Array< OneD, NekDouble > > u, Array< OneD, NekDouble > force)
Array< OneD, NekDouble > m_coeffs
Definition RigidSolver.h:84
std::vector< int > m_index
Definition RigidSolver.h:83
Array< OneD, Array< OneD, NekDouble > > m_C
Definition RigidSolver.h:87
Array< OneD, Array< OneD, NekDouble > > m_K
Definition RigidSolver.h:88
void SetNewmarkBeta(NekDouble beta, NekDouble gamma, NekDouble dt, Array< OneD, NekDouble > M, Array< OneD, NekDouble > C, Array< OneD, NekDouble > K, std::set< int > DirDoFs, int solveType)
void SolvePrescribed(Array< OneD, Array< OneD, NekDouble > > u, std::map< int, NekDouble > motionPrescribed)
static bool GenerateVector(const std::string &str, std::vector< T > &out)
Takes a comma-separated string and converts it to entries in a vector.
Array< OneD, NekDouble > m_pivot
void UpdateMRFData(Array< OneD, NekDouble > &MRFData)
void ParserFunctionToMap(const bool allowzero, const LibUtilities::SessionReaderSharedPtr session, const std::string &FuncName, const std::string &var, std::map< int, LibUtilities::EquationSharedPtr > &result, const int i)
Array< OneD, NekDouble > m_C
void LoadParameters(const LibUtilities::SessionReaderSharedPtr session, const TiXmlElement *pSolver)
Newmark_BetaSolver m_bodySolver
NekDouble m_pivotdistance
std::set< int > m_dirDoFs
Array< OneD, NekDouble > m_inertialPosition
void SetNewmarkBetaSolver(Array< OneD, NekDouble > &AddedMass)
void UpdatePrescribed(const NekDouble &time, std::map< int, NekDouble > &Dirs)
NekDouble EvaluateExpression(const LibUtilities::SessionReaderSharedPtr session, std::string expression)
FrameTransform m_frame
void InitBodySolver(const LibUtilities::SessionReaderSharedPtr session, const TiXmlElement *pSolver, Array< OneD, NekDouble > pivot)
Array< OneD, NekDouble > m_K
NekDouble m_rotaionInertia
void SolveBodyFrame(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const Array< OneD, NekDouble > &forcebody, std::map< int, NekDouble > &Dirs)
void InitObject(const LibUtilities::SessionReaderSharedPtr session, const MultiRegions::ExpListSharedPtr &pField, Array< OneD, NekDouble > pivot)
void SetMovableDoFs(std::vector< bool > &moveDoFs)
std::ofstream m_outputStream
std::map< int, LibUtilities::EquationSharedPtr > m_frameVelFunction
void SetOldFvis(Array< OneD, NekDouble > force)
Array< OneD, NekDouble > m_M
void SetInitialConditions(const LibUtilities::SessionReaderSharedPtr session, Array< OneD, NekDouble > MRFData)
void SolveInertialFrame(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const Array< OneD, NekDouble > &forcebody, std::map< int, NekDouble > &Dirs)
void GetFilterInfo(const LibUtilities::SessionReaderSharedPtr session, std::map< std::string, std::string > &vParams)
Array< OneD, Array< OneD, NekDouble > > m_vel
std::map< int, LibUtilities::EquationSharedPtr > m_extForceFunction
Array< OneD, NekDouble > m_oldFvis
Array< OneD, NekDouble > m_extForceXYZ
void SolveBodyMotion(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const Array< OneD, NekDouble > &forcebody, std::map< int, NekDouble > &Dirs)
void SolveRotOneFree(Array< OneD, Array< OneD, NekDouble > > &bodyVel, const Array< OneD, NekDouble > &forcebody, std::map< int, NekDouble > &Dirs)
NekDouble m_currentTime
void UpdateFrameVelocity(Array< OneD, NekDouble > &aeroforce, const NekDouble &time, Array< OneD, NekDouble > &MRFData)
Updates the forcing array with the current required forcing.
static void Dgetrs(const char &trans, const int &n, const int &nrhs, const double *a, const int &lda, int *ipiv, double *b, const int &ldb, int &info)
General matrix LU backsolve.
Definition Lapack.hpp:297
static void DoSgetrf(const int &m, const int &n, double *a, const int &lda, int *ipiv, int &info)
General matrix LU factorisation.
Definition Lapack.hpp:276
std::shared_ptr< FieldIO > FieldIOSharedPtr
Definition FieldIO.h:322
static std::string PortablePath(const fs::path &path)
create portable path on different platforms for std::filesystem path.
std::shared_ptr< SessionReader > SessionReaderSharedPtr
std::shared_ptr< Equation > EquationSharedPtr
Definition Equation.h:131
static FieldMetaDataMap NullFieldMetaDataMap
Definition FieldIO.h:51
@ beta
Gauss Radau pinned at x=-1,.
Definition PointsType.h:59
std::shared_ptr< ExpList > ExpListSharedPtr
Shared pointer to an ExpList object.
static const NekDouble kNekZeroTol
std::shared_ptr< DNekMat > DNekMatSharedPtr
T Dot(int n, const T *w, const T *x)
dot product
Definition Vmath.hpp:761
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.
Definition Vmath.hpp:180
void Vcopy(int n, const T *x, const int incx, T *y, const int incy)
Definition Vmath.hpp:825
scalarT< T > sqrt(scalarT< T > in)
Definition scalar.hpp:290