Loading...
Searching...
No Matches
01simpleTurbGeomClosed.C
Go to the documentation of this file.
1/*---------------------------------------------------------------------------*\
2 ██╗████████╗██╗ ██╗ █████╗ ██████╗ █████╗ ███████╗██╗ ██╗
3 ██║╚══██╔══╝██║ ██║██╔══██╗██╔════╝██╔══██╗ ██╔════╝██║ ██║
4 ██║ ██║ ███████║███████║██║ ███████║█████╗█████╗ ██║ ██║
5 ██║ ██║ ██╔══██║██╔══██║██║ ██╔══██║╚════╝██╔══╝ ╚██╗ ██╔╝
6 ██║ ██║ ██║ ██║██║ ██║╚██████╗██║ ██║ ██║ ╚████╔╝
7 ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝ ╚═╝ ╚═══╝
8
9 * In real Time Highly Advanced Computational Applications for Finite Volumes
10 * Copyright (C) 2017 by the ITHACA-FV authors
11-------------------------------------------------------------------------------
12License
13 This file is part of ITHACA-FV
14 ITHACA-FV is free software: you can redistribute it and/or modify
15 it under the terms of the GNU Lesser General Public License as published by
16 the Free Software Foundation, either version 3 of the License, or
17 (at your option) any later version.
18 ITHACA-FV is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License
23 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
24Description
25 Example of turbulent steady NS Reduction Problem solved by the use of the SIMPLE algorithm
26SourceFiles
27 01simpleTurbGeomClosed.C
28\*---------------------------------------------------------------------------*/
29
30#include <torch/script.h>
31#include <torch/torch.h>
32#include "torch2Eigen.H"
33#include "SteadyNSSimple.H"
34#include "ITHACAstream.H"
35#include "ITHACAPOD.H"
37#include "forces.H"
38#include "IOmanip.H"
39#include "RBFMotionSolver.H"
40
41
42using namespace ITHACAtorch::torch2Eigen;
43
45{
46 public:
48 SteadyNSSimpleNN(int argc, char* argv[])
49 :
50 SteadyNSSimple(argc, argv)
51 {
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());
56 Net->push_back(torch::nn::Linear(64, NNutModes));
57 optimizer = new torch::optim::Adam(Net->parameters(),
58 torch::optim::AdamOptions(2e-2));
59 };
60
61 Eigen::MatrixXd bias_inp;
62 Eigen::MatrixXd scale_inp;
63 Eigen::MatrixXd bias_out;
64 Eigen::MatrixXd scale_out;
65
66 Eigen::MatrixXd coeffL2Nut;
67 Eigen::MatrixXd coeffL2U;
68
69 torch::Tensor coeffL2U_tensor;
70 torch::Tensor coeffL2Nut_tensor;
71
72 torch::nn::Sequential Net;
73 torch::optim::Optimizer* optimizer;
74 torch::jit::script::Module netTorchscript;
75
76 void loadNet(word filename)
77 {
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";
80 M_Assert(ITHACAutilities::check_file(filename), Msg.c_str());
81 netTorchscript = torch::jit::load(filename);
82 cnpy::load(bias_inp, "ITHACAoutput/NN/minAnglesInp_" + name(
83 NUmodes) + "_" + name(NNutModes) + ".npy");
84 cnpy::load(scale_inp, "ITHACAoutput/NN/scaleAnglesInp_" + name(
85 NUmodes) + "_" + name(NNutModes) + ".npy");
86 cnpy::load(bias_out, "ITHACAoutput/NN/minOut_" + name(NUmodes) + "_" + name(
87 NNutModes) + ".npy");
88 cnpy::load(scale_out, "ITHACAoutput/NN/scaleOut_" + name(NUmodes) + "_" + name(
89 NNutModes) + ".npy");
90 netTorchscript.eval();
91 }
92
93 // This function computes the coefficients which are later used for training
94 void getTurbNN()
95 {
96 if (!ITHACAutilities::check_folder("ITHACAoutput/NN/coeffs"))
97 {
98 mkDir("ITHACAoutput/NN/coeffs");
99 // Read Fields for Train
100 PtrList<volVectorField> UfieldTrain;
101 PtrList<volScalarField> PfieldTrain;
102 PtrList<volScalarField> nutFieldsTrain;
103 ITHACAstream::readMiddleFields(UfieldTrain, _U(),
104 "./ITHACAoutput/Offline/");
105 ITHACAstream::readMiddleFields(PfieldTrain, _p(),
106 "./ITHACAoutput/Offline/");
107 auto nut_train = _mesh().lookupObject<volScalarField>("nut");
108 ITHACAstream::readMiddleFields(nutFieldsTrain, nut_train,
109 "./ITHACAoutput/Offline/");
111 std::cout << "Computing the coefficients for U train" << std::endl;
112 Eigen::MatrixXd coeffL2U_train = ITHACAutilities::getCoeffs(UfieldTrain,
113 Umodes,
114 0, true);
115 std::cout << "Computing the coefficients for p train" << std::endl;
116 Eigen::MatrixXd coeffL2P_train = ITHACAutilities::getCoeffs(PfieldTrain,
117 Pmodes,
118 0, true);
119 std::cout << "Computing the coefficients for nuT train" << std::endl;
120 Eigen::MatrixXd coeffL2Nut_train = ITHACAutilities::getCoeffs(nutFieldsTrain,
121 nutModes,
122 0, true);
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");
129 // Read Fields for Test
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");
139 ITHACAstream::readMiddleFields(nutFieldsTest, nut_test,
140 "./ITHACAoutput/checkOff/");
141 // Compute the coefficients for test
142 Eigen::MatrixXd coeffL2U_test = ITHACAutilities::getCoeffs(UfieldTest,
143 Umodes,
144 0, true);
145 Eigen::MatrixXd coeffL2P_test = ITHACAutilities::getCoeffs(PfieldTest,
146 Pmodes,
147 0, true);
148 Eigen::MatrixXd coeffL2Nut_test = ITHACAutilities::getCoeffs(nutFieldsTest,
149 nutModes,
150 0, true);
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");
157 }
158 }
159
160 Eigen::MatrixXd evalNet(Eigen::MatrixXd a, double mu_now)
161 {
162 Eigen::MatrixXd xpred(a.rows() + 1, 1);
163
164 if (xpred.cols() != 1)
165 {
166 throw std::runtime_error("Predictions for more than one sample not supported yet.");
167 }
168
169 xpred.bottomRows(a.rows()) = a;
170 xpred(0, 0) = mu_now;
171 xpred = xpred.array() * scale_inp.array() + bias_inp.array() ;
172 xpred.transposeInPlace();
173 torch::Tensor xTensor = eigenMatrix2torchTensor(xpred);
174 torch::Tensor out;
175 std::vector<torch::jit::IValue> XTensorInp;
176 XTensorInp.push_back(xTensor);
177 out = netTorchscript.forward(XTensorInp).toTensor();
178 Eigen::MatrixXd g = torchTensor2eigenMatrix<double>(out);
179 g.transposeInPlace();
180 g = (g.array() - bias_out.array()) / scale_out.array();
181 return g;
182 }
183
184 // Function to eval the NN once the input is provided
185 Eigen::MatrixXd evalNet(Eigen::MatrixXd a)
186 {
187 netTorchscript.eval();
188 a.transposeInPlace();
189 a = (a.array() - bias_inp.array()) / scale_inp.array();
190 torch::Tensor aTensor = eigenMatrix2torchTensor(a);
191 torch::Tensor out;// = Net->forward(aTensor);
192 std::vector<torch::jit::IValue> XTensorInp;
193 XTensorInp.push_back(aTensor);
194 out = netTorchscript.forward(XTensorInp).toTensor();
195 Eigen::MatrixXd g = torchTensor2eigenMatrix<double>(out);
196 g = g.array() * scale_out.array() + bias_out.array();
197 g.transposeInPlace();
198 return g;
199 }
200};
201
203{
204 public:
207 :
208 problem(&FOMproblem)
209 {}
210
213
214 // Function to perform the online phase
215 void solveOnline_Simple(scalar mu_now,
216 int NmodesUproj, int NmodesPproj, int NmodesNut = 0,
217 word Folder = "./ITHACAoutput/Reconstruct/")
218 {
219 counter++;
220
221 // For all the variables, in case one wants to use all the available modes it is just necessary to set
222 // the requested number into the ITHACAdict to zero
223 if (NmodesUproj == 0)
224 {
225 NmodesUproj = problem->Umodes.size();
226 }
227
228 if (NmodesPproj == 0)
229 {
230 NmodesPproj = problem->Pmodes.size();
231 }
232
233 if (NmodesNut == 0)
234 {
235 NmodesNut = problem->nutModes.size();
236 }
237
238 // Initializations
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 =
253 problem->para->ITHACAdict->lookupOrDefault<float>("residualJumpLim", 1e-5);
254 float normalizedResidualLim =
255 problem->para->ITHACAdict->lookupOrDefault<float>("normalizedResidualLim",
256 1e-5);
257 scalar residual_jump(1 + residualJumpLim);
258 volScalarField& P = problem->_p();
259 volVectorField& U = problem->_U();
260 volScalarField& nut = const_cast<volScalarField&>
261 (problem->_mesh().lookupObject<volScalarField>("nut"));
262 volVectorField u2 = U;
263 a0 = ITHACAutilities::getCoeffs(U, problem->Umodes, NmodesUproj, true);
264 b = ITHACAutilities::getCoeffs(P, problem->Pmodes, NmodesPproj, true);
265 nutCoeff = ITHACAutilities::getCoeffs(nut, problem->nutModes, NmodesNut, true);
266 a(0) = a0(0); // Do not remove: it is not working without this condition
267 b = b0;
268 fvMesh& mesh = problem->_mesh();
269 Time& runTime = problem->_runTime();
270 P.rename("p");
271 surfaceScalarField& phi(problem->_phi());
272 problem->Umodes.reconstruct(U, a, "U");
273 problem->Pmodes.reconstruct(P, b, "p");
274 vector v(1, 0, 0);
276 //problem->nutModes.reconstruct(nut, nutCoeff, "nut");
277 phi = fvc::flux(U);
278 int iter = 0;
279 simpleControl& simple = problem->_simple();
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);
284
285 // SIMPLE algorithm starts here
286 while ((residual_jump > residualJumpLim
287 || std::max(U_norm_res, P_norm_res) > normalizedResidualLim) &&
288 iter < maxIterOn)
289 {
290 iter++;
291 std::cout << iter << std::endl;
292#if defined(OFVER) && (OFVER == 6)
293 simple.loop(runTime);
294#else
295 problem->_simple().loop();
296#endif
297
298 // If the case is turbulent, then the network is evaluated
300 {
301 nutCoeff = problem->evalNet(a, mu_now);
302 //nutCoeff = nutCoeffOld + 0.7*(nutCoeff - nutCoeffOld);
303 volScalarField& nut = const_cast<volScalarField&>
304 (problem->_mesh().lookupObject<volScalarField>("nut"));
305 problem->nutModes.reconstruct(nut, nutCoeff, "nut");
306 //ITHACAstream::exportSolution(nut, name(counter), Folder);
307 }
308
309 volScalarField nueff = problem->turbulence->nuEff();
310 vector v(1, 0, 0);
312 // Momentum equation
313 fvVectorMatrix UEqn
314 (
315 fvm::div(phi, U)
316 - fvm::laplacian(nueff, U)
317 - fvc::div(nueff * dev2(T(fvc::grad(U))))
318 );
319 UEqn.relax();
320 //solve(UEqn == - fvc::grad(P));
321 List<Eigen::MatrixXd> RedLinSysU = problem->Umodes.project(UEqn, NmodesUproj);
322 volVectorField gradPfull = -fvc::grad(P);
323 Eigen::MatrixXd projGrad = problem->Umodes.project(gradPfull, NmodesUproj);
324 RedLinSysU[1] = RedLinSysU[1] + projGrad;
325 a = reducedProblem::solveLinearSys(RedLinSysU, a, uresidual);
326 problem->Umodes.reconstruct(U, a, "U");
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));
331 adjustPhi(phiHbyA, U, P);
332 tmp<volScalarField> rAtU(rAU);
333
334 if (simple.consistent())
335 {
336 rAtU = 1.0 / (1.0 / rAU - UEqn.H1());
337 phiHbyA +=
338 fvc::interpolate(rAtU() - rAU) * fvc::snGrad(P) * mesh.magSf();
339 HbyA -= (rAU - rAtU()) * fvc::grad(P);
340 }
341
342 List<Eigen::MatrixXd> RedLinSysP;
343 bOld = b;
344
345 while (simple.correctNonOrthogonal())
346 {
347 // Continuity equation
348 fvScalarMatrix pEqn
349 (
350 fvm::laplacian(rAtU(), P) == fvc::div(phiHbyA)
351 );
352 RedLinSysP = problem->Pmodes.project(pEqn, NmodesPproj);
353 //pEqn.solve();
354 b = reducedProblem::solveLinearSys(RedLinSysP, b, presidual);
355 problem->Pmodes.reconstruct(P, b, "p");
356
357 if (simple.finalNonOrthogonalIter())
358 {
359 phi = phiHbyA - pEqn.flux();
360 }
361 }
362
363 b = bOld + mesh.fieldRelaxationFactor("p") * (b - bOld);
364 problem->Pmodes.reconstruct(P, b, "p");
365 nutCoeffOld = nutCoeff;
366 // P.relax();
367 U = HbyA - rAtU() * fvc::grad(P);
368 U.correctBoundaryConditions();
369 uresidualOld = uresidualOld - uresidual;
370 presidualOld = presidualOld - presidual;
371 uresidualOld = uresidualOld.cwiseAbs();
372 presidualOld = presidualOld.cwiseAbs();
373 residual_jump = std::max(uresidualOld.sum(), presidualOld.sum());
374 uresidualOld = uresidual;
375 presidualOld = presidual;
376 uresidual = uresidual.cwiseAbs();
377 presidual = presidual.cwiseAbs();
378 U_norm_res = uresidual.sum() / (RedLinSysU[1].cwiseAbs()).sum();
379 P_norm_res = presidual.sum() / (RedLinSysP[1].cwiseAbs()).sum();
380
381 if (problem->para->debug)
382 {
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 <<
387 std::endl;
388 std::cout << "Final normalized residual for pressure: " << P_norm_res <<
389 std::endl;
390 }
391
392 res_os_U << U_norm_res << std::endl;
393 res_os_P << P_norm_res << std::endl;
394 }
395
396 res_os_U.close();
397 res_os_P.close();
398 std::cout << "Solution " << counter << " converged in " << iter <<
399 " iterations." << std::endl;
400 std::cout << "Final normalized residual for velocity: " << U_norm_res <<
401 std::endl;
402 std::cout << "Final normalized residual for pressure: " << P_norm_res <<
403 std::endl;
404 problem->Umodes.reconstruct(U, a, "Uaux");
405 problem->Pmodes.reconstruct(P, b, "Paux");
406
408 {
409 volScalarField& nut = const_cast<volScalarField&>
410 (problem->_mesh().lookupObject<volScalarField>("nut"));
411 nut.rename("nutAux");
413 }
414
415 ITHACAstream::exportSolution(U, name(counter), Folder);
416 ITHACAstream::exportSolution(P, name(counter), Folder);
417 runTime.setTime(runTime.startTime(), 0);
418 }
419};
420
422{
423 public:
425 explicit tutorial01cl(int argc, char* argv[])
426 :
427 SteadyNSSimpleNN(argc, argv)
428 {
429 curX = _mesh().points();
430 point0 = _mesh().points();
431 }
432
434 vectorField point0;
436 List<vector> curX;
437
439 void offlineSolve(Eigen::MatrixXd Box, List<label> patches,
440 word folder = "./ITHACAoutput/Offline/")
441 {
442 Vector<double> inl(0, 0, 0);
443 List<scalar> mu_now(1);
444 volVectorField& U = _U();
445 volScalarField& p = _p();
446
447 // if the offline solution is already performed read the fields
449 !ITHACAutilities::check_folder("./ITHACAoutput/POD/1"))
450 {
453 auto nut = _mesh().lookupObject<volScalarField>("nut");
455 }
456 else if (offline && !ITHACAutilities::check_folder("./ITHACAoutput/POD/1"))
457 {
460 }
461 else if (!offline)
462 {
463 //Vector<double> Uinl(1, 0, 0);
464 for (label i = 0; i < mu.rows(); i++)
465 {
466 _mesh().movePoints(point0);
467 List<vector> points2Move;
468 labelList boxIndices = ITHACAutilities::getIndicesFromBox(_mesh(), patches, Box,
469 points2Move);
470 mu_now[0] = mu(i, 0);
471 linearMovePts(mu_now[0], points2Move);
472
473 for (int j = 0; j < boxIndices.size(); j++)
474 {
475 curX[boxIndices[j]] = points2Move[j];
476 }
477
478 Field<vector> curXV(curX);
479 _mesh().movePoints(curXV);
480 ITHACAstream::writePoints(_mesh().points(), folder,
481 name(i + 1) + "/polyMesh/");
482 //assignIF(U, Uinl);
483 truthSolve2(mu_now, folder);
484 int middleF = 1;
485
486 while (ITHACAutilities::check_folder(folder + name(
487 i + 1) + "/" + name(middleF)))
488 {
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);
493 system(command);
494 std::cout.clear();
495 middleF++;
496 }
497
498 restart();
499 }
500 }
501 }
502
503 void linearMovePts(double angle, List<vector>& points2Move)
504 {
505 double sMax;
506 scalarList x;
507 scalarList y;
508
509 for (label i = 0; i < points2Move.size(); i++)
510 {
511 x.append(points2Move[i].component(0));
512 y.append(points2Move[i].component(1));
513 }
514
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);
520
521 for (label i = 0; i < points2Move.size(); i++)
522 {
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;
526 }
527 }
528};
529
530int main(int argc, char* argv[])
531{
532 // Construct the tutorial object
533 tutorial01cl example(argc, argv);
534 // Read some parameters from file
536 example._runTime());
537 // Read the files where the parameters are stored
538 std::ifstream exFileOff("./angOff_mat.txt");
539
540 if (exFileOff)
541 {
542 example.mu = ITHACAstream::readMatrix("./angOff_mat.txt");
543 }
544 else
545 {
546 example.mu = Eigen::VectorXd::LinSpaced(50, 0, 75);
547 ITHACAstream::exportMatrix(example.mu, "angOff", "eigen", "./");
548 }
549
550 Eigen::MatrixXd angOn;
551 std::ifstream exFileOn("./angOn_mat.txt");
552
553 if (exFileOn)
554 {
555 angOn = ITHACAstream::readMatrix("./angOn_mat.txt");
556 }
557 else
558 {
559 //angOn = Eigen::VectorXd::LinSpaced(20, 5, 70);
560 angOn = ITHACAutilities::rand(10, 1, 0, 70);
561 ITHACAstream::exportMatrix(angOn, "angOn", "eigen", "./");
562 }
563
564 //Set the box including the step
565 Eigen::MatrixXd Box(2, 3);
566 Box << 1.98, 0.01, 0.11,
567 7.02, -0.666669, -0.01;
568 //Select the patches to be moved
569 List<label> movPat;
570 movPat.append(3);
571 movPat.append(5);
572 // Set the maximum iterations number for the offline phase
573 example.maxIter = para->ITHACAdict->lookupOrDefault<int>("maxIter", 2000);
574 // Perform the offline solve
575 example.offlineSolve(Box, movPat);
576 List<vector> points2Move;
577 labelList boxIndices = ITHACAutilities::getIndicesFromBox(example._mesh(),
578 movPat, Box,
579 points2Move);
580 example.linearMovePts((example.mu.maxCoeff() + example.mu.minCoeff()) / 2,
581 points2Move);
582
583 for (int j = 0; j < boxIndices.size(); j++)
584 {
585 example.curX[boxIndices[j]] = points2Move[j];
586 }
587
588 Field<vector> curXV(example.curX);
589 example._mesh().movePoints(curXV);
590 // Perform POD on velocity and pressure and store the first 10 modes
591 ITHACAPOD::getModes(example.Ufield, example.Umodes, example._U().name(),
592 example.podex, 0, 0,
593 example.NUmodesOut);
594 ITHACAPOD::getModes(example.Pfield, example.Pmodes, example._p().name(),
595 example.podex, 0, 0,
596 example.NPmodesOut);
597 // Error analysis
598 tutorial01cl checkOff(argc, argv);
599 std::clock_t startOff;
600 double durationOff;
601 startOff = std::clock();
602
603 if (!ITHACAutilities::check_folder("./ITHACAoutput/checkOff"))
604 {
605 checkOff.restart();
607 checkOff._runTime());
608 checkOff.offline = false;
609 checkOff.mu = angOn;
610 checkOff.offlineSolve(Box, movPat, "./ITHACAoutput/checkOff/");
611 checkOff.offline = true;
612 }
613
614 durationOff = (std::clock() - startOff);
615
617 {
618 ITHACAPOD::getModes(example.nutFields, example.nutModes, "nut",
619 example.podex, 0, 0, example.NNutModesOut);
620 // Create the RBF for turbulence
621 example.getTurbNN();
622 }
623
624 std::string wrng =
625 "The network for this problem has not been calculated yet. Perform the Python training (see train.py).";
626 M_Assert(ITHACAutilities::check_file("ITHACAoutput/NN/Net_" + name(
627 example.NUmodes) + "_" + name(
628 example.NNutModes) + ".pt"), wrng.c_str());
629 example.loadNet("ITHACAoutput/NN/Net_" + name(example.NUmodes) + "_" + name(
630 example.NNutModes) + ".pt");
631 example._mesh().movePoints(example.point0);
632 // Create the reduced object
633 reducedSimpleSteadyNN reduced(example);
634 PtrList<volVectorField> U_rec_list;
635 PtrList<volScalarField> P_rec_list;
636 // Reads inlet volocities boundary conditions.
637 word vel_file(para->ITHACAdict->lookup("online_velocities"));
638 Eigen::MatrixXd vel = ITHACAstream::readMatrix(vel_file);
639 // Set the maximum iterations number for the online phase
640 reduced.maxIterOn = para->ITHACAdict->lookupOrDefault<int>("maxIterOn", 2000);
641 std::cout << "Total amout of parameters to be solved online: " + name(
642 angOn.rows()) << std::endl;
643 //Perform the online solutions
644 std::clock_t startOn;
645 double durationOn;
646 startOn = std::clock();
647
648 for (label k = 0; k < angOn.rows(); k++)
649 {
650 std::cout << "Solving online for parameter number " + name(k + 1) << std::endl;
651 scalar mu_now = angOn(k, 0);
652 example.restart();
653 reduced.vel_now = vel;
654
656 {
657 example._mesh().movePoints(example.point0);
658 List<vector> points2Move;
659 labelList boxIndices = ITHACAutilities::getIndicesFromBox(example._mesh(),
660 movPat, Box, points2Move);
661 example.linearMovePts(mu_now, points2Move);
662
663 for (int j = 0; j < boxIndices.size(); j++)
664 {
665 example.curX[boxIndices[j]] = points2Move[j];
666 }
667
668 Field<vector> curXV(example.curX);
669 example._mesh().movePoints(curXV);
670 ITHACAstream::writePoints(example._mesh().points(),
671 "./ITHACAoutput/Reconstruct_" + name(example.NUmodes) + "_" + name(
672 example.NPmodes) + "/", name(k + 1) + "/polyMesh/");
673 reduced.solveOnline_Simple(mu_now, example.NUmodes, example.NPmodes,
674 example.NNutModes, "./ITHACAoutput/Reconstruct_" + name(
675 example.NUmodes) + "_" + name(example.NPmodes) + "/");
676 }
677 else
678 {
679 example._mesh().movePoints(example.point0);
680 List<vector> points2Move;
681 labelList boxIndices = ITHACAutilities::getIndicesFromBox(example._mesh(),
682 movPat, Box, points2Move);
683 example.linearMovePts(mu_now, points2Move);
684
685 for (int j = 0; j < boxIndices.size(); j++)
686 {
687 example.curX[boxIndices[j]] = points2Move[j];
688 }
689
690 Field<vector> curXV(example.curX);
691 example._mesh().movePoints(curXV);
692 ITHACAstream::writePoints(example._mesh().points(),
693 "./ITHACAoutput/Reconstruct_" + name(example.NUmodes) + "_" + name(
694 example.NPmodes) + "/", name(k + 1) + "/polyMesh/");
695 reduced.solveOnline_Simple(mu_now, example.NUmodes, example.NPmodes,
696 example.NNutModes, "./ITHACAoutput/Reconstruct_" + name(
697 example.NUmodes) + "_" + name(example.NPmodes) + "/");
698 }
699 }
700
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());
709 ITHACAstream::readConvergedFields(Ufull, checkOff._U(),
710 "./ITHACAoutput/checkOff/");
711 ITHACAstream::readConvergedFields(Pfull, checkOff._p(),
712 "./ITHACAoutput/checkOff/");
713 ITHACAstream::read_fields(Ured, Uaux,
714 "./ITHACAoutput/Reconstruct_" + name(example.NUmodes) + "_" + name(
715 example.NPmodes) + "/");
716 ITHACAstream::read_fields(Pred, Paux,
717 "./ITHACAoutput/Reconstruct_" + name(example.NUmodes) + "_" + name(
718 example.NPmodes) + "/");
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));
722
723 for (label k = 0; k < Ufull.size(); k++)
724 {
725 volVectorField errorU = (Ufull[k] - Ured[k]).ref();
726 volVectorField devU = (Ufull[k] - U_fs).ref();
727 volScalarField errorP = (Pfull[k] - Pred[k]).ref();
728 relErrorU(k, 0) = ITHACAutilities::frobNorm(errorU) /
730 relErrorP(k, 0) = ITHACAutilities::frobNorm(errorP) /
732 }
733
735 "errorU_" + name(example.NUmodes) + "_" + name(example.NPmodes) + "_" + name(
736 example.NNutModes), "python", ".");
738 "errorP_" + name(example.NUmodes) + "_" + name(example.NPmodes) + "_" + name(
739 example.NNutModes), "python", ".");
740 std::cout << "The online phase duration is equal to " << durationOn <<
741 std::endl;
742 std::cout << "The offline phase duration is equal to " << durationOff <<
743 std::endl;
744 exit(0);
745}
int main(int argc, char *argv[])
fvScalarMatrix pEqn
Definition CFM.H:31
Header file of the ITHACAPOD class.
Foam::fvMesh & mesh
Definition createMesh.H:47
Foam::Time & runTime
Definition createTime.H:33
#define M_Assert(Expr, Msg)
Header file of the ITHACAstream class, it contains the implementation of several methods for input ou...
scalar uresidual
scalar presidual
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...
Definition Modes.C:275
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.
Definition Modes.C:63
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.
Definition steadyNS.H:125
void restart()
set U and P back to the values into the 0 folder
Definition steadyNS.C:2253
label NPmodes
Number of pressure modes used for the projection.
Definition steadyNS.H:143
autoPtr< surfaceScalarField > _phi
Flux.
Definition steadyNS.H:293
autoPtr< simpleControl > _simple
simpleControl
Definition steadyNS.H:284
PtrList< volScalarField > Pfield
List of pointers used to form the pressure snapshots matrix.
Definition steadyNS.H:86
autoPtr< Time > _runTime
Time.
Definition steadyNS.H:290
volVectorModes Umodes
List of pointers used to form the velocity modes.
Definition steadyNS.H:101
PtrList< volVectorField > Ufield
List of pointers used to form the velocity snapshots matrix.
Definition steadyNS.H:89
autoPtr< fvMesh > _mesh
Mesh.
Definition steadyNS.H:281
label NUmodes
Number of velocity modes used for the projection.
Definition steadyNS.H:140
ITHACAparameters * para
Definition steadyNS.H:82
label NNutModesOut
Number of nut modes to be calculated.
Definition steadyNS.H:137
label NNutModes
Number of nut modes used for the projection.
Definition steadyNS.H:149
autoPtr< incompressible::turbulenceModel > turbulence
Turbulence model.
Definition steadyNS.H:299
label NUmodesOut
Number of velocity modes to be calculated.
Definition steadyNS.H:128
label NPmodesOut
Number of pressure modes to be calculated.
Definition steadyNS.H:131
autoPtr< volVectorField > _U
Velocity field.
Definition steadyNS.H:263
volScalarModes Pmodes
List of pointers used to form the pressure modes.
Definition steadyNS.H:98
autoPtr< volScalarField > _p
Pressure field.
Definition steadyNS.H:260
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.
volScalarField & T
Definition createT.H:46
volScalarField & v
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.
Definition ITHACAPOD.C:93
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.
Definition torch2Eigen.C:39
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)
surfaceScalarField & phi
volVectorField & U
volScalarField & nut
dimensionedVector & g
fvVectorMatrix & UEqn
Definition UEqn.H:37
volScalarField & p
adjustPhi(phiHbyA, U, p)
tmp< volScalarField > rAtU(rAU)
surfaceScalarField phiHbyA("phiHbyA", fvc::flux(HbyA))
volVectorField HbyA(constrainHbyA(rAU *UEqn.H(), U, p))
label i
Definition pEqn.H:46
volScalarField rAU(1.0/UEqn.A())
Header file of the torch2Eigen namespace.