30#include <torch/script.h>
31#include <torch/torch.h>
52 Net->push_back(torch::nn::Linear(
NUmodes, 128));
53 Net->push_back(torch::nn::ReLU());
54 Net->push_back(torch::nn::Linear(128, 64));
55 Net->push_back(torch::nn::ReLU());
58 torch::optim::AdamOptions(2e-2));
72 torch::nn::Sequential
Net;
78 std::string Msg = filename +
79 " is not existing, please run the training stage of the net with the correct number of modes for U and Nut";
98 mkDir(
"ITHACAoutput/NN/coeffs");
100 PtrList<volVectorField> UfieldTrain;
101 PtrList<volScalarField> PfieldTrain;
102 PtrList<volScalarField> nutFieldsTrain;
104 "./ITHACAoutput/Offline/");
106 "./ITHACAoutput/Offline/");
107 auto nut_train =
_mesh().lookupObject<volScalarField>(
"nut");
109 "./ITHACAoutput/Offline/");
111 std::cout <<
"Computing the coefficients for U train" << std::endl;
115 std::cout <<
"Computing the coefficients for p train" << std::endl;
119 std::cout <<
"Computing the coefficients for nuT train" << std::endl;
123 coeffL2U_train.transposeInPlace();
124 coeffL2P_train.transposeInPlace();
125 coeffL2Nut_train.transposeInPlace();
126 cnpy::save(coeffL2U_train,
"ITHACAoutput/NN/coeffs/coeffL2UTrain.npy");
127 cnpy::save(coeffL2P_train,
"ITHACAoutput/NN/coeffs/coeffL2PTrain.npy");
128 cnpy::save(coeffL2Nut_train,
"ITHACAoutput/NN/coeffs/coeffL2NutTrain.npy");
130 PtrList<volVectorField> UfieldTest;
131 PtrList<volScalarField> PfieldTest;
132 PtrList<volScalarField> nutFieldsTest;
135 "./ITHACAoutput/checkOff/");
137 "./ITHACAoutput/checkOff/");
138 auto nut_test =
_mesh().lookupObject<volScalarField>(
"nut");
140 "./ITHACAoutput/checkOff/");
151 coeffL2U_test.transposeInPlace();
152 coeffL2P_test.transposeInPlace();
153 coeffL2Nut_test.transposeInPlace();
154 cnpy::save(coeffL2U_test,
"ITHACAoutput/NN/coeffs/coeffL2UTest.npy");
155 cnpy::save(coeffL2P_test,
"ITHACAoutput/NN/coeffs/coeffL2PTest.npy");
156 cnpy::save(coeffL2Nut_test,
"ITHACAoutput/NN/coeffs/coeffL2NutTest.npy");
160 Eigen::MatrixXd
evalNet(Eigen::MatrixXd a,
double mu_now)
162 Eigen::MatrixXd xpred(a.rows() + 1, 1);
164 if (xpred.cols() != 1)
166 throw std::runtime_error(
"Predictions for more than one sample not supported yet.");
169 xpred.bottomRows(a.rows()) = a;
170 xpred(0, 0) = mu_now;
172 xpred.transposeInPlace();
175 std::vector<torch::jit::IValue> XTensorInp;
176 XTensorInp.push_back(xTensor);
179 g.transposeInPlace();
188 a.transposeInPlace();
192 std::vector<torch::jit::IValue> XTensorInp;
193 XTensorInp.push_back(aTensor);
197 g.transposeInPlace();
216 int NmodesUproj,
int NmodesPproj,
int NmodesNut = 0,
217 word Folder =
"./ITHACAoutput/Reconstruct/")
223 if (NmodesUproj == 0)
228 if (NmodesPproj == 0)
239 Eigen::VectorXd uresidualOld = Eigen::VectorXd::Zero(NmodesUproj);
240 Eigen::VectorXd presidualOld = Eigen::VectorXd::Zero(NmodesPproj);
241 Eigen::VectorXd
uresidual = Eigen::VectorXd::Zero(NmodesUproj);
242 Eigen::VectorXd
presidual = Eigen::VectorXd::Zero(NmodesPproj);
243 scalar U_norm_res(1);
244 scalar P_norm_res(1);
245 Eigen::MatrixXd a = Eigen::VectorXd::Zero(NmodesUproj);
246 Eigen::MatrixXd a0 = Eigen::VectorXd::Zero(NmodesUproj);
247 Eigen::MatrixXd b = Eigen::VectorXd::Zero(NmodesPproj);
248 Eigen::MatrixXd b0 = Eigen::VectorXd::Zero(NmodesPproj);
249 Eigen::MatrixXd bOld = b;
250 Eigen::MatrixXd nutCoeff = Eigen::VectorXd::Zero(NmodesNut);
251 Eigen::MatrixXd nutCoeffOld = Eigen::VectorXd::Zero(NmodesNut);
252 float residualJumpLim =
254 float normalizedResidualLim =
257 scalar residual_jump(1 + residualJumpLim);
260 volScalarField&
nut =
const_cast<volScalarField&
>
262 volVectorField u2 =
U;
280 std::ofstream res_os_U;
281 std::ofstream res_os_P;
282 res_os_U.open(Folder + name(
counter) +
"/residualsU", std::ios_base::app);
283 res_os_P.open(Folder + name(
counter) +
"/residualsP", std::ios_base::app);
286 while ((residual_jump > residualJumpLim
287 || std::max(U_norm_res, P_norm_res) > normalizedResidualLim) &&
291 std::cout << iter << std::endl;
292#if defined(OFVER) && (OFVER == 6)
303 volScalarField&
nut =
const_cast<volScalarField&
>
316 - fvm::laplacian(nueff,
U)
317 - fvc::div(nueff * dev2(
T(fvc::grad(
U))))
322 volVectorField gradPfull = -fvc::grad(P);
324 RedLinSysU[1] = RedLinSysU[1] + projGrad;
328 volScalarField
rAU(1.0 /
UEqn.A());
329 volVectorField
HbyA(constrainHbyA(1.0 /
UEqn.A() *
UEqn.H(),
U, P));
330 surfaceScalarField
phiHbyA(
"phiHbyA", fvc::flux(
HbyA));
338 fvc::interpolate(
rAtU() -
rAU) * fvc::snGrad(P) *
mesh.magSf();
342 List<Eigen::MatrixXd> RedLinSysP;
345 while (
simple.correctNonOrthogonal())
357 if (
simple.finalNonOrthogonalIter())
363 b = bOld +
mesh.fieldRelaxationFactor(
"p") * (b - bOld);
365 nutCoeffOld = nutCoeff;
368 U.correctBoundaryConditions();
371 uresidualOld = uresidualOld.cwiseAbs();
372 presidualOld = presidualOld.cwiseAbs();
373 residual_jump = std::max(uresidualOld.sum(), presidualOld.sum());
378 U_norm_res =
uresidual.sum() / (RedLinSysU[1].cwiseAbs()).sum();
379 P_norm_res =
presidual.sum() / (RedLinSysP[1].cwiseAbs()).sum();
383 std::cout <<
"Residual jump = " << residual_jump << std::endl;
384 std::cout <<
"Normalized residual = " << std::max(U_norm_res,
385 P_norm_res) << std::endl;
386 std::cout <<
"Final normalized residual for velocity: " << U_norm_res <<
388 std::cout <<
"Final normalized residual for pressure: " << P_norm_res <<
392 res_os_U << U_norm_res << std::endl;
393 res_os_P << P_norm_res << std::endl;
398 std::cout <<
"Solution " <<
counter <<
" converged in " << iter <<
399 " iterations." << std::endl;
400 std::cout <<
"Final normalized residual for velocity: " << U_norm_res <<
402 std::cout <<
"Final normalized residual for pressure: " << P_norm_res <<
409 volScalarField&
nut =
const_cast<volScalarField&
>
411 nut.rename(
"nutAux");
440 word folder =
"./ITHACAoutput/Offline/")
442 Vector<double> inl(0, 0, 0);
443 List<scalar> mu_now(1);
444 volVectorField&
U =
_U();
445 volScalarField&
p =
_p();
453 auto nut =
_mesh().lookupObject<volScalarField>(
"nut");
464 for (label
i = 0;
i <
mu.rows();
i++)
467 List<vector> points2Move;
470 mu_now[0] =
mu(
i, 0);
473 for (
int j = 0; j < boxIndices.size(); j++)
475 curX[boxIndices[j]] = points2Move[j];
478 Field<vector> curXV(
curX);
479 _mesh().movePoints(curXV);
481 name(
i + 1) +
"/polyMesh/");
487 i + 1) +
"/" + name(middleF)))
489 word command(
"ln -s $(readlink -f " + folder + name(
490 i + 1) +
"/polyMesh/) " + folder + name(
i + 1) +
"/" + name(
491 middleF) +
"/" +
" >/dev/null 2>&1");
492 std::cout.setstate(std::ios_base::failbit);
509 for (label
i = 0;
i < points2Move.size();
i++)
511 x.append(points2Move[
i].component(0));
512 y.append(points2Move[
i].component(1));
515 double xMin = min(x);
516 double xMax = max(x);
517 double yMin = min(y);
518 double yMax = max(y);
519 sMax = (yMax - yMin) * std::tan(M_PI * angle / 180);
521 for (label
i = 0;
i < points2Move.size();
i++)
523 points2Move[
i].component(0) = points2Move[
i].component(0) +
524 (yMax - points2Move[
i].component(1)) / (yMax - yMin) * (xMax -
525 points2Move[
i].component(0)) / (xMax - xMin) * sMax;
530int main(
int argc,
char* argv[])
538 std::ifstream exFileOff(
"./angOff_mat.txt");
546 example.
mu = Eigen::VectorXd::LinSpaced(50, 0, 75);
550 Eigen::MatrixXd angOn;
551 std::ifstream exFileOn(
"./angOn_mat.txt");
565 Eigen::MatrixXd Box(2, 3);
566 Box << 1.98, 0.01, 0.11,
567 7.02, -0.666669, -0.01;
576 List<vector> points2Move;
583 for (
int j = 0; j < boxIndices.size(); j++)
585 example.
curX[boxIndices[j]] = points2Move[j];
588 Field<vector> curXV(example.
curX);
589 example.
_mesh().movePoints(curXV);
599 std::clock_t startOff;
601 startOff = std::clock();
610 checkOff.
offlineSolve(Box, movPat,
"./ITHACAoutput/checkOff/");
614 durationOff = (std::clock() - startOff);
625 "The network for this problem has not been calculated yet. Perform the Python training (see train.py).";
628 example.
NNutModes) +
".pt"), wrng.c_str());
629 example.
loadNet(
"ITHACAoutput/NN/Net_" + name(example.
NUmodes) +
"_" + name(
634 PtrList<volVectorField> U_rec_list;
635 PtrList<volScalarField> P_rec_list;
637 word vel_file(para->
ITHACAdict->lookup(
"online_velocities"));
641 std::cout <<
"Total amout of parameters to be solved online: " + name(
642 angOn.rows()) << std::endl;
644 std::clock_t startOn;
646 startOn = std::clock();
648 for (label k = 0; k < angOn.rows(); k++)
650 std::cout <<
"Solving online for parameter number " + name(k + 1) << std::endl;
651 scalar mu_now = angOn(k, 0);
658 List<vector> points2Move;
660 movPat, Box, points2Move);
663 for (
int j = 0; j < boxIndices.size(); j++)
665 example.
curX[boxIndices[j]] = points2Move[j];
668 Field<vector> curXV(example.
curX);
669 example.
_mesh().movePoints(curXV);
671 "./ITHACAoutput/Reconstruct_" + name(example.
NUmodes) +
"_" + name(
672 example.
NPmodes) +
"/", name(k + 1) +
"/polyMesh/");
674 example.
NNutModes,
"./ITHACAoutput/Reconstruct_" + name(
680 List<vector> points2Move;
682 movPat, Box, points2Move);
685 for (
int j = 0; j < boxIndices.size(); j++)
687 example.
curX[boxIndices[j]] = points2Move[j];
690 Field<vector> curXV(example.
curX);
691 example.
_mesh().movePoints(curXV);
693 "./ITHACAoutput/Reconstruct_" + name(example.
NUmodes) +
"_" + name(
694 example.
NPmodes) +
"/", name(k + 1) +
"/polyMesh/");
696 example.
NNutModes,
"./ITHACAoutput/Reconstruct_" + name(
701 durationOn = (std::clock() - startOn);
702 std::cout <<
"ONLINE PHASE COMPLETED" << std::endl;
703 PtrList<volVectorField> Ufull;
704 PtrList<volScalarField> Pfull;
705 PtrList<volVectorField> Ured;
706 PtrList<volScalarField> Pred;
707 volVectorField Uaux(
"Uaux", checkOff.
_U());
708 volScalarField Paux(
"Paux", checkOff.
_p());
710 "./ITHACAoutput/checkOff/");
712 "./ITHACAoutput/checkOff/");
714 "./ITHACAoutput/Reconstruct_" + name(example.
NUmodes) +
"_" + name(
717 "./ITHACAoutput/Reconstruct_" + name(example.
NUmodes) +
"_" + name(
719 Eigen::MatrixXd relErrorU(Ufull.size(), 1);
720 Eigen::MatrixXd relErrorP(Pfull.size(), 1);
721 dimensionedVector U_fs(
"U_fs", dimVelocity, vector(1, 0, 0));
723 for (label k = 0; k < Ufull.size(); k++)
725 volVectorField errorU = (Ufull[k] - Ured[k]).ref();
726 volVectorField devU = (Ufull[k] - U_fs).ref();
727 volScalarField errorP = (Pfull[k] - Pred[k]).ref();
735 "errorU_" + name(example.
NUmodes) +
"_" + name(example.
NPmodes) +
"_" + name(
738 "errorP_" + name(example.
NUmodes) +
"_" + name(example.
NPmodes) +
"_" + name(
740 std::cout <<
"The online phase duration is equal to " << durationOn <<
742 std::cout <<
"The offline phase duration is equal to " << durationOff <<
int main(int argc, char *argv[])
Header file of the ITHACAPOD class.
#define M_Assert(Expr, Msg)
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
Header file of the reducedSteadyNS class.
Header file of the steadyNS class.
Class for the definition of some general parameters, the parameters must be defined from the file ITH...
IOdictionary * ITHACAdict
Dictionary for input objects from file.
static ITHACAparameters * getInstance()
Gets an instance of ITHACAparameters, to be used if the instance is already existing.
GeometricField< Type, PatchField, GeoMesh > reconstruct(GeometricField< Type, PatchField, GeoMesh > &inputField, Eigen::MatrixXd Coeff, word Name)
Function to reconstruct the solution starting from the coefficients, in this case the field is passed...
List< Eigen::MatrixXd > project(fvMatrix< Type > &Af, label numberOfModes=0, word projType="G")
A function that project an FvMatrix (OpenFoam linear System) on the modes.
Eigen::MatrixXd scale_inp
torch::nn::Sequential Net
torch::Tensor coeffL2U_tensor
Eigen::MatrixXd coeffL2Nut
SteadyNSSimpleNN(int argc, char *argv[])
Constructor.
torch::optim::Optimizer * optimizer
Eigen::MatrixXd scale_out
torch::Tensor coeffL2Nut_tensor
torch::jit::script::Module netTorchscript
void loadNet(word filename)
Eigen::MatrixXd evalNet(Eigen::MatrixXd a, double mu_now)
Eigen::MatrixXd evalNet(Eigen::MatrixXd a)
Implementation of a parametrized full order steady NS problem and preparation of the the reduced ma...
void truthSolve2(List< scalar > mu_now, word Folder="./ITHACAoutput/Offline/")
Offline solver for the whole Navier-Stokes problem.
volScalarModes nutModes
List of POD modes for eddy viscosity.
PtrList< volScalarField > nutFields
List of snapshots for the solution for eddy viscosity.
static Eigen::MatrixXd solveLinearSys(List< Eigen::MatrixXd > LinSys, Eigen::MatrixXd x, Eigen::VectorXd &residual, const Eigen::MatrixXd &bc=Eigen::MatrixXd::Zero(0, 0), const std::string solverType="fullPivLu")
Linear system solver for the online problem.
reducedSimpleSteadyNN(SteadyNSSimpleNN &FOMproblem)
Constructor.
SteadyNSSimpleNN * problem
Full problem.
void solveOnline_Simple(scalar mu_now, int NmodesUproj, int NmodesPproj, int NmodesNut=0, word Folder="./ITHACAoutput/Reconstruct/")
Class where it is implemented a reduced problem for the steady Navier-stokes problem.
int maxIterOn
Maximum iterations number for the online step.
Eigen::MatrixXd vel_now
Imposed boundary conditions.
bool offline
Boolean variable, it is 1 if the Offline phase has already been computed, else 0.
Eigen::MatrixXd mu
Row matrix of parameters.
bool podex
Boolean variable, it is 1 if the POD has already been computed, else 0.
scalar maxIter
Number of maximum iterations to be done for the computation of the truth solution.
void restart()
set U and P back to the values into the 0 folder
label NPmodes
Number of pressure modes used for the projection.
autoPtr< surfaceScalarField > _phi
Flux.
autoPtr< simpleControl > _simple
simpleControl
PtrList< volScalarField > Pfield
List of pointers used to form the pressure snapshots matrix.
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.
autoPtr< fvMesh > _mesh
Mesh.
label NUmodes
Number of velocity modes used for the projection.
label NNutModesOut
Number of nut modes to be calculated.
label NNutModes
Number of nut modes used for the projection.
autoPtr< incompressible::turbulenceModel > turbulence
Turbulence model.
label NUmodesOut
Number of velocity modes to be calculated.
label NPmodesOut
Number of pressure modes to be calculated.
autoPtr< volVectorField > _U
Velocity field.
volScalarModes Pmodes
List of pointers used to form the pressure modes.
autoPtr< volScalarField > _p
Pressure field.
List< vector > curX
List to store the moved coordinates.
void linearMovePts(double angle, List< vector > &points2Move)
vectorField point0
Initial coordinates of the grid points.
tutorial01cl(int argc, char *argv[])
Constructor.
void offlineSolve(Eigen::MatrixXd Box, List< label > patches, word folder="./ITHACAoutput/Offline/")
Perform an Offline solve.
void getModes(PtrList< GeometricField< Type, PatchField, GeoMesh > > &snapshots, PtrList< GeometricField< Type, PatchField, GeoMesh > > &modes, word fieldName, bool podex, bool supex, bool sup, label nmodes, bool correctBC)
Computes the bases or reads them for a field.
void writePoints(pointField points, fileName folder, fileName subfolder)
Write points of a mesh to a file.
void readConvergedFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &Lfield, GeometricField< Type, PatchField, GeoMesh > &field, fileName casename)
Function to read a list of volVectorField from name of the field including only converged snapshots.
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 readMiddleFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &Lfield, GeometricField< Type, PatchField, GeoMesh > &field, fileName casename)
Funtion to read a list of volVectorField from name of the field including all the intermediate snapsh...
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 ...
List< Eigen::MatrixXd > readMatrix(word folder, word mat_name)
Read a three dimensional matrix from a txt file in Eigen format.
void read_fields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &Lfield, word Name, fileName casename, int first_snap, int n_snap)
Function to read a list of fields from the name of the field and casename.
torch::Tensor eigenMatrix2torchTensor(Eigen::Matrix< type, Eigen::Dynamic, Eigen::Dynamic > _eigenMatrix)
Convert an eigen Matrix to a torch tensor.
template Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > torchTensor2eigenMatrix< double >(torch::Tensor &torchTensor)
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.
double frobNorm(GeometricField< Type, PatchField, GeoMesh > &field)
Evaluate the Frobenius norm of a field.
Eigen::MatrixXd rand(label rows, label cols, double min, double max)
Generates random matrix with random values in an interval.
bool isTurbulent()
This function checks if the case is turbulent.
void assignBC(GeometricField< scalar, fvPatchField, volMesh > &s, label BC_ind, double value)
Assign uniform Boundary Condition to a volScalarField.
bool check_folder(word folder)
Checks if a folder exists.
bool check_file(std::string fileName)
Function that returns true if a file exists.
labelList getIndicesFromBox(const fvMesh &mesh, List< label > indices, Eigen::MatrixXd Box, List< vector > &points2Move)
Gives the indices conteined into a defined box.
void save(const Eigen::Matrix< T, -1, dim > &mat, const std::string fname)
Eigen::Matrix< T, -1, dim > load(Eigen::Matrix< T, -1, dim > &mat, const std::string fname, std::string order="rowMajor")
simpleControl simple(mesh)
tmp< volScalarField > rAtU(rAU)
surfaceScalarField phiHbyA("phiHbyA", fvc::flux(HbyA))
volVectorField HbyA(constrainHbyA(rAU *UEqn.H(), U, p))
volScalarField rAU(1.0/UEqn.A())
Header file of the torch2Eigen namespace.