Loading...
Searching...
No Matches
inverseLaplacianProblem_paramBC.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-------------------------------------------------------------------------------
12
13 License
14 This file is part of ITHACA-FV
15
16 ITHACA-FV is free software: you can redistribute it and/or modify
17 it under the terms of the GNU Lesser General Public License as published by
18 the Free Software Foundation, either version 3 of the License, or
19 (at your option) any later version.
20
21 ITHACA-FV is distributed in the hope that it will be useful,
22 but WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 GNU Lesser General Public License for more details.
25
26 You should have received a copy of the GNU Lesser General Public License
27 along with ITHACA-FV. If not, see <http://www.gnu.org/licenses/>.
28
29\*---------------------------------------------------------------------------*/
30
33
35
36// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * * //
37
38// Constructors
40
47
48// * * * * * * * * * * * * * * Full Order Methods * * * * * * * * * * * * * * //
49
51{
52 volScalarField& T = _T();
53 fvMesh& mesh = _mesh();
54
55 if (baseFuncType == "rbf")
56 {
57 Info << "Radial Basis Functions are used." << endl;
58 // The center of each function is the projection of each thermocouple
59 // on the boundary hotSide
60
62 {
64 }
65
69 {
70 gBaseFunctions[funcI].resize(T.boundaryField()[hotSide_ind].size());
71 scalar thermocoupleX = thermocouplesPos[funcI].x();
72 scalar thermocoupleZ = thermocouplesPos[funcI].z();
73 forAll (T.boundaryField()[hotSide_ind], faceI)
74 {
75 scalar faceX = mesh.boundaryMesh()[hotSide_ind].faceCentres()[faceI].x();
76 scalar faceZ = mesh.boundaryMesh()[hotSide_ind].faceCentres()[faceI].z();
77 scalar radius = Foam::sqrt((faceX - thermocoupleX) * (faceX - thermocoupleX) +
78 (faceZ - thermocoupleZ) * (faceZ - thermocoupleZ));
79 gBaseFunctions[funcI][faceI] = Foam::exp(- (shapeParameter *
81 * radius * radius));
82 }
83 }
84 }
85 else if (baseFuncType == "pod")
86 {
87 printf("At line number %d in file %s\n", __LINE__, __FILE__);
88 Info << "\nPod basis are not coded yet" << endl;
89 Info << "Exiting" << endl;
90 exit(101);
91 //Eigen::MatrixXd temp =
92 // ITHACAstream::readMatrix("./ITHACAoutput/podMarquardt/gReducedBases_mat.txt");
93 //gBaseFunctions.resize(temp.cols());
94 //gWeights.resize(temp.cols());
95 //forAll(gBaseFunctions, baseI)
96 //{
97 // gBaseFunctions[baseI].resize(temp.rows());
98 // forAll(gBaseFunctions[baseI], faceI)
99 // {
100 // gBaseFunctions[baseI][faceI] = temp(faceI, baseI);
101 // }
102 //}
103 }
104 else
105 {
106 printf("At line number %d in file %s\n", __LINE__, __FILE__);
107 Info << "\nBasis function type not known. It can be rbf or pod" << endl;
108 Info << "Exiting" << endl;
109 exit(102);
110 }
111}
112
114{
115 volScalarField& T = _T();
116 fvMesh& mesh = _mesh();
117 Eigen::MatrixXd gBaseFuncEigen;
118 set_gParametrized("rbf");
119
120 if (Nmodes == 0)
121 {
122 Info << "Selecting all modes." << endl;
123 Nmodes = gBaseFunctions.size();
124 }
125
126 gBaseFuncEigen.resize(gBaseFunctions[0].size(), gBaseFunctions.size());
127 Eigen::VectorXd faceAreaVect;
128 faceAreaVect.resize(mesh.magSf().boundaryField()[hotSide_ind].size());
129 forAll(gBaseFunctions, funcI)
130 {
131 forAll (T.boundaryField()[hotSide_ind], faceI)
132 {
133 if (funcI == 0)
134 {
135 faceAreaVect(faceI) = mesh.magSf().boundaryField()[hotSide_ind][faceI];
136 }
137
138 gBaseFuncEigen(faceI, funcI) = gBaseFunctions[funcI][faceI];
139 }
140 }
141
142 Eigen::MatrixXd correlationMatrix = gBaseFuncEigen.transpose() *
143 faceAreaVect.asDiagonal() * gBaseFuncEigen;
144 Eigen::JacobiSVD<Eigen::MatrixXd> svd(correlationMatrix,
145 Eigen::ComputeThinU | Eigen::ComputeThinV);
146 gPODmodes = svd.matrixU().leftCols(Nmodes);
147 Eigen::MatrixXd gBaseFuncEigen_new = gBaseFuncEigen * gPODmodes;
148 Info << "gBaseFuncEigen_new size = " << gBaseFuncEigen_new.cols() << ", " <<
149 gBaseFuncEigen_new.rows() << endl;
150 gBaseFunctions.resize(Nmodes);
151 gWeights.resize(Nmodes);
152 forAll(gBaseFunctions, funcI)
153 {
154 forAll (T.boundaryField()[hotSide_ind], faceI)
155 {
156 gBaseFunctions[funcI][faceI] = gBaseFuncEigen_new(faceI, funcI);
157 }
158 }
159}
160
162 scalar _shapeParameter)
163{
164 shapeParameter = _shapeParameter;
165 baseFuncType = _baseFuncType;
166 volScalarField& T = _T();
168 g.resize(T.boundaryField()[hotSide_ind].size(), 0.0);
169 forAll (gWeights, weigthI)
170 {
171 gWeights[weigthI] = 0; //-10000;
172 }
173
174 Info << "gWeights = " << gWeights << endl;
175 forAll (T.boundaryField()[hotSide_ind], faceI)
176 {
177 g[faceI] = 0.0;
178 forAll (gWeights, weigthI)
179 {
180 g[faceI] += gWeights[weigthI] * gBaseFunctions[weigthI][faceI];
181 }
182 }
183}
184
186{
187 M_Assert(weigths.size() == gBaseFunctions.size(),
188 "weigths size different from basis functions size");
189 volScalarField& T = _T();
190 forAll (T.boundaryField()[hotSide_ind], faceI)
191 {
192 g[faceI] = 0.0;
193 forAll (weigths, weigthI)
194 {
195 g[faceI] += weigths[weigthI] * gBaseFunctions[weigthI][faceI];
196 }
197 }
198}
199
201{
202 fvMesh& mesh = _mesh();
203 volScalarField& T(_T());
204 Tbasis.resize(0);
205 Tad_base.resize(0);
206 char recomputeOffline;
207
208 if (ITHACAutilities::check_file(folderOffline + "Theta_mat.txt") && force == 0)
209 {
210 do
211 {
212 metaData_offline metaData;
213 std::ifstream fin(folderOffline + "metaData.txt");
214 fin >> metaData.numberTC >> metaData.numberBasis >>
215 metaData.basisType >> metaData.shapeParameter;
216 fin.close();
217 std::cout << "\nOffline FOUND with parameter:\n" <<
218 "Number of thermocouples = " << metaData.numberTC <<
219 "\nNumber of basis functions = " << metaData.numberBasis <<
220 "\nType of basis functions = " << metaData.basisType <<
221 "\nRBF shape parameters = " << metaData.shapeParameter <<
222 "\n\nShould I recompute it? [y/n]" << std::endl;
223 std::cin >> recomputeOffline;
224 }
225 while (!cin.fail() && recomputeOffline != 'y' && recomputeOffline != 'n' );
226 }
227
228 if (recomputeOffline == 'y')
229 {
230 force = 1;
231 }
232
233 if (ITHACAutilities::check_file(folderOffline + "Theta_mat.txt") && force == 0)
234 {
235 volScalarField Tad(_T());
236 Tad.rename("Tad");
237 Info << "\nOffline already computed." << endl;
238 Info << "Check that the basis used for the parameterized BC are correct (RBF, POD, etc.)\n";
239 Theta = ITHACAstream::readMatrix(folderOffline + "Theta_mat.txt");
240 addSol = ITHACAstream::readMatrix(folderOffline + "addSol_mat.txt");
244 }
245 else
246 {
247 Info << "\nComputing offline" << endl;
248
250 {
251 mkDir(folderOffline);
252 }
253
254 metaData_offline metaData(Tmeas.size(), gWeights.size(), baseFuncType,
256 std::ofstream fout(folderOffline + "metaData.txt");
257 fout << metaData.numberTC << ' ' <<
258 metaData.numberBasis << ' ' <<
259 metaData.basisType << ' ' <<
260 metaData.shapeParameter << ' ';
261 fout.close();
264 M_Assert(Tmeas.size() > 0, "Initialize Tmeas");
265 M_Assert(gWeights.size() > 0, "Initialize gWeights");
266 Theta.resize(Tmeas.size(), gWeights.size());
267
268 for (label j = 0; j < Theta.cols(); j++)
269 {
270 gWeights = Foam::zero();
271 gWeights[j] = 1;
273 Info << "Solving for j = " << j << endl;
274 solveDirect();
275 volScalarField& T = _T();
276 Tbasis.append(T.clone());
278
279 for (label i = 0; i < Theta.rows(); i++)
280 {
281 Theta(i, j) = Tdirect(i) + addSol(i);
282 }
283
284 volScalarField gParametrizedField = list2Field(g);
285 ITHACAstream::exportSolution(gParametrizedField, std::to_string(j + 1),
287 "gParametrized");
288 }
289
292 Info << "\nOffline part ENDED\n" << endl;
293 }
294
295 Eigen::MatrixXd A = Theta.transpose() * Theta;
296 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A,
297 Eigen::ComputeThinU | Eigen::ComputeThinV);
298 Eigen::MatrixXd singularValues = svd.singularValues();
299
300 if (singularValues.minCoeff() > 0)
301 {
302 double conditionNumber = singularValues.maxCoeff() / singularValues.minCoeff();
303 Info << "Condition number = " << conditionNumber << endl;
304 }
305
306 ITHACAstream::exportMatrix(singularValues, "singularValues", "eigen",
308 offlineReady = 1;
309}
310
312 word linSys_solver,
313 double regPar)
314{
315 M_Assert(offlineReady, "Compute offline before running parameterizedBC.");
316 Info << endl << "Using quasilinearity of direct problem" << endl;
317 //parameterizedBCoffline(folder, forceOffline);
318 List<Eigen::MatrixXd> linSys;
319 linSys.resize(2);
320 Info << "Theta size = " << Theta.rows() << ", " << Theta.cols() << endl;
321 linSys[0] = Theta.transpose() * Theta;
322 linSys[1] = Theta.transpose() * (Tmeas + addSol);
323 Eigen::VectorXd weigths;
324
325 if (linSys_solver == "fullPivLU")
326 {
327 weigths = linSys[0].fullPivLu().solve(linSys[1]);
328 }
329 else if (linSys_solver == "jacobiSvd")
330 {
331 Eigen::JacobiSVD<Eigen::MatrixXd> svd(linSys[0],
332 Eigen::ComputeThinU | Eigen::ComputeThinV);
333 weigths = svd.solve(linSys[1]);
334 }
335 else if (linSys_solver == "householderQr")
336 {
337 weigths = linSys[0].householderQr().solve(linSys[1]);
338 }
339 else if (linSys_solver == "ldlt")
340 {
341 weigths = linSys[0].ldlt().solve(linSys[1]);
342 }
343 else if (linSys_solver == "inverse")
344 {
345 weigths = linSys[0].inverse() * linSys[1];
346 }
347 else if (linSys_solver == "TSVD")
348 {
349 weigths = ITHACAregularization::TSVD(linSys[0], linSys[1], int(regPar));
350 }
351 else if (linSys_solver == "Tikhonov")
352 {
353 Info << "WARNING: Tikhonov regularization does not work properly" << endl;
354 weigths = ITHACAregularization::Tikhonov(linSys[0], linSys[1], regPar);
355 }
356 else
357 {
358 printf("At line number %d in file %s\n", __LINE__, __FILE__);
359 Info << "Select a linear system solver in this list:" << endl
360 << "fullPivLU, jacobiSvd, householderQr, ldlt, inverse, TSVD" << endl;
361 Info << "Exiting." << endl;
362 exit(1);
363 }
364
366 return weigths;
367}
368
370 Eigen::VectorXd weigths)
371{
373 //std::cout << "Eigenvalues of Theta.transpose() * Theta are " << std::endl;
374 //std::cout << linSys[0].eigenvalues() << std::endl;
375 //Eigen::JacobiSVD<Eigen::MatrixXd> svd(linSys[0], Eigen::ComputeThinU | Eigen::ComputeThinV);
376 //std::cout << "Singular values of Theta.transpose() * Theta are " << std::endl;
377 //std::cout << svd.singularValues() << std::endl;
378 //std::cout << "debug: weigths size = " << std::endl;
379 //std::cout << weigths.size() << std::endl;
380 //
381 //residual = linSys[0] * weigths - linSys[1];
382 //std::cout << "Residual = " << std::endl;
383 //std::cout << residual << std::endl;
384 //std::cout << "Residual 2-norm = " << std::endl;
385 //std::cout << residual.squaredNorm() << std::endl;
386 gWeights.resize(weigths.size());
387 forAll(gWeights, weightI)
388 {
389 gWeights[weightI] = weigths(weightI);
390 }
391
393 reconstructT();
394 volScalarField& T = _T();
396 J = 0.5 * (Tdirect - Tmeas).dot(Tdirect - Tmeas);
397 Info << "J = " << J << endl;
398 Info << "End" << endl;
399 Info << endl;
400}
401
403{
404 restart();
405 Tad_base.resize(0);
406 fvMesh& mesh = _mesh();
407 simpleControl& simple = _simple();
408 volScalarField Tad(_T());
409 Foam::Time& runTime = _runTime();
411 List<scalar> RobinBC = - Tf;
412 forAll(mesh.boundaryMesh(), patchI)
413 {
414 if (patchI == mesh.boundaryMesh().findPatchID("coldSide"))
415 {
417 }
418 else if (patchI == mesh.boundaryMesh().findPatchID("hotSide"))
419 {
421 }
422 else
423 {
425 }
426 }
427
428#if defined(OFVER) && (OFVER == 6)
429
430 while (simple.loop(runTime))
431#else
432 while (simple.loop())
433#endif
434 {
435 while (simple.correctNonOrthogonal())
436 {
437 fvScalarMatrix TEqn
438 (
439 fvm::laplacian(DT, Tad)
440 );
441 TEqn.solve();
442 }
443 }
444
446 Tad_base.append(Tad.clone());
449 "Tad");
450}
451
453{
454 Info << "Reconstructing field T" << endl;
455 restart();
457 volScalarField Trec = Tbasis[0];
459 forAll(Tbasis, baseI)
460 {
461 Trec += gWeights[baseI] * (Tbasis[baseI] + Tad_base[0]);
462 }
463
464 Trec += - Tad_base[0];
465 volScalarField& T = _T();
466 T = Trec;
467}
forAll(example_CG.gList, solutionI)
Definition CGtest.H:21
Foam::fvMesh & mesh
Definition createMesh.H:47
Foam::Time & runTime
Definition createTime.H:33
#define M_Assert(Expr, Msg)
void update_gParametrized(List< scalar > weigths)
Update the boundary heat flux.
Eigen::VectorXd addSol
Solution of the additional problem at the thermocouples positions.
Eigen::VectorXd parameterizedBC(word linSys_solver="fullPivLU", double regPar=0)
Solve the online phase.
virtual void set_gBaseFunctions()
Define the base functions used for the parametrization of the heat flux g The center of each base fun...
Eigen::MatrixXd Theta
Theta matrix of the lynear system.
List< List< scalar > > gBaseFunctions
Basis of the heat flux parameterization.
virtual void solveAdditional()
Set BC the additional problem and solves it.
void parameterizedBCpostProcess(Eigen::VectorXd weigths)
Reconstruct the temperature field and compute the cost function J.
word baseFuncType
Type of basis functions used for the parameterization of the heat flux.
void set_gBaseFunctionsPOD(label Nmodes)
Performs POD on the RBF basis functions.
PtrList< volScalarField > Tbasis
Solutions of the direct problem with the basis of the parameterization as boundary heat flux.
List< scalar > gWeights
Weights of the heat flux parameterization.
void set_gParametrized(word baseFuncType, scalar _shapeParameter=1)
Set initial heat flux for the parameterized BC method.
void parameterizedBCoffline(bool force=0)
Performs offline computation for the parameterized BC method, if the offline directory "....
word folderOffline
Folder where the offline solutions and matrices are saved.
PtrList< volScalarField > Tad_base
Solution of the additional problem.
void reconstructT()
Reconstuct the field T using the offline computed fields.
Eigen::MatrixXd gPODmodes
Modes of the POD.
bool offlineReady
Flag to know if the offline phase was computed.
label hotSide_ind
Index of the hotSide patch.
dimensionedScalar DT
Dummy thermal conductivity with unitary value.
List< vector > thermocouplesPos
List containing the positions of the thermocouples.
List< scalar > Tf
Temperature at coldSide [K].
autoPtr< simpleControl > _simple
simpleControl
List< scalar > g
Heat flux at hotSide [W/m2].
bool thermocouplesRead
Flag to know if thermocouples file was read.
double J
Cost funtion [K^2].
Eigen::VectorXd Tdirect
Vector of computed temperatures at the thermocouples locations [K].
List< scalar > valueFraction
Value fraction for the Robin BC.
scalar homogeneousBC
Homogenerous BC.
volScalarField list2Field(List< scalar > list, scalar innerField=0.0)
Create a field with the hotSide boundary heat flux at the hotSide bounday cells for visualization.
Eigen::VectorXd Tmeas
Vector of measured temperatures at the thermocouples locations [K].
void set_valueFraction()
Set valueFraction list values for Robin condition.
autoPtr< fvMesh > _mesh
Mesh.
Eigen::VectorXd fieldValueAtThermocouples(volScalarField &field)
Interpolates the field value at the thermocouples points.
List< scalar > refGrad
Reference gradient for the Robin BC.
virtual void readThermocouples()
Identifies in the mesh the cells corresponding to the termocouples locations.
inverseLaplacianProblem()
Null constructor.
int thermocouplesNum
Number of thermocouples.
void solveDirect()
Solve direct problem.
autoPtr< volScalarField > _T
Temperature field.
volScalarField & T
Definition createT.H:46
Header file of the inverseLaplacianProblem_paramBC class.
fvScalarMatrix & TEqn
Definition TEqn.H:15
volScalarField & A
Eigen::VectorXd Tikhonov(Eigen::MatrixXd A, Eigen::MatrixXd b, double regularizationParameter)
Truncated Singular Value regularization.
Eigen::VectorXd TSVD(Eigen::MatrixXd A, Eigen::MatrixXd b, int filter)
Truncated Singular Value regularization.
void exportFields(PtrList< GeometricField< Type, PatchField, GeoMesh > > &field, word folder, word fieldname)
Function to export a scalar of vector field.
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 ...
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.
void assignMixedBC(GeometricField< Type, fvPatchField, volMesh > &field, label BC_ind, List< Type > &value, List< Type > &grad, List< scalar > &valueFrac)
Assign value of a boundary condition of type "mixed".
void assignIF(GeometricField< Type, fvPatchField, volMesh > &s, Type value)
Assign internal field.
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.
Info<< endl;Info<< "*********************************************************"<< endl;Info<< "Performing test for the parameterized BC inverse solver"<< endl;Info<< endl;word outputFolder="./ITHACAoutput/parameterizedBCtest_RBFparameter/";volScalarField gTrueField=example_paramBC.list2Field(example_paramBC.gTrue);ITHACAstream::exportSolution(gTrueField, "1", outputFolder, "gTrue");Eigen::VectorXd rbfWidth=EigenFunctions::ExpSpaced(0.001, 100, rbfWidthTest_size);ITHACAstream::exportMatrix(rbfWidth, "rbfShapeParameters", "eigen", outputFolder);Eigen::VectorXd residualNorms;residualNorms.resize(rbfWidthTest_size);Eigen::VectorXd heatFluxL2norm(rbfWidthTest_size);Eigen::VectorXd heatFluxLinfNorm=heatFluxL2norm;Eigen::VectorXd condNumber=heatFluxL2norm;Eigen::MatrixXd singVal;for(int i=0;i< rbfWidthTest_size;i++){ Info<< "*********************************************************"<< endl;Info<< "RBF parameter "<< rbfWidth(i)<< endl;Info<< "Test "<< i+1<< endl;Info<< endl;example_paramBC.set_gParametrized("rbf", rbfWidth(i));example_paramBC.parameterizedBCoffline(1);example_paramBC.parameterizedBC("fullPivLU");volScalarField gParametrizedField=example_paramBC.list2Field(example_paramBC.g);ITHACAstream::exportSolution(gParametrizedField, std::to_string(i+1), outputFolder, "gParametrized");volScalarField &T(example_paramBC._T());ITHACAstream::exportSolution(T, std::to_string(i+1), outputFolder, "T");residualNorms(i)=Foam::sqrt(example_paramBC.residual.squaredNorm());Eigen::MatrixXd A=example_paramBC.Theta.transpose() *example_paramBC.Theta;Eigen::JacobiSVD< Eigen::MatrixXd > svd(A, Eigen::ComputeThinU|Eigen::ComputeThinV)
Eigen::MatrixXd singularValues
double conditionNumber
simpleControl simple(mesh)
label i
Definition pEqn.H:46