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 Eigen::MatrixXd correlationMatrix = gBaseFuncEigen.transpose() *
142 faceAreaVect.asDiagonal() * gBaseFuncEigen;
143 Eigen::JacobiSVD<Eigen::MatrixXd> svd(correlationMatrix,
144 Eigen::ComputeThinU | Eigen::ComputeThinV);
145 gPODmodes = svd.matrixU().leftCols(Nmodes);
146 Eigen::MatrixXd gBaseFuncEigen_new = gBaseFuncEigen * gPODmodes;
147 Info << "gBaseFuncEigen_new size = " << gBaseFuncEigen_new.cols() << ", " <<
148 gBaseFuncEigen_new.rows() << endl;
149 gBaseFunctions.resize(Nmodes);
150 gWeights.resize(Nmodes);
151 forAll(gBaseFunctions, funcI)
152 {
153 forAll (T.boundaryField()[hotSide_ind], faceI)
154 {
155 gBaseFunctions[funcI][faceI] = gBaseFuncEigen_new(faceI, funcI);
156 }
157 }
158}
159
161 scalar _shapeParameter)
162{
163 shapeParameter = _shapeParameter;
164 baseFuncType = _baseFuncType;
165 volScalarField& T = _T();
167 g.resize(T.boundaryField()[hotSide_ind].size(), 0.0);
168 forAll (gWeights, weigthI)
169 {
170 gWeights[weigthI] = 0; //-10000;
171 }
172 Info << "gWeights = " << gWeights << endl;
173 forAll (T.boundaryField()[hotSide_ind], faceI)
174 {
175 g[faceI] = 0.0;
176 forAll (gWeights, weigthI)
177 {
178 g[faceI] += gWeights[weigthI] * gBaseFunctions[weigthI][faceI];
179 }
180 }
181}
182
184{
185 M_Assert(weigths.size() == gBaseFunctions.size(),
186 "weigths size different from basis functions size");
187 volScalarField& T = _T();
188 forAll (T.boundaryField()[hotSide_ind], faceI)
189 {
190 g[faceI] = 0.0;
191 forAll (weigths, weigthI)
192 {
193 g[faceI] += weigths[weigthI] * gBaseFunctions[weigthI][faceI];
194 }
195 }
196}
197
199{
200 fvMesh& mesh = _mesh();
201 volScalarField& T(_T());
202 Tbasis.resize(0);
203 Tad_base.resize(0);
204 char recomputeOffline;
205
206 if (ITHACAutilities::check_file(folderOffline + "Theta_mat.txt") && force == 0)
207 {
208 do
209 {
210 metaData_offline metaData;
211 std::ifstream fin(folderOffline + "metaData.txt");
212 fin >> metaData.numberTC >> metaData.numberBasis >>
213 metaData.basisType >> metaData.shapeParameter;
214 fin.close();
215 std::cout << "\nOffline FOUND with parameter:\n" <<
216 "Number of thermocouples = " << metaData.numberTC <<
217 "\nNumber of basis functions = " << metaData.numberBasis <<
218 "\nType of basis functions = " << metaData.basisType <<
219 "\nRBF shape parameters = " << metaData.shapeParameter <<
220 "\n\nShould I recompute it? [y/n]" << std::endl;
221 std::cin >> recomputeOffline;
222 }
223 while ( !cin.fail() && recomputeOffline != 'y' && recomputeOffline != 'n' );
224 }
225
226 if (recomputeOffline == 'y')
227 {
228 force = 1;
229 }
230
231 if (ITHACAutilities::check_file(folderOffline + "Theta_mat.txt") && force == 0)
232 {
233 volScalarField Tad(_T());
234 Tad.rename("Tad");
235 Info << "\nOffline already computed." << endl;
236 Info << "Check that the basis used for the parameterized BC are correct (RBF, POD, etc.)\n";
237 Theta = ITHACAstream::readMatrix(folderOffline + "Theta_mat.txt");
238 addSol = ITHACAstream::readMatrix(folderOffline + "addSol_mat.txt");
242 }
243 else
244 {
245 Info << "\nComputing offline" << endl;
246
248 {
249 mkDir(folderOffline);
250 }
251
252 metaData_offline metaData(Tmeas.size(), gWeights.size(), baseFuncType,
254 std::ofstream fout(folderOffline + "metaData.txt");
255 fout << metaData.numberTC << ' ' <<
256 metaData.numberBasis << ' ' <<
257 metaData.basisType << ' ' <<
258 metaData.shapeParameter << ' ';
259 fout.close();
262 M_Assert(Tmeas.size() > 0, "Initialize Tmeas");
263 M_Assert(gWeights.size() > 0, "Initialize gWeights");
264 Theta.resize(Tmeas.size(), gWeights.size());
265
266 for (label j = 0; j < Theta.cols(); j++)
267 {
268 gWeights = Foam::zero();
269 gWeights[j] = 1;
271 Info << "Solving for j = " << j << endl;
272 solveDirect();
273 volScalarField& T = _T();
274 Tbasis.append(T.clone());
276
277 for (label i = 0; i < Theta.rows(); i++)
278 {
279 Theta(i, j) = Tdirect(i) + addSol(i);
280 }
281
282 volScalarField gParametrizedField = list2Field(g);
283 ITHACAstream::exportSolution(gParametrizedField, std::to_string(j + 1),
285 "gParametrized");
286 }
287
290 Info << "\nOffline part ENDED\n" << endl;
291 }
292
293 Eigen::MatrixXd A = Theta.transpose() * Theta;
294 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A,
295 Eigen::ComputeThinU | Eigen::ComputeThinV);
296 Eigen::MatrixXd singularValues = svd.singularValues();
297
298 if (singularValues.minCoeff() > 0)
299 {
300 double conditionNumber = singularValues.maxCoeff() / singularValues.minCoeff();
301 Info << "Condition number = " << conditionNumber << endl;
302 }
303
304 ITHACAstream::exportMatrix(singularValues, "singularValues", "eigen",
306 offlineReady = 1;
307}
308
310 word linSys_solver,
311 double regPar)
312{
313 M_Assert(offlineReady, "Compute offline before running parameterizedBC.");
314 Info << endl << "Using quasilinearity of direct problem" << endl;
315 //parameterizedBCoffline(folder, forceOffline);
316 List<Eigen::MatrixXd> linSys;
317 linSys.resize(2);
318 Info << "Theta size = " << Theta.rows() << ", " << Theta.cols() << endl;
319 linSys[0] = Theta.transpose() * Theta;
320 linSys[1] = Theta.transpose() * (Tmeas + addSol);
321 Eigen::VectorXd weigths;
322
323 if (linSys_solver == "fullPivLU")
324 {
325 weigths = linSys[0].fullPivLu().solve(linSys[1]);
326 }
327 else if (linSys_solver == "jacobiSvd")
328 {
329 Eigen::JacobiSVD<Eigen::MatrixXd> svd(linSys[0],
330 Eigen::ComputeThinU | Eigen::ComputeThinV);
331 weigths = svd.solve(linSys[1]);
332 }
333 else if (linSys_solver == "householderQr")
334 {
335 weigths = linSys[0].householderQr().solve(linSys[1]);
336 }
337 else if (linSys_solver == "ldlt")
338 {
339 weigths = linSys[0].ldlt().solve(linSys[1]);
340 }
341 else if (linSys_solver == "inverse")
342 {
343 weigths = linSys[0].inverse() * linSys[1];
344 }
345 else if (linSys_solver == "TSVD")
346 {
347 weigths = ITHACAregularization::TSVD(linSys[0], linSys[1], int(regPar));
348 }
349 else if (linSys_solver == "Tikhonov")
350 {
351 Info << "WARNING: Tikhonov regularization does not work properly" << endl;
352 weigths = ITHACAregularization::Tikhonov(linSys[0], linSys[1], regPar);
353 }
354 else
355 {
356 printf("At line number %d in file %s\n", __LINE__, __FILE__);
357 Info << "Select a linear system solver in this list:" << endl
358 << "fullPivLU, jacobiSvd, householderQr, ldlt, inverse, TSVD" << endl;
359 Info << "Exiting." << endl;
360 exit(1);
361 }
362
364 return weigths;
365}
366
368 Eigen::VectorXd weigths)
369{
371 //std::cout << "Eigenvalues of Theta.transpose() * Theta are " << std::endl;
372 //std::cout << linSys[0].eigenvalues() << std::endl;
373 //Eigen::JacobiSVD<Eigen::MatrixXd> svd(linSys[0], Eigen::ComputeThinU | Eigen::ComputeThinV);
374 //std::cout << "Singular values of Theta.transpose() * Theta are " << std::endl;
375 //std::cout << svd.singularValues() << std::endl;
376 //std::cout << "debug: weigths size = " << std::endl;
377 //std::cout << weigths.size() << std::endl;
378 //
379 //residual = linSys[0] * weigths - linSys[1];
380 //std::cout << "Residual = " << std::endl;
381 //std::cout << residual << std::endl;
382 //std::cout << "Residual 2-norm = " << std::endl;
383 //std::cout << residual.squaredNorm() << std::endl;
384 gWeights.resize(weigths.size());
385 forAll(gWeights, weightI)
386 {
387 gWeights[weightI] = weigths(weightI);
388 }
390 reconstructT();
391 volScalarField& T = _T();
393 J = 0.5 * (Tdirect - Tmeas).dot(Tdirect - Tmeas);
394 Info << "J = " << J << endl;
395 Info << "End" << endl;
396 Info << endl;
397}
398
400{
401 restart();
402 Tad_base.resize(0);
403 fvMesh& mesh = _mesh();
404 simpleControl& simple = _simple();
405 volScalarField Tad(_T());
406 Foam::Time& runTime = _runTime();
408 List<scalar> RobinBC = - Tf;
409 forAll(mesh.boundaryMesh(), patchI)
410 {
411 if (patchI == mesh.boundaryMesh().findPatchID("coldSide"))
412 {
414 }
415 else if (patchI == mesh.boundaryMesh().findPatchID("hotSide"))
416 {
418 }
419 else
420 {
422 }
423 }
424#if defined(OFVER) && (OFVER == 6)
425
426 while (simple.loop(runTime))
427#else
428 while (simple.loop())
429#endif
430 {
431 while (simple.correctNonOrthogonal())
432 {
433 fvScalarMatrix TEqn
434 (
435 fvm::laplacian(DT, Tad)
436 );
437 TEqn.solve();
438 }
439 }
440
442 Tad_base.append(Tad.clone());
445 "Tad");
446}
447
449{
450 Info << "Reconstructing field T" << endl;
451 restart();
453 volScalarField Trec = Tbasis[0];
455 forAll(Tbasis, baseI)
456 {
457 Trec += gWeights[baseI] * (Tbasis[baseI] + Tad_base[0]);
458 }
459 Trec += - Tad_base[0];
460 volScalarField& T = _T();
461 T = Trec;
462}
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.
Implementation of a inverse Laplacian problem .
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.
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