31#include "UnsteadyNSTurb.H"
40UnsteadyNSTurb::UnsteadyNSTurb() {}
42UnsteadyNSTurb::UnsteadyNSTurb(
int argc,
char* argv[])
44 _args = autoPtr<argList>(
new argList(argc, argv));
46 if (!
_args->checkRootCase())
48 Foam::FatalError.exit();
51 argList& args =
_args();
52#include "createTime.H"
53#include "createMesh.H"
54 _pimple = autoPtr<pimpleControl>(
new pimpleControl(mesh));
55#include "createFields.H"
56#include "createUfIfPresent.H"
57#include "createFvOptions.H"
72 timeDerivativeSchemeOrder =
73 ITHACAdict->lookupOrDefault<word>(
"timeDerivativeSchemeOrder",
"second");
77 "The BC method must be set to lift or penalty in ITHACAdict"
81 timeDerivativeSchemeOrder ==
"first" || timeDerivativeSchemeOrder ==
"second",
82 "The time derivative approximation must be set to either first or second order scheme in ITHACAdict"
88 NUmodesOut = para->ITHACAdict->lookupOrDefault<label>(
"NmodesUout", 15);
89 NPmodesOut = para->ITHACAdict->lookupOrDefault<label>(
"NmodesPout", 15);
90 NNutModesOut = para->ITHACAdict->lookupOrDefault<label>(
"NmodesNutOut", 15);
91 NUmodes = para->ITHACAdict->lookupOrDefault<label>(
"NmodesUproj", 10);
92 NSUPmodes = para->ITHACAdict->lookupOrDefault<label>(
"NmodesSUPproj", 10);
93 NPmodes = para->ITHACAdict->lookupOrDefault<label>(
"NmodesPproj", 10);
94 NNutModes = para->ITHACAdict->lookupOrDefault<label>(
"NmodesNutProj", 0);
98UnsteadyNSTurb::UnsteadyNSTurb(
const Parameters* myParameters):
108 surfaceScalarField& phi =
_phi();
109 fvMesh& mesh =
_mesh();
110#include "initContinuityErrs.H"
112 pimpleControl& pimple =
_pimple();
113 volScalarField& p =
_p();
114 volVectorField& U =
_U();
115 volScalarField& nut =
_nut();
116 IOMRFZoneList& MRF =
_MRF();
118 instantList Times = runTime.times();
121 mesh.setFluxRequired(p.name());
123 runTime.setTime(Times[1], 1);
126 label nsnapshots = 0;
128 while (runTime.run())
130#include "readTimeControls.H"
131#include "CourantNo.H"
132#include "setDeltaT.H"
134 Info <<
"Time = " << runTime.timeName() << nl << endl;
136 while (pimple.loop())
140 while (pimple.correct())
145 if (pimple.turbCorr())
147 laminarTransport.correct();
152 Info <<
"ExecutionTime = " << runTime.elapsedCpuTime() <<
" s"
153 <<
" ClockTime = " << runTime.elapsedClockTime() <<
" s"
165 std::ofstream of(offlinepath + name(
counter) +
"/" + runTime.timeName());
166 Ufield.append(tmp<volVectorField>(U));
167 Pfield.append(tmp<volScalarField>(p));
168 nutFields.append(tmp<volScalarField>(nut));
175 for (label i = 0; i < mu_now.size(); ++i)
194Eigen::Tensor<double, 3>
201 for (label i = 0; i < cSize; ++i)
205 for (label k = 0; k < cSize; ++k)
220 "./ITHACAoutput/Matrices/",
228Eigen::Tensor<double, 3>
232 const label nAvg =
nutAve.size();
233 Eigen::Tensor<double, 3>
ct1AveTensor(cSize, nAvg, cSize);
235 for (label i = 0; i < cSize; ++i)
237 for (label j = 0; j < nAvg; ++j)
239 for (label k = 0; k < cSize; ++k)
254 "./ITHACAoutput/Matrices/",
262Eigen::Tensor<double, 3>
266 const label nFluct = nutFluctModes.size();
269 for (label i = 0; i < cSize; ++i)
271 for (label j = 0; j < nFluct; ++j)
273 for (label k = 0; k < cSize; ++k)
288 "./ITHACAoutput/Matrices/",
296Eigen::Tensor<double, 3>
303 for (label i = 0; i <
NPmodes; ++i)
307 for (label k = 0; k < cSize; ++k)
322 "./ITHACAoutput/Matrices/",
331Eigen::Tensor<double, 3>
336 const label nAvg =
nutAve.size();
339 for (label i = 0; i <
NPmodes; ++i)
341 for (label j = 0; j < nAvg; ++j)
343 for (label k = 0; k < cSize; ++k)
358 "./ITHACAoutput/Matrices/",
367Eigen::Tensor<double, 3>
372 const label nFluct = nutFluctModes.size();
375 for (label i = 0; i <
NPmodes; ++i)
377 for (label j = 0; j < nFluct; ++j)
379 for (label k = 0; k < cSize; ++k)
394 "./ITHACAoutput/Matrices/",
403Eigen::Tensor<double, 3>
410 for (label i = 0; i < cSize; ++i)
414 for (label k = 0; k < cSize; ++k)
429 "./ITHACAoutput/Matrices/",
437Eigen::Tensor<double, 3>
441 const label nAvg =
nutAve.size();
442 Eigen::Tensor<double, 3>
ct2AveTensor(cSize, nAvg, cSize);
444 for (label i = 0; i < cSize; ++i)
446 for (label j = 0; j < nAvg; ++j)
448 for (label k = 0; k < cSize; ++k)
463 "./ITHACAoutput/Matrices/",
471Eigen::Tensor<double, 3>
475 const label nFluct = nutFluctModes.size();
478 for (label i = 0; i < cSize; ++i)
480 for (label j = 0; j < nFluct; ++j)
482 for (label k = 0; k < cSize; ++k)
488 & fvc::div(nutFluctModes[j] * dev2((fvc::grad(
L_U_SUPmodes[k]))().T()))
497 "./ITHACAoutput/Matrices/",
505Eigen::Tensor<double, 3>
512 for (label i = 0; i <
NPmodes; ++i)
516 for (label k = 0; k < cSize; ++k)
531 "./ITHACAoutput/Matrices/",
540Eigen::Tensor<double, 3>
545 const label nAvg =
nutAve.size();
548 for (label i = 0; i <
NPmodes; ++i)
550 for (label j = 0; j < nAvg; ++j)
552 for (label k = 0; k < cSize; ++k)
567 "./ITHACAoutput/Matrices/",
576Eigen::Tensor<double, 3>
581 const label nFluct = nutFluctModes.size();
584 for (label i = 0; i <
NPmodes; ++i)
586 for (label j = 0; j < nFluct; ++j)
588 for (label k = 0; k < cSize; ++k)
594 & fvc::div(nutFluctModes[j] * dev2((fvc::grad(
L_U_SUPmodes[k]))().T()))
603 "./ITHACAoutput/Matrices/",
615 Eigen::MatrixXd
btMatrix(btSize, btSize);
618 for (label i = 0; i < btSize; ++i)
620 for (label j = 0; j < btSize; ++j)
634 "./ITHACAoutput/Matrices/",
640Eigen::MatrixXd UnsteadyNSTurb::continuity_matrix(label NUmodes,
641 label NSUPmodes, label NPmodes)
644 M_Assert(cSize > 0,
"continuity_matrix: cSize=0");
645 M_Assert(
NPmodes > 0,
"continuity_matrix: NPmodes=0");
646 Eigen::MatrixXd Pmat(
NPmodes, cSize);
649 for (label i = 0; i <
NPmodes; ++i)
651 for (label j = 0; j < cSize; ++j)
661 "./ITHACAoutput/Matrices/",
668Eigen::MatrixXd UnsteadyNSTurb::pressurePPE_L(label NPmodes)
670 Eigen::MatrixXd Lvec(
NPmodes, 1);
672 const word muPath =
"./ITHACAoutput/Offline/mu_samples_mat.txt";
676 "[PPE-L] mu_samples_mat.txt not found; cannot compute R_t."
682 "[PPE-L] mu/time log has <2 rows; need two snapshots for R_t."
684 const double dt0 = muMat(1, 0) - muMat(0, 0);
685 M_Assert(std::abs(dt0) > SMALL,
"[PPE-L] dt0 ~ 0; check mu_samples_mat.txt.");
687 "[PPE-L] Need at least 2 velocity snapshots to build R_t.");
688 const volVectorField& U0 =
Uomfield[0];
689 const volVectorField& U1 =
Uomfield[1];
690 tmp<volVectorField> tUdot = (U1 - U0) / dt0;
691 const volVectorField& Udot = tUdot();
692 const fvMesh& mesh =
Pmodes[0]().mesh();
694 for (label i = 0; i <
NPmodes; ++i)
697 forAll(mesh.boundary(), patchi)
699 const scalarField& chiF =
Pmodes[i].boundaryField()[patchi];
700 const vectorField& UdotF = Udot.boundaryField()[patchi];
701 const vectorField& Sf = mesh.Sf().boundaryField()[patchi];
702 Li += gSum(chiF * (UdotF & Sf));
719 Info <<
"[DEBUG] Entered projectSUP()" << endl;
728 for (label k = 0; k <
liftfield.size(); ++k)
736 for (label k = 0; k <
NUmodes; ++k)
867 const word ct1AveStr =
881 const word ct2AveStr =
896 if (nutFluctModes.size() != 0)
898 const word ct1FluctStr =
912 const word ct2FluctStr =
950 if (nutFluctModes.size() != 0)
973 if (nutFluctModes.size() != 0)
975 cTotalFluctTensor.resize(cSize, nutFluctModes.size(), cSize);
979 if (para->exportPython)
982 "./ITHACAoutput/Matrices/");
984 "./ITHACAoutput/Matrices/");
986 "./ITHACAoutput/Matrices/");
988 "./ITHACAoutput/Matrices/");
990 "./ITHACAoutput/Matrices/");
992 "./ITHACAoutput/Matrices/");
994 "./ITHACAoutput/Matrices/");
996 "./ITHACAoutput/Matrices/");
998 "./ITHACAoutput/Matrices/");
1003 "./ITHACAoutput/Matrices/");
1005 "./ITHACAoutput/Matrices/");
1008 if (nutFluctModes.size() != 0)
1011 "./ITHACAoutput/Matrices/");
1013 "./ITHACAoutput/Matrices/");
1017 if (para->exportMatlab)
1020 "./ITHACAoutput/Matrices/");
1022 "./ITHACAoutput/Matrices/");
1024 "./ITHACAoutput/Matrices/");
1026 "./ITHACAoutput/Matrices/");
1028 "./ITHACAoutput/Matrices/");
1030 "./ITHACAoutput/Matrices/");
1032 "./ITHACAoutput/Matrices/");
1034 "./ITHACAoutput/Matrices/");
1036 "./ITHACAoutput/Matrices/");
1041 "./ITHACAoutput/Matrices/");
1043 "./ITHACAoutput/Matrices/");
1046 if (nutFluctModes.size() != 0)
1049 "./ITHACAoutput/Matrices/");
1051 "./ITHACAoutput/Matrices/");
1055 if (para->exportTxt)
1058 "./ITHACAoutput/Matrices/");
1060 "./ITHACAoutput/Matrices/");
1062 "./ITHACAoutput/Matrices/");
1064 "./ITHACAoutput/Matrices/");
1066 "./ITHACAoutput/Matrices/");
1068 "./ITHACAoutput/Matrices/");
1070 "./ITHACAoutput/Matrices/C");
1072 "./ITHACAoutput/Matrices/ct1");
1074 "./ITHACAoutput/Matrices/ct2");
1079 "./ITHACAoutput/Matrices/ct1Ave");
1081 "./ITHACAoutput/Matrices/ct2Ave");
1084 if (nutFluctModes.size() != 0)
1087 "./ITHACAoutput/Matrices/");
1089 "./ITHACAoutput/Matrices/");
1093 Info <<
"[DEBUG] SUP sizes: cSize=" << cSize
1099 <<
") P(" << P_matrix.rows() <<
"x" << P_matrix.cols() <<
")\n";
1100 Info <<
"[DEBUG] projectSUP() done. SUP matrices/tensors exported.\n";
1102 if (rbfInterp && (!Pstream::parRun()))
1105 <<
"\n==== [RBF DEBUG SUP] ENTERING OFFLINE RBF CONSTRUCTION (AVG linear-μ + FLUCT RBF) ====\n";
1106 const word coeffDir =
"./ITHACAoutput/Coefficients/";
1107 const word muPath =
"./ITHACAoutput/Offline/mu_samples_mat.txt";
1109 Info <<
"[RBF DEBUG SUP] muMat shape: " << muMat.rows() <<
" x " <<
1110 muMat.cols() << endl;
1111 const int nPar = 12;
1112 const int nSnapshotsPerPar = 200;
1113 Eigen::VectorXd timeVec = muMat.col(0);
1114 Eigen::VectorXd muVec = muMat.col(1);
1116 coeffDir +
"Nut_avg_coeffs_mat.txt");
1118 coeffDir +
"Nut_fluct_coeffs_mat.txt");
1119 Info <<
"[RBF DEBUG SUP] Loaded coeffNutAvg shape: " << coeffNutAvg.rows()
1120 <<
" x " << coeffNutAvg.cols() << endl;
1121 Info <<
"[RBF DEBUG SUP] Loaded coeffNutFluct shape: " <<
1122 coeffNutFluct.rows() <<
" x " << coeffNutFluct.cols() << endl;
1123 const int nNutAvgModes = coeffNutAvg.rows();
1124 const int nNutFluctModes = coeffNutFluct.rows();
1125 const int nUniqueMu = nPar;
1127 a.transposeInPlace();
1128 Eigen::VectorXd initSnapInd(nPar);
1129 Eigen::VectorXd timeSnap(nPar);
1131 for (
int i = 0; i < nPar; ++i)
1133 const int start = i * nSnapshotsPerPar;
1134 initSnapInd(i) = start;
1135 timeSnap(i) = timeVec(start + 1) - timeVec(start);
1136 Info <<
"[RBF DEBUG SUP] i=" << i <<
", start=" << start <<
", dt=" <<
1137 timeSnap(i) << endl;
1140 Eigen::VectorXd muVecUnique(nUniqueMu);
1142 for (
int i = 0; i < nUniqueMu; ++i)
1144 muVecUnique(i) = muVec(
static_cast<int>(initSnapInd(i)));
1147 Info <<
"[RBF DEBUG SUP] muVecUnique: [" << muVecUnique(0) <<
" ... "
1148 << muVecUnique(muVecUnique.size() - 1) <<
"] (M=" << muVecUnique.size() <<
1151 "[RBF DEBUG SUP] Calling velDerivativeCoeff() for fluctuation part...\n";
1152 Eigen::MatrixXd Gfluct = coeffNutFluct.transpose();
1154 initSnapInd, timeSnap);
1155 Eigen::MatrixXd velRBF_fluct = interpDataFluct[0];
1156 Eigen::MatrixXd coeffs_fluct = interpDataFluct[1];
1157 Info <<
"[RBF DEBUG SUP] velRBF_fluct shape: " << velRBF_fluct.rows() <<
1158 " x " << velRBF_fluct.cols() << endl;
1159 Info <<
"[RBF DEBUG SUP] coeffs_fluct shape: " << coeffs_fluct.rows() <<
1160 " x " << coeffs_fluct.cols() << endl;
1161 const int nSnapshots = velRBF_fluct.rows();
1162 const int nModes = velRBF_fluct.cols() / 2;
1163 Eigen::MatrixXd adot_only(nSnapshots, nModes);
1165 for (
int i = 0; i < nSnapshots; ++i)
1167 adot_only.row(i) = velRBF_fluct.row(i).tail(nModes);
1173 const double eAvg = 3;
1174 const double eFluct = 0.05;
1175 Eigen::MatrixXd radiiAvg;
1176 Eigen::MatrixXd radiiFluct;
1181 M_Assert(radiiAvg.size() == nNutAvgModes,
"radiiAvg size mismatch");
1185 radiiAvg = Eigen::MatrixXd::Ones(nNutAvgModes, 1) * eAvg;
1191 M_Assert(radiiFluct.size() == nNutFluctModes,
"radiiFluct size mismatch");
1195 radiiFluct = Eigen::MatrixXd::Ones(nNutFluctModes, 1) * eFluct;
1198 List<SPLINTER::DataTable*> samplesNutAvg;
1199 List<SPLINTER::RBFSpline*> rbfSplinesNutAvg;
1200 samplesNutAvg.resize(0);
1201 rbfSplinesNutAvg.resize(0);
1206 List<SPLINTER::DataTable*> samplesNutFluct;
1207 List<SPLINTER::RBFSpline*> rbfSplinesNutFluct;
1208 samplesNutFluct.resize(nNutFluctModes);
1209 rbfSplinesNutFluct.resize(nNutFluctModes);
1210 Info <<
">>> [SUP] Building nut_fluct RBF splines...\n";
1212 for (label i = 0; i < nNutFluctModes; ++i)
1214 const word weightName =
"wRBF_NUTFLUCT_" + name(i + 1);
1215 samplesNutFluct[i] =
new SPLINTER::DataTable(velRBF_fluct.cols(), 1);
1217 for (label j = 0; j < velRBF_fluct.rows(); ++j)
1219 samplesNutFluct[i]->addSample(velRBF_fluct.row(j), coeffs_fluct(j, i));
1222 Eigen::MatrixXd weights;
1228 rbfSplinesNutFluct[i] =
1229 new SPLINTER::RBFSpline
1231 *samplesNutFluct[i],
1232 SPLINTER::RadialBasisFunctionType::GAUSSIAN,
1236 Info <<
" [SUP] nut_fluct RBF " << i + 1 <<
"/" << nNutFluctModes
1237 <<
" loaded from ./ITHACAoutput/weightsSUP/" << weightName <<
"\n";
1241 rbfSplinesNutFluct[i] =
1242 new SPLINTER::RBFSpline
1244 *samplesNutFluct[i],
1245 SPLINTER::RadialBasisFunctionType::GAUSSIAN,
1251 rbfSplinesNutFluct[i]->weights,
1252 "./ITHACAoutput/weightsSUP/",
1255 Info <<
" [SUP] nut_fluct RBF " << i + 1 <<
"/" << nNutFluctModes
1256 <<
" fitted & saved to ./ITHACAoutput/weightsSUP/" << weightName <<
"\n";
1260 this->rbfSplinesNutAvg = rbfSplinesNutAvg;
1261 this->rbfSplinesNutFluct = rbfSplinesNutFluct;
1262 this->samplesNutAvg = samplesNutAvg;
1263 this->samplesNutFluct = samplesNutFluct;
1265 ">>> [SUP] Finished AVG linear-μ table export + FLUCT RBF build.\n";
1284 for (label k = 0; k <
liftfield.size(); ++k)
1292 for (label k = 0; k <
NUmodes; ++k)
1354 const word D_str =
"D_" + name(
NPmodes);
1366 const word bc1_str =
1379 const word bc2_str =
1393 const word bc3_str =
1465 const word ct1AveStr =
1479 const word ct2AveStr =
1494 if (nutFluctModes.size() != 0)
1496 const word ct1FluctStr =
1510 const word ct2FluctStr =
1526 const word ct1PPEStr =
1541 const word ct2PPEStr =
1559 const word ct1PPEAveStr =
1574 const word ct2PPEAveStr =
1590 if (nutFluctModes.size() != 0)
1592 const word ct1PPEFluctStr =
1593 "ct1PPEFluct_" + name(
liftfield.size()) +
"_" + name(
NUmodes) +
"_" + name(
1607 const word ct2PPEFluctStr =
1608 "ct2PPEFluct_" + name(
liftfield.size()) +
"_" + name(
NUmodes) +
"_" + name(
1625 const word L_str =
"L_" + name(
NPmodes);
1633 L_vector = pressurePPE_L(
NPmodes);
1668 if (nutFluctModes.size() != 0)
1678 L_vector = pressurePPE_L(
NPmodes);
1688 if (para->exportPython)
1691 "./ITHACAoutput/Matrices/");
1693 "./ITHACAoutput/Matrices/");
1695 "./ITHACAoutput/Matrices/");
1697 "./ITHACAoutput/Matrices/");
1699 "./ITHACAoutput/Matrices/");
1701 "./ITHACAoutput/Matrices/");
1703 "./ITHACAoutput/Matrices/");
1705 "./ITHACAoutput/Matrices/");
1707 "./ITHACAoutput/Matrices/");
1709 "./ITHACAoutput/Matrices/");
1711 "./ITHACAoutput/Matrices/");
1713 "./ITHACAoutput/Matrices/");
1715 "./ITHACAoutput/Matrices/");
1720 "./ITHACAoutput/Matrices/");
1722 "./ITHACAoutput/Matrices/");
1724 "./ITHACAoutput/Matrices/");
1726 "./ITHACAoutput/Matrices/");
1729 if (nutFluctModes.size() != 0)
1732 "./ITHACAoutput/Matrices/");
1734 "./ITHACAoutput/Matrices/");
1736 "./ITHACAoutput/Matrices/");
1738 "./ITHACAoutput/Matrices/");
1747 if (para->exportMatlab)
1750 "./ITHACAoutput/Matrices/");
1752 "./ITHACAoutput/Matrices/");
1754 "./ITHACAoutput/Matrices/");
1756 "./ITHACAoutput/Matrices/");
1758 "./ITHACAoutput/Matrices/");
1760 "./ITHACAoutput/Matrices/");
1762 "./ITHACAoutput/Matrices/");
1764 "./ITHACAoutput/Matrices/");
1766 "./ITHACAoutput/Matrices/");
1768 "./ITHACAoutput/Matrices/");
1770 "./ITHACAoutput/Matrices/");
1772 "./ITHACAoutput/Matrices/");
1774 "./ITHACAoutput/Matrices/");
1779 "./ITHACAoutput/Matrices/");
1781 "./ITHACAoutput/Matrices/");
1783 "./ITHACAoutput/Matrices/");
1785 "./ITHACAoutput/Matrices/");
1788 if (nutFluctModes.size() != 0)
1791 "./ITHACAoutput/Matrices/");
1793 "./ITHACAoutput/Matrices/");
1795 "./ITHACAoutput/Matrices/");
1797 "./ITHACAoutput/Matrices/");
1806 if (para->exportTxt)
1809 "./ITHACAoutput/Matrices/");
1811 "./ITHACAoutput/Matrices/");
1813 "./ITHACAoutput/Matrices/");
1815 "./ITHACAoutput/Matrices/");
1817 "./ITHACAoutput/Matrices/");
1819 "./ITHACAoutput/Matrices/");
1821 "./ITHACAoutput/Matrices/C");
1823 "./ITHACAoutput/Matrices/G");
1825 "./ITHACAoutput/Matrices/BC2");
1827 "./ITHACAoutput/Matrices/");
1829 "./ITHACAoutput/Matrices/ct1");
1831 "./ITHACAoutput/Matrices/ct2");
1833 "./ITHACAoutput/Matrices/ct1PPE");
1835 "./ITHACAoutput/Matrices/ct2PPE");
1840 "./ITHACAoutput/Matrices/ct1Ave");
1842 "./ITHACAoutput/Matrices/ct2Ave");
1844 "./ITHACAoutput/Matrices/ct1PPEAve");
1846 "./ITHACAoutput/Matrices/ct2PPEAve");
1849 if (nutFluctModes.size() != 0)
1852 "./ITHACAoutput/Matrices/");
1854 "./ITHACAoutput/Matrices/");
1856 "./ITHACAoutput/Matrices/");
1858 "./ITHACAoutput/Matrices/");
1882 if (nutFluctModes.size() != 0)
1884 cTotalFluctTensor.resize(cSize, nutFluctModes.size(), cSize);
1886 cTotalPPEFluctTensor.resize(
NPmodes, nutFluctModes.size(), cSize);
1890 if (rbfInterp && (!Pstream::parRun()))
1893 <<
"\n==== [RBF DEBUG] ENTERING OFFLINE RBF CONSTRUCTION (AVG linear-μ + FLUCT RBF) ====\n";
1894 const word coeffDir =
"./ITHACAoutput/Coefficients/";
1895 const word muPath =
"./ITHACAoutput/Offline/mu_samples_mat.txt";
1897 Info <<
"[RBF DEBUG] muMat shape: " << muMat.rows() <<
" x " <<
1898 muMat.cols() << endl;
1899 const int nPar = 12;
1900 const int nSnapshotsPerPar = 200;
1901 Eigen::VectorXd timeVec = muMat.col(0);
1902 Eigen::VectorXd muVec = muMat.col(1);
1904 coeffDir +
"Nut_avg_coeffs_mat.txt");
1906 coeffDir +
"Nut_fluct_coeffs_mat.txt");
1907 Info <<
"[RBF DEBUG] Loaded coeffNutAvg shape: " << coeffNutAvg.rows() <<
1908 " x " << coeffNutAvg.cols() << endl;
1909 Info <<
"[RBF DEBUG] Loaded coeffNutFluct shape: " << coeffNutFluct.rows()
1910 <<
" x " << coeffNutFluct.cols() << endl;
1911 const int nNutAvgModes = coeffNutAvg.rows();
1912 const int nNutFluctModes = coeffNutFluct.rows();
1913 const int nUniqueMu = nPar;
1915 a.transposeInPlace();
1916 Eigen::VectorXd initSnapInd(nPar);
1917 Eigen::VectorXd timeSnap(nPar);
1919 for (
int i = 0; i < nPar; ++i)
1921 const int start = i * nSnapshotsPerPar;
1922 initSnapInd(i) = start;
1923 timeSnap(i) = timeVec(start + 1) - timeVec(start);
1924 Info <<
"[RBF DEBUG] i=" << i <<
", start=" << start <<
", dt=" <<
1925 timeSnap(i) << endl;
1928 Eigen::VectorXd muVecUnique(nUniqueMu);
1930 for (
int i = 0; i < nUniqueMu; ++i)
1932 muVecUnique(i) = muVec(
static_cast<int>(initSnapInd(i)));
1935 Info <<
"[RBF DEBUG] muVecUnique: [" << muVecUnique(0) <<
" ... "
1936 << muVecUnique(muVecUnique.size() - 1) <<
"] (M=" << muVecUnique.size() <<
1939 "[RBF DEBUG] Calling velDerivativeCoeff() for fluctuation part...\n";
1940 Eigen::MatrixXd Gfluct = coeffNutFluct.transpose();
1942 initSnapInd, timeSnap);
1943 Eigen::MatrixXd velRBF_fluct = interpDataFluct[0];
1944 Eigen::MatrixXd coeffs_fluct = interpDataFluct[1];
1945 Info <<
"[RBF DEBUG] velRBF_fluct shape: " << velRBF_fluct.rows() <<
" x "
1946 << velRBF_fluct.cols() << endl;
1947 Info <<
"[RBF DEBUG] coeffs_fluct shape: " << coeffs_fluct.rows() <<
" x "
1948 << coeffs_fluct.cols() << endl;
1949 const int nSnapshots = velRBF_fluct.rows();
1950 const int nModes = velRBF_fluct.cols() / 2;
1951 Eigen::MatrixXd adot_only(nSnapshots, nModes);
1953 for (
int i = 0; i < nSnapshots; ++i)
1955 adot_only.row(i) = velRBF_fluct.row(i).tail(nModes);
1961 Info <<
"\n[RBF DEBUG] First row of a (velocity coeffs): ";
1963 for (
int k = 0; k < a.cols(); ++k)
1965 Info << a(0, k) <<
" ";
1969 Info <<
"[RBF DEBUG] First row of velRBF_fluct ([a, aDot]): ";
1971 for (
int k = 0; k < velRBF_fluct.cols(); ++k)
1973 Info << velRBF_fluct(0, k) <<
" ";
1977 Info <<
"[RBF DEBUG] First row of adot_only (aDot): ";
1979 for (
int k = 0; k < adot_only.cols(); ++k)
1981 Info << adot_only(0, k) <<
" ";
1985 const double eAvg = 3;
1986 const double eFluct = 0.05;
1987 Eigen::MatrixXd radiiAvg;
1988 Eigen::MatrixXd radiiFluct;
1993 Info <<
"[RBF DEBUG] Loaded radii_avg.txt, shape: " << radiiAvg.rows() <<
1994 " x " << radiiAvg.cols() << endl;
1995 M_Assert(radiiAvg.size() == nNutAvgModes,
"radiiAvg size mismatch");
1999 radiiAvg = Eigen::MatrixXd::Ones(nNutAvgModes, 1) * eAvg;
2001 "[RBF DEBUG] Set default radii for nutAvg (unused with linear μ), e=" << eAvg
2008 Info <<
"[RBF DEBUG] Loaded radii_fluct.txt, shape: " << radiiFluct.rows()
2009 <<
" x " << radiiFluct.cols() << endl;
2010 M_Assert(radiiFluct.size() == nNutFluctModes,
"radiiFluct size mismatch");
2014 radiiFluct = Eigen::MatrixXd::Ones(nNutFluctModes, 1) * eFluct;
2015 Info <<
"[RBF DEBUG] Set default radii for nutFluct, e=" << eFluct <<
2019 List<SPLINTER::DataTable*> samplesNutAvg;
2020 List<SPLINTER::RBFSpline*> rbfSplinesNutAvg;
2021 samplesNutAvg.resize(0);
2022 rbfSplinesNutAvg.resize(0);
2027 Info <<
">>> Persisted νt_avg tables for linear μ-interpolation: "
2028 <<
"mu size=" << muVecUnique.size()
2029 <<
", coeff table=" << coeffNutAvg.rows() <<
"x" << coeffNutAvg.cols() <<
"\n";
2030 List<SPLINTER::DataTable*> samplesNutFluct;
2031 List<SPLINTER::RBFSpline*> rbfSplinesNutFluct;
2032 samplesNutFluct.resize(nNutFluctModes);
2033 rbfSplinesNutFluct.resize(nNutFluctModes);
2034 Info <<
">>> Building nut_fluct RBF splines...\n";
2036 for (label i = 0; i < nNutFluctModes; ++i)
2038 const word weightName =
"wRBF_NUTFLUCT_" + name(i + 1);
2039 samplesNutFluct[i] =
new SPLINTER::DataTable(velRBF_fluct.cols(), 1);
2041 for (label j = 0; j < velRBF_fluct.rows(); ++j)
2043 samplesNutFluct[i]->addSample(velRBF_fluct.row(j), coeffs_fluct(j, i));
2046 Eigen::MatrixXd weights;
2052 rbfSplinesNutFluct[i] =
2053 new SPLINTER::RBFSpline
2055 *samplesNutFluct[i],
2056 SPLINTER::RadialBasisFunctionType::GAUSSIAN,
2060 Info <<
" nut_fluct RBF " << i + 1 <<
"/" << nNutFluctModes
2061 <<
" loaded from weights.\n";
2065 rbfSplinesNutFluct[i] =
2066 new SPLINTER::RBFSpline
2068 *samplesNutFluct[i],
2069 SPLINTER::RadialBasisFunctionType::GAUSSIAN,
2075 rbfSplinesNutFluct[i]->weights,
2076 "./ITHACAoutput/weightsPPE/",
2079 Info <<
" nut_fluct RBF " << i + 1 <<
"/" << nNutFluctModes
2080 <<
" fitted & saved.\n";
2084 Info <<
"[OFFLINE] Built nutAvgSplines: " << rbfSplinesNutAvg.size()
2085 <<
" (expected 0 for linear μ)\n";
2086 Info <<
"[OFFLINE] Built nutFluctSplines:" << rbfSplinesNutFluct.size() <<
2088 Info <<
">>> Finished AVG linear-μ table export + FLUCT RBF build.\n";
2089 this->rbfSplinesNutAvg = rbfSplinesNutAvg;
2090 this->rbfSplinesNutFluct = rbfSplinesNutFluct;
2091 this->samplesNutAvg = samplesNutAvg;
2092 this->samplesNutFluct = samplesNutFluct;
2093 Info <<
"[OFFLINE] Built nutAvgSplines: " << rbfSplinesNutAvg.size() <<
2095 Info <<
"[OFFLINE] Built nutFluctSplines: " << rbfSplinesNutFluct.size() <<
2102 Eigen::VectorXd initSnapInd,
2103 Eigen::VectorXd timeSnap)
2105 List<Eigen::MatrixXd> newCoeffs;
2106 newCoeffs.setSize(2);
2107 const label velCoeffsNum = A.cols();
2108 const label snapshotsNum = A.rows();
2109 const label parsSamplesNum = initSnapInd.size();
2110 const label timeSnapshotsPerSample = snapshotsNum / parsSamplesNum;
2111 const label newColsNum = 2 * velCoeffsNum;
2112 const label newRowsNum = snapshotsNum - parsSamplesNum;
2113 newCoeffs[0].resize(newRowsNum, newColsNum);
2114 newCoeffs[1].resize(newRowsNum, G.cols());
2117 for (label j = 0; j < parsSamplesNum; ++j)
2119 const int i0 = j * timeSnapshotsPerSample;
2120 const int N = timeSnapshotsPerSample;
2122 for (
int n = 1; n < N; ++n, ++rowCount)
2124 const Eigen::RowVectorXd a_now = A.row(i0 + n);
2125 const Eigen::RowVectorXd a_prev = A.row(i0 + n - 1);
2126 const Eigen::RowVectorXd adot = (a_now - a_prev) / timeSnap(j);
2127 newCoeffs[0].row(rowCount) << a_now, adot;
2128 newCoeffs[1].row(rowCount) = G.row(i0 + n);
2139 List<Eigen::MatrixXd> newCoeffs;
2140 newCoeffs.setSize(2);
2141 Eigen::MatrixXd pars =
z.leftCols(
z.cols() - 1);
2142 newCoeffs[0].resize(A.rows(), A.cols() +
z.cols() - 1);
2143 newCoeffs[1].resize(G.rows(), G.cols());
2144 newCoeffs[0] << pars, A;
2152 Eigen::VectorXd initSnapInd,
2153 Eigen::VectorXd timeSnap)
2155 Info <<
"[velParDerivativeCoeff] ENTER" << endl;
2156 List<Eigen::MatrixXd> newCoeffs;
2157 newCoeffs.setSize(2);
2158 const label velCoeffsNum = A.cols();
2159 const label snapshotsNum = A.rows();
2160 const label parsSamplesNum = initSnapInd.size();
2161 const label timeSnapshotsPerSample = snapshotsNum / parsSamplesNum;
2162 Info <<
"[velParDerivativeCoeff] A shape: " << snapshotsNum <<
" x " <<
2163 velCoeffsNum << endl;
2164 Info <<
"[velParDerivativeCoeff] G shape: " << G.rows() <<
" x " <<
2166 Info <<
"[velParDerivativeCoeff] nPars: " << parsSamplesNum
2167 <<
", timeSnapshotsPerSample: " << timeSnapshotsPerSample << endl;
2168 Eigen::MatrixXd pars(snapshotsNum, 1);
2170 for (label j = 0; j < parsSamplesNum; ++j)
2172 pars.block(j * timeSnapshotsPerSample, 0, timeSnapshotsPerSample, 1) =
2173 Eigen::VectorXd::Constant(timeSnapshotsPerSample,
mu(j));
2176 const label newColsNum = 2 * velCoeffsNum;
2177 const label newRowsNum = snapshotsNum - parsSamplesNum;
2178 Info <<
"[velParDerivativeCoeff] newCoeffs[0] size: " << newRowsNum <<
2179 " x " << (newColsNum + pars.cols()) << endl;
2180 Info <<
"[velParDerivativeCoeff] newCoeffs[1] size: " << newRowsNum <<
2181 " x " << G.cols() << endl;
2182 newCoeffs[0].resize(newRowsNum, newColsNum + pars.cols());
2183 newCoeffs[1].resize(newRowsNum, G.cols());
2184 int totalRowsWritten = 0;
2186 for (label j = 0; j < parsSamplesNum; ++j)
2188 const int start = j * timeSnapshotsPerSample;
2189 const int rowOffset = j * (timeSnapshotsPerSample - 1);
2190 Info <<
"[velParDerivativeCoeff] Group " << j
2191 <<
": start=" << start <<
", rowOffset=" << rowOffset << endl;
2192 Info <<
"[velParDerivativeCoeff] b0: rows " << start <<
" to "
2193 << (start + timeSnapshotsPerSample - 2) << endl;
2195 if (start + timeSnapshotsPerSample - 1 > snapshotsNum)
2197 std::cerr <<
"[velParDerivativeCoeff][ERROR] b0 access out of bounds! (start="
2198 << start <<
", timeSnapshotsPerSample-1=" << (timeSnapshotsPerSample - 1)
2199 <<
", snapshotsNum=" << snapshotsNum <<
")" << endl;
2203 const Eigen::MatrixXd b0 = A.middleRows(start, timeSnapshotsPerSample - 1);
2204 Info <<
"[velParDerivativeCoeff] b1: rows " << (start + 1) <<
" to "
2205 << (start + timeSnapshotsPerSample - 1) << endl;
2207 if (start + 1 + timeSnapshotsPerSample - 2 >= snapshotsNum)
2209 std::cerr <<
"[velParDerivativeCoeff][ERROR] b1 access out of bounds! (start+1="
2210 << (start + 1) <<
", timeSnapshotsPerSample-1=" << (timeSnapshotsPerSample - 1)
2211 <<
", snapshotsNum=" << snapshotsNum <<
")" << endl;
2215 const Eigen::MatrixXd b1 = A.middleRows(start + 1, timeSnapshotsPerSample - 1);
2216 Eigen::MatrixXd bNew(b0.rows(), b0.cols() + b1.cols());
2217 bNew << b1, (b1 - b0) / timeSnap(j);
2218 Info <<
"[velParDerivativeCoeff] pars block for input: rows " <<
2219 (start + 1) <<
" to "
2220 << (start + timeSnapshotsPerSample - 1) << endl;
2222 if (start + 1 + timeSnapshotsPerSample - 2 >= snapshotsNum)
2224 std::cerr <<
"[velParDerivativeCoeff][ERROR] pars access out of bounds!" <<
2229 newCoeffs[0].block(rowOffset, 0, timeSnapshotsPerSample - 1, pars.cols()) =
2230 pars.middleRows(start + 1, timeSnapshotsPerSample - 1);
2231 newCoeffs[0].block(rowOffset, pars.cols(), timeSnapshotsPerSample - 1,
2233 Info <<
"[velParDerivativeCoeff] G block for output: rows " <<
2234 (start + 1) <<
" to "
2235 << (start + timeSnapshotsPerSample - 1) << endl;
2237 if (start + 1 + timeSnapshotsPerSample - 2 >= G.rows())
2239 std::cerr <<
"[velParDerivativeCoeff][ERROR] G access out of bounds!" <<
2244 newCoeffs[1].middleRows(rowOffset, timeSnapshotsPerSample - 1) =
2245 G.middleRows(start + 1, timeSnapshotsPerSample - 1);
2246 totalRowsWritten += timeSnapshotsPerSample - 1;
2247 Info <<
"[velParDerivativeCoeff] Finished group " << j
2248 <<
", totalRowsWritten so far: " << totalRowsWritten << endl;
2251 Info <<
"[velParDerivativeCoeff] FINISHED. Total rows written: "
2252 << totalRowsWritten <<
"/" << newRowsNum << endl;
2258 Eigen::VectorXd par,
2261 Eigen::MatrixXd newCoeffs;
2262 const label velCoeffsNum = A.cols();
2263 const label snapshotsNum = A.rows();
2264 const label parsSamplesNum = par.size();
2265 const label newColsNum = 2 * velCoeffsNum + parsSamplesNum;
2266 const label newRowsNum = snapshotsNum - 1;
2267 newCoeffs.resize(newRowsNum, newColsNum);
2268 const Eigen::MatrixXd b0 = A.topRows(A.rows() - 1);
2269 const Eigen::MatrixXd b1 = A.bottomRows(A.rows() - 1);
2270 Eigen::MatrixXd bNew(b0.rows(), b0.cols() + b1.cols());
2271 bNew << b1, ((b1 - b0) / timeSnap);
2272 newCoeffs.leftCols(parsSamplesNum) =
2273 Eigen::MatrixXd::Ones(newRowsNum, parsSamplesNum) * par;
2274 newCoeffs.rightCols(newColsNum - parsSamplesNum) = bNew;
2285 volVectorField& Smag, std::optional<PtrList<volVectorField>> modesU)
2287 if (m_parameters->get_DEIMInterpolatedField() ==
"fullStressFunction"
2294 Info <<
"Error : DEIMInterpolatedField not valid : "
2295 << m_parameters->get_DEIMInterpolatedField() << endl;
2296 Info <<
"DEIM is available for fullStressFunction and nut only." << endl;
2314 std::optional<PtrList<volVectorField>> modesU)
2317 volVectorField snapshotj = m_parameters->get_template_field_U();
2318 ITHACAstream::read_snapshot(snapshotj, snap_time, m_parameters->get_casenameData());
2323 snapshotj = proj_snapshotj;
2332 volScalarField phij = template_field_phi;
2333 ITHACAstream::read_snapshot(phij, snap_time, m_parameters->get_casenameData());
2334 volVectorField snapshotj = m_parameters->get_template_field_U();
2335 ITHACAstream::read_snapshot(snapshotj, snap_time, m_parameters->get_casenameData());
2343 return (fvc::div(2*nut*dev(S)));
2350 return (fvc::div(nut*fvc::grad(phij)));
2356 return ( fvc::laplacian(coefDiff , phi) );
2392 return volScalarField(
"projFullStressFunction",
2393 m_parameters->get_template_field_fullStressFunction() & m_parameters->get_template_field_U());
2399 volVectorField Smagj = m_parameters->get_template_field_fullStressFunction();
2402 ITHACAstream::read_snapshot(Smagj, snap_time, m_parameters->get_casenameData());
2406 word path =
"./ITHACAoutput/Hyperreduction/reducedFullStressFunction/";
2407 ITHACAstream::read_snapshot(Smagj, snap_time, path);
2410 return Smagj & mode;
2414 const volVectorField& mode)
2425 volVectorField& modeU_proj , volVectorField& modeU_grad)
2437 return volScalarField(
"projSmagFromNut",
initSmagFunction() & m_parameters->get_template_field_U());
2441 (
const word& snap_time,
const volVectorField& modeU_proj,
const volVectorField& modeU_grad)
2444 volScalarField Nutj(m_parameters->get_DEIMInterpolatedField(), m_parameters->get_template_field_nut());
2447 ITHACAstream::read_snapshot(Nutj, snap_time, m_parameters->get_casenameData());
2451 word path =
"./ITHACAoutput/Hyperreduction/reducedNut/";
2452 ITHACAstream::read_snapshot(Nutj, snap_time, path);
2458 const volScalarField& Nut,
const volVectorField& modeU_proj,
const volVectorField& modeU_grad)
2464 const volVectorField& u,
const volVectorField& v)
2468 return 2*coefDiff*(dev(symGradU) && dev(symGradV));
2477 std::optional<PtrList<volVectorField>> modesU)
2479 if (m_parameters->get_DEIMInterpolatedField() ==
"nut"
2484 else if (m_parameters->get_DEIMInterpolatedField() ==
"fullStressFunction_K")
2488 else if (m_parameters->get_DEIMInterpolatedField() ==
"fullStressFunction_Omega")
2494 Info <<
"Error : DEIMInterpolatedField not valid : "
2495 << m_parameters->get_DEIMInterpolatedField() << endl;
2496 Info <<
"DEIM is available for fullStressFunction and nut only." << endl;
2503 return volScalarField(m_parameters->get_template_field_nut());
2509 volVectorField snapshotj = m_parameters->get_template_field_U();
2510 ITHACAstream::read_snapshot(snapshotj, snap_time, m_parameters->get_casenameData());
2515 snapshotj = proj_snapshotj;
2530 volScalarField delta = m_parameters->get_delta();
2531 float Ck = m_parameters->get_Ck();
2532 float Ce = m_parameters->get_Ce();
2542 volScalarField a(Ce/delta);
2543 volScalarField b((2.0/3.0)*tr(S));
2544 volScalarField c(2*Ck*delta*(dev(S) && S));
2546 volScalarField k(sqr((-b + sqrt(sqr(b) + 4*a*c))/(2*a)));
2548 volScalarField nut = m_parameters->get_template_field_nut();
2551 for (
int i=0; i<nut.size(); i++)
2553 nut[i] = Ck*delta[i]*std::pow(k[i],0.5);
2557 nut.correctBoundaryConditions();
2600 volTensorField gradV=fvc::grad(snapshotj);
2601 return 0.5*(gradV+gradV.T());
2606 volVectorField gradV=fvc::grad(phij);
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
Class that contains all parameters of the stochastic POD.
volVectorField computeSmagTerm_fromU(const volVectorField &snapshotj)
Compute Smagorinsky Snapshot for a given velocity field U.
void computeProjSmagFromNut_fromNut_fromModes(volScalarField &phi, const volScalarField &Nut, const volVectorField &modeU_proj, const volVectorField &modeU_grad)
Compute projSmagFromNut given Nut and 2 velocity modes.
Eigen::Tensor< double, 3 > ct1PPEFluctTensor
Turbulent fluctuation viscosity tensor for the splitting approach in the PPE equation.
Eigen::Tensor< double, 3 > cTotalTensor
Turbulent total viscosity tensor.
Eigen::Tensor< double, 3 > turbulenceAveTensor2(label NUmodes, label NSUPmodes)
ct2Ave added tensor for approximation of the averaged part of the eddy viscosity
Eigen::Tensor< double, 3 > ct1Tensor
Turbulent viscosity tensor.
Eigen::Tensor< double, 3 > cTotalPPETensor
Turbulent total viscosity tensor in the PPE equation.
volScalarField computeNut_fromU(const volVectorField &snapshotj)
Compute turbulent viscosity Snapshot for a given velocity field U.
PtrList< volScalarField > nutAve
List of for eddy viscosity time-averaged fields.
scalar _pRefValue
Pressure reference value.
Eigen::MatrixXd btTurbulence(label NUmodes, label NSUPmodes)
bt added matrix for the turbulence treatement
List< Eigen::MatrixXd > velParDerivativeCoeff(Eigen::MatrixXd A, Eigen::MatrixXd G, Eigen::VectorXd initSnapInd, Eigen::VectorXd timeSnap)
A method to compute the two matrices needed for the RBF interpolation by combining the parameter valu...
Eigen::Tensor< double, 3 > ct2Tensor
Turbulent viscosity tensor.
Eigen::Tensor< double, 3 > turbulencePPETensor1(label NUmodes, label NSUPmodes, label NPmodes, label nNutModes)
ct1PPE added tensor for the turbulence treatement in the PPE method
Eigen::Tensor< double, 3 > turbulenceAveTensor1(label NUmodes, label NSUPmodes)
ct1Ave added tensor for approximation of the averaged part of the eddy viscosity
Eigen::Tensor< double, 3 > ct2PPEAveTensor
Turbulent average viscosity tensor for the splitting approach in the PPE equation.
volVectorField initSmagFunction()
Initialize Smagorinsky term with values at time 0.
Eigen::Tensor< double, 3 > ct1PPETensor
Turbulent viscosity tensor in the PPE equation.
void projectSUP(fileName folder, label NUmodes, label NPmodes, label NSUPmodes, label nNutModes, bool rbfInterp=true)
Project using a supremizer approach.
volScalarField computeNut_fromS(const volTensorField &S)
Compute turbulent viscosity Snapshot for a given tensor Field S.
static volTensorField computeS_fromU(const volVectorField &snapshotj)
Compute S deformation tensor for a given vector field U.
Eigen::Tensor< double, 3 > cTotalAveTensor
Turbulent total average viscosity tensor for the splitting approach.
Eigen::Tensor< double, 3 > turbulencePPEAveTensor1(label NUmodes, label NSUPmodes, label NPmodes)
ct1PPEAve added tensor for approximation of the averaged part of the eddy viscosity with the usage of...
Eigen::Tensor< double, 3 > turbulenceFluctTensor1(label NUmodes, label NSUPmodes)
ct1Fluct added tensor for approximation of the fluctuating part of the eddy viscosity
volScalarField computeSmagTermPhi_at_time(const word &snap_time, const volScalarField template_field_phi)
Compute Smagorinsky Snapshot of a tracer phi at a given time.
volScalarField computeSmagTermPhi_fromUPhi(const volVectorField &snapshotj, const volScalarField &phij)
Compute Smagorinsky Snapshot for given velocity field U and tracer phi.
volScalarField initNutFunction()
Initialize Nut term with values at time 0.
Eigen::Tensor< double, 3 > ct1PPEAveTensor
Turbulent average viscosity tensor for the splitting approach in the PPE equation.
Eigen::Tensor< double, 3 > ct1FluctTensor
Turbulent fluctuation viscosity tensor for the splitting approach.
Eigen::Tensor< double, 3 > turbulenceTensor2(label NUmodes, label NSUPmodes, label nNutModes)
ct2 added tensor for the turbulence treatement
Eigen::Tensor< double, 3 > turbulencePPEFluctTensor2(label NUmodes, label NSUPmodes, label NPmodes)
ct2PPEFluct added tensor for approximation of the fluctuating part of the eddy viscosity with the usa...
autoPtr< volScalarField > _nut
Eddy viscosity field.
label interChoice
Interpolation independent variable choice.
volScalarField computeNut_at_time(const word &snap_time, std::optional< PtrList< volVectorField > > modesU=std::nullopt)
Compute non linear Snapshot at a given time.
Eigen::MatrixXd btMatrix
Turbulent viscosity term.
volScalarModes nutModes
List of POD modes for eddy viscosity.
Eigen::Tensor< double, 3 > turbulenceFluctTensor2(label NUmodes, label NSUPmodes)
ct2Fluct added tensor for approximation of the fluctuating part of the eddy viscosity
volScalarField initSmagPhiFunction(const volScalarField template_field_phi)
Initialize Smagorinsky term of a tracer phi with values at time 0.
static volScalarField projDiffusionIBP(const volScalarField &coefDiff, const volVectorField &u, const volVectorField &v)
Compute projected diffusion term with the integration by parts (IBP) equation for a given vector fiel...
Eigen::Tensor< double, 3 > turbulencePPEAveTensor2(label NUmodes, label NSUPmodes, label NPmodes)
ct2PPEAve added tensor for approximation of the averaged part of the eddy viscosity with the usage of...
Eigen::Tensor< double, 3 > ct2FluctTensor
Turbulent fluctuation viscosity tensor for the splitting approach.
double e
RBF functions radius.
Eigen::Tensor< double, 3 > ct1AveTensor
Turbulent average viscosity tensor for the splitting approach.
Eigen::Tensor< double, 3 > ct2PPEFluctTensor
Turbulent fluctuation viscosity tensor for the splitting approach in the PPE equation.
PtrList< volScalarField > nutFields
List of snapshots for the solution for eddy viscosity.
volScalarField initProjSmagFromNutFunction()
Initialize projSmagFromNut with values at time 0.
static volScalarField diffusion(const T &coefDiff, const volScalarField &phi)
Compute diffusion term for a given scalar field phi.
label _pRefCell
Pressure reference cell.
volVectorField computeSmagTerm_at_time(const word &snap_time, std::optional< PtrList< volVectorField > > modesU=std::nullopt)
Compute Smagorinsky Snapshot at a given time.
List< Eigen::MatrixXd > velParCoeff(Eigen::MatrixXd A, Eigen::MatrixXd G)
A method to compute the two matrices needed for the RBF interpolation by combining the parameter samp...
volScalarField initProjSmagFunction()
Initialize projFullStressFunction with values at time 0.
Eigen::MatrixXd bTotalMatrix
Total B Matrix.
List< Eigen::MatrixXd > velDerivativeCoeff(Eigen::MatrixXd A, Eigen::MatrixXd G, Eigen::VectorXd initSnapInd, Eigen::VectorXd timeSnap)
A method to compute the two matrices needed for the RBF interpolation by combining the velocity L2 pr...
volScalarField computeProjSmagFromNut_at_time_fromModes(const word &snap_time, const volVectorField &modeU_proj, const volVectorField &modeU_grad)
Compute projSmagFromNut snapshot at a given time from 2 velocity modes.
label nNutModes
Number of viscoisty modes used for the projection.
Eigen::Tensor< double, 3 > ct2AveTensor
Turbulent average viscosity tensor for the splitting approach.
void computeProjSmagTerm_fromSmag_fromMode(volScalarField &phi, const volVectorField &Smag, const volVectorField &mode)
Compute projFullStressFunction given the Smagorinsky term and the velocity mode.
Eigen::Tensor< double, 3 > turbulencePPEFluctTensor1(label NUmodes, label NSUPmodes, label NPmodes)
ct1PPEFluct added tensor for approximation of the fluctuating part of the eddy viscosity with the usa...
void projectPPE(fileName folder, label NUmodes, label NPmodes, label NSUPmodes, label nNutModes, bool rbfInterp=true)
Project using the Poisson Equation for pressure.
Eigen::Tensor< double, 3 > turbulencePPETensor2(label NUmodes, label NSUPmodes, label NPmodes, label nNutModes)
ct2PPE added tensor for the turbulence treatement in the PPE method
Eigen::MatrixXd z
Time-parameter combined matrix.
Eigen::Tensor< double, 3 > turbulenceTensor1(label NUmodes, label NSUPmodes, label nNutModes)
ct1 added tensor for the turbulence treatement
Eigen::Tensor< double, 3 > ct2PPETensor
Turbulent viscosity tensor in the PPE equation.
volScalarField computeProjSmagTerm_at_time_fromMode(const word &snap_time, const volVectorField &mode)
Compute projFullStressFunction snapshot at a given time projected on the given mode.
Eigen::Tensor< double, 3 > cTotalPPEAveTensor
Turbulent total average viscosity tensor for the splitting approach in the PPE equation.
void computeNonLinearSnapshot_at_time(const word &snap_time, volVectorField &Smag, std::optional< PtrList< volVectorField > > modesU=std::nullopt)
Compute non linear Snapshot at a given time.
bool checkWrite(Time &timeObject)
Function to check if the solution must be exported.
scalar startTime
Start Time (initial time to start storing the snapshots).
scalar writeEvery
Time step of the writing procedure.
scalar timeStep
Time step of the simulation.
scalar nextWrite
Auxiliary variable to store the next writing instant.
scalar finalTime
Final time (final time of the simulation and consequently of the acquisition of the snapshots).
void writeMu(List< scalar > mu_now)
Write out a list of scalar corresponding to the parameters used in the truthSolve.
Eigen::MatrixXd mu_samples
Matrix of parameters to be used for PODI, where each row corresponds to a sample point....
label counter
Counter used for the output of the full order solutions.
bool offline
Boolean variable, it is 1 if the Offline phase has already been computed, else 0.
IOdictionary * ITHACAdict
dictionary to store input output infos
Eigen::MatrixXd mu
Row matrix of parameters.
autoPtr< argList > _args
argList
bool podex
Boolean variable, it is 1 if the POD has already been computed, else 0.
void truthSolve()
Perform a TruthSolve.
List< Eigen::MatrixXd > bcVelVec
Boundary term for penalty method - vector.
scalar maxIter
Number of maximum iterations to be done for the computation of the truth solution.
label NPmodes
Number of pressure modes used for the projection.
bool supex
Boolean variable to check the existence of the supremizer modes.
Eigen::MatrixXd BC1_matrix
PPE BC1.
Eigen::MatrixXd diffusive_term(label NUmodes, label NPmodes, label NSUPmodes)
Diffusive Term.
autoPtr< surfaceScalarField > _phi
Flux.
Eigen::MatrixXd BC3_matrix
PPE BC3.
Eigen::Tensor< double, 3 > C_tensor
Diffusion term.
PtrList< volScalarField > Pfield
List of pointers used to form the pressure snapshots matrix.
volVectorModes supmodes
List of pointers used to form the supremizer modes.
List< Eigen::MatrixXd > bcVelocityVec(label NUmodes, label NSUPmodes)
Boundary integral modes on boundary used by the penaly method.
autoPtr< fv::options > _fvOptions
fvOptions
autoPtr< Time > _runTime
Time.
volVectorModes Umodes
List of pointers used to form the velocity modes.
PtrList< volVectorField > Ufield
List of pointers used to form the velocity snapshots matrix.
Eigen::MatrixXd pressure_BC1(label NPmodes, label NUmodes)
Term N° 1 given by the additional boundary condition using a PPE approach.
scalar tolerance
Tolerance for the residual of the stationary problems, there is the same tolerance for velocity and p...
Eigen::MatrixXd mass_term(label NUmodes, label NPmodes, label NSUPmodes)
Mass Term.
autoPtr< fvMesh > _mesh
Mesh.
autoPtr< singlePhaseTransportModel > _laminarTransport
Laminar transport (used by turbulence model).
label NUmodes
Number of velocity modes used for the projection.
PtrList< volVectorField > liftfield
List of pointers used to form the list of lifting functions.
scalar pRefValue
Reference pressure value.
label pRefCell
Reference pressure cell.
volVectorModes L_U_SUPmodes
List of pointers containing the total number of lift, supremizer and velocity modes.
PtrList< volVectorField > Uomfield
List of pointers used to form the homogeneous velocity snapshots.
Eigen::MatrixXd pressure_BC3(label NPmodes, label NUmodes)
Term N° 3 given by the additional boundary condition using a PPE approach.
label NNutModesOut
Number of nut modes to be calculated.
Eigen::MatrixXd B_matrix
Diffusion term.
Eigen::MatrixXd D_matrix
Laplacian term PPE.
autoPtr< IOMRFZoneList > _MRF
MRF variable.
label NSUPmodes
Number of supremizer modes used for the projection.
Eigen::Tensor< double, 3 > gTensor
Divergence of momentum PPE.
label NNutModes
Number of nut modes used for the projection.
Eigen::MatrixXd K_matrix
Gradient of pressure matrix.
Eigen::Tensor< double, 3 > convective_term_tens(label NUmodes, label NPmodes, label NSUPmodes)
Export convective term as a tensor.
label NUmodesOut
Number of velocity modes to be calculated.
Eigen::Tensor< double, 3 > divMomentum(label NUmodes, label NPmodes)
Divergence of convective term (PPE approach).
Eigen::MatrixXd pressure_gradient_term(label NUmodes, label NPmodes, label NSUPmodes)
Gradient of pressure.
List< Eigen::MatrixXd > bcVelMat
Boundary term for penalty method - matrix.
Eigen::MatrixXd M_matrix
Mass Matrix.
Eigen::MatrixXd laplacian_pressure(label NPmodes)
Laplacian of pressure term (PPE approach).
label NPmodesOut
Number of pressure modes to be calculated.
List< Eigen::MatrixXd > bcVelocityMat(label NUmodes, label NSUPmodes)
Boundary integral modes on boundary used by the penaly method.
Eigen::Tensor< double, 3 > bc2Tensor
PPE BC2.
autoPtr< volVectorField > _U
Velocity field.
Eigen::Tensor< double, 3 > pressureBC2(label NPmodes, label NUmodes)
Term N° 2 given by the additional boundary condition using a PPE approach.
volScalarModes Pmodes
List of pointers used to form the pressure modes.
word bcMethod
Boundary Method.
autoPtr< volScalarField > _p
Pressure field.
autoPtr< incompressible::turbulenceModel > turbulence
Turbulence model.
autoPtr< pimpleControl > _pimple
pimpleControl
void ReadDenseMatrix(MatrixType &Matrix, word folder, word MatrixName)
Read a dense matrix from a binary format file.
void exportSolution(GeometricField< Type, PatchField, GeoMesh > &s, fileName subfolder, fileName folder, word fieldName)
Export a field to file in a certain folder and subfolder.
void exportMatrix(Eigen::Matrix< T, -1, dim > &matrix, word Name, word type, word folder)
Export the reduced matrices in numpy (type=python), matlab (type=matlab) and txt (type=eigen) format ...
void SaveDenseMatrix(MatrixType &Matrix, word folder, word MatrixName)
Save a dense matrix to a binary format file.
void ReadDenseTensor(TensorType &Tensor, word folder, word MatrixName)
Read a dense tensor from file.
List< Eigen::MatrixXd > readMatrix(word folder, word mat_name)
Read a three dimensional matrix from a txt file in Eigen format.
void exportTensor(Eigen::Tensor< T, 3 > tensor, word Name, word type, word folder)
Export the reduced tensor in numpy (tipo=python), matlab (tipo=matlab) and txt (tipo=eigen) format.
void SaveDenseTensor(TensorType &Tensor, word folder, word MatrixName)
Save a dense tensor to file.
Eigen::VectorXd getCoeffs(GeometricField< Type, PatchField, GeoMesh > &snapshot, PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, label Nmodes, bool consider_volumes)
Projects a snapshot on a basis function and gets the coefficients of the projection.
volTensorField tensorFieldProduct(const volScalarField &coef, const volTensorField &S)
Tensor field product between a volScalarField and a volTensorField.
bool containsSubstring(std::string contain, std::string contained)
Returns true if contained is a substring of contain, false otherwise.
T project_to_POD_basis(T &field, PtrList< T > &modes)
Compute the projection of a field in a POD basis.
bool check_pod()
Check if the POD data folder "./ITHACAoutput/POD" exists.
bool check_off()
Check if the offline data folder "./ITHACAoutput/Offline" exists.
bool check_folder(word folder)
Checks if a folder exists.
bool check_file(std::string fileName)
Function that returns true if a file exists.
bool check_sup()
Check if the supremizer folder exists.