Loading...
Searching...
No Matches
02enKF_1DinverseHeatTransfer.H
Go to the documentation of this file.
1#ifndef EnKF_1DinverseHeatTransfer_H
2#define EnKF_1DinverseHeatTransfer_H
3#include "simpleControl.H"
4#include "fvOptions.H"
5
6
11{
12 public:
13 explicit EnKF_1DinverseHeatTransfer(int argc, char* argv[], int Nseeds_)
14 :
15 laplacianProblem(argc, argv)
16 {
17 fvMesh& mesh = _mesh();
18 _simple = autoPtr<simpleControl>
19 (
20 new simpleControl
21 (
22 mesh
23 )
24 );
25 simpleControl& simple = _simple();
26 Time& runTime = _runTime();
27#include "createFvOptions.H"
28 left_ind = mesh.boundaryMesh().findPatchID("left");
29 Nseeds = Nseeds_;
30 Tensemble = PtrList<volScalarField>(Nseeds);
31 volScalarField& T(_T());
32 stateSize = T.size();
33 priorSamples = Eigen::MatrixXd::Zero(stateSize, Nseeds);
35 startTime = runTime.startTime().value();
36 deltaTime = runTime.deltaTValue();
37 endTime = runTime.endTime().value();
39 Info << "startTime = " << startTime << endl;
40 Info << "endTime = " << endTime << endl;
41 Info << "deltaTime = " << deltaTime << endl;
42 Info << "Ntimes = " << Ntimes << endl;
43 timeVector.resize(Ntimes);
44 probe_mean.resize(Nprobes, Ntimes);
48 }
49
51 autoPtr<simpleControl> _simple;
52 autoPtr<fv::options> _fvOptions;
54 double k;
56 double rho;
58 double Cp;
60 label left_ind;
61 Eigen::MatrixXd measurements;
65 int Nseeds;
66
68 PtrList<volScalarField> Tensemble;
70 PtrList<volScalarField> Tmean;
72
73 std::shared_ptr<muq::Modeling::Gaussian> priorDensity;
74 std::shared_ptr<muq::Modeling::Gaussian> modelErrorDensity;
75 std::shared_ptr<muq::Modeling::Gaussian> measNoiseDensity;
76 double meas_cov;
77
78 Eigen::MatrixXd priorSamples;
79 Eigen::MatrixXd posteriorSamples;
80
81 double startTime;
82 double deltaTime;
83 double endTime;
84 int Ntimes;
85
87 Eigen::VectorXd timeVector;
89 int Nprobes = 1;
91 Foam::vector probePosition = Foam::vector(0.5, 0.1, 0.005);
92 Eigen::MatrixXd probe_true;
93 Eigen::MatrixXd probe_mean;
94 Eigen::MatrixXd probe_MaxConfidence;
95 Eigen::MatrixXd probe_minConfidence;
96
98 int sampleI = 0;
99 int sampleFlag = 0;
100
103 double updateBC(bool reconstruction = 0)
104 {
105 Time& runTime = _runTime();
106 scalar time = runTime.value();
107 double BC = time * 5 + 2;
108
109 if (reconstruction)
110 {
111 BC = time * 5 + 0;
112 }
113
114 return BC;
115 }
116
119 {
120 samplingTimeI = 0;
121 sampleI = 0;
122 sampleFlag = 0;
123 }
124
126 Eigen::VectorXd observe(volScalarField field)
127 {
128 fvMesh& mesh = _mesh();
129 Time& runTime = _runTime();
130 IOdictionary measurementsDict
131 (
132 IOobject
133 (
134 "measurementsDict",
135 runTime.constant(),
136 mesh,
137 IOobject::MUST_READ,
138 IOobject::NO_WRITE
139 )
140 );
141 List<vector> measurementPoints(measurementsDict.lookup("positions"));
142 Eigen::VectorXd measures(measurementPoints.size());
143 forAll(measurementPoints, pntI)
144 {
145 //TODO
146 //add check if I put two measurements on the same cell
147 measures(pntI) = field[mesh.findCell(measurementPoints[pntI])];
148 }
149
150 return measures;
151 }
152
154 Eigen::MatrixXd solve(volScalarField& T, word outputFolder,
155 word outputFieldName, bool reconstruction = 0)
156 {
157 Eigen::MatrixXd obsMat;
158 fvMesh& mesh = _mesh();
159 Foam::Time& runTime = _runTime();
160 simpleControl& simple = _simple();
161 fv::options& fvOptions(_fvOptions());
162 dimensionedScalar diffusivity("diffusivity", dimensionSet(0, 2, -1, 0, 0, 0, 0),
163 k / (rho * Cp));
164 Info << "Thermal diffusivity = " << diffusivity << " m2/s" << endl;
165 int timeI = 0;
166
167 while (runTime.loop())
168 {
169 scalar time = runTime.value();
170
171 if (!reconstruction)
172 {
173 sampleFlag++;
174 timeVector(timeI) = time;
175 timeI++;
176 }
177
178 // Update BC
179 ITHACAutilities::assignBC(T, mesh.boundaryMesh().findPatchID("left"),
180 updateBC(reconstruction));
181
182 // Solve
183 while (simple.correctNonOrthogonal())
184 {
185 fvScalarMatrix TEqn
186 (
187 fvm::ddt(T) - fvm::laplacian(diffusivity, T)
188 );
189 fvOptions.constrain(TEqn);
190 TEqn.solve();
191 fvOptions.correct(T);
192 }
193
194 if (reconstruction)
195 {
196 //Adding model error
197 forAll(T.internalField(), cellI)
198 {
199 T.ref()[cellI] += modelErrorDensity->Sample()(cellI);
200 }
201 }
202 else
203 {
204 probe_true.col(timeI - 1) = sampleField(T, probePosition);
205 }
206
208 outputFolder,
209 outputFieldName);
210
212 {
213 Info << "Sampling at time = " << runTime.timeName() << nl << endl;
214 obsMat.conservativeResize(observe(T).size(), obsMat.cols() + 1);
215 obsMat.col(sampleI) = observe(T);
216
217 if (!reconstruction)
218 {
219 sampleFlag = 0;
220 sampleI++;
221 }
222 }
223
224 runTime.write();
225 }
226
227 if (!reconstruction)
228 {
229 ITHACAstream::exportMatrix(timeVector, "timeVector", "eigen", outputFolder);
230 ITHACAstream::exportMatrix(probe_true, "probe_true", "eigen", outputFolder);
231 }
232
233 return obsMat;
234 }
235
238 {
239 Info << "\n****************************************\n" << endl;
240 Info << "\nPerforming true solution\n" << endl;
241 word outputFolder = "./ITHACAoutput/direct/";
242 restart();
243 volScalarField& T(_T());
245 measurements = solve(T, outputFolder, "Tdirect");
246 ITHACAstream::exportMatrix(measurements, "trueMeasurements", "eigen",
247 outputFolder);
248 std::cout << "Number of samples in time = " << measurements.cols() << std::endl;
249 std::cout << "Number of sample in space = " << measurements.rows() << std::endl;
251 Info << "\nEND true solution\n" << endl;
252 Info << "\n****************************************\n" << endl;
253 }
254
255
258 {
259 restart();
260 Time& runTime = _runTime();
262 std::vector<Eigen::MatrixXd> observationTensor;
263 word outputFolder = "ITHACAoutput/reconstuction";
264 Tmean.resize(Ntimes);
265 Info << "\n****************************************\n" << endl;
266 Info << "\nStarting reconstruction\n" << endl;
267 int samplesCounter = 0;
268 // Read true field
269 PtrList<volScalarField> Ttrue;
270 ITHACAstream::read_fields(Ttrue, "Tdirect",
271 "ITHACAoutput/direct/");
272
273 for (int timeI = 0; timeI < Ntimes; timeI++)
274 {
275 double initialTime = timeI * deltaTime + startTime;
276 Info << "\n\nTime " << initialTime + deltaTime << endl;
277 Eigen::MatrixXd forecastOutput = forecastStep(initialTime, timeI,
278 initialTime + deltaTime);
279
280 if (forecastOutput.cols() > 0)
281 {
282 // This is a sampling step
283 samplesCounter++;
284 observationTensor.push_back(forecastOutput);
285 sampleFlag = 0;
286 Eigen::VectorXd meas = measurements.col(samplesCounter - 1);
287 // Kalman filter
289 Eigen::MatrixXd::Identity(meas.size(), meas.size()) * meas_cov, forecastOutput);
290
291 for (int i = 0; i < Nseeds; i++)
292 {
293 restart();
294 volScalarField& T = _T();
295 Eigen::VectorXd internalField = posteriorSamples.col(i);
296 assignIF(T, internalField);
297 Tensemble.Foam::PtrList<volScalarField>::set(i, T.clone());
298 }
299 }
300 else
301 {
302 Info << "debug : NOT a sampling step" << endl;
303 }
304
305 // Fill the mean value field
306 Eigen::VectorXd internalField = Foam2Eigen::PtrList2Eigen(
307 Tensemble).rowwise().mean();
308 volScalarField& Tmean = _T();
309 assignIF(Tmean, internalField);
310 ITHACAstream::exportSolution(Tmean, std::to_string(initialTime + deltaTime),
311 outputFolder, "Tmean");
312 ITHACAstream::exportSolution(Ttrue[timeI],
313 std::to_string(initialTime + deltaTime),
314 outputFolder, "Ttrue");
315 // Save values at measurements points
316 Eigen::MatrixXd ensambleProbe(Nprobes, Nseeds);
317
318 for (int i = 0; i < Nseeds; i++)
319 {
320 ensambleProbe.col(i) = sampleField(Tensemble[i], probePosition);
321 }
322
323 probe_mean.col(timeI) = ensambleProbe.rowwise().mean();
324 probe_MaxConfidence.col(timeI) = ITHACAmuq::muq2ithaca::quantile(ensambleProbe,
325 0.95);
326 probe_minConfidence.col(timeI) = ITHACAmuq::muq2ithaca::quantile(ensambleProbe,
327 0.05);
328 }
329
330 ITHACAstream::exportMatrix(probe_mean, "probe_mean", "eigen", outputFolder);
331 ITHACAstream::exportMatrix(probe_MaxConfidence, "probe_MaxConfidence", "eigen",
332 outputFolder);
333 ITHACAstream::exportMatrix(probe_minConfidence, "probe_minConfidence", "eigen",
334 outputFolder);
335 Info << "\n****************************************\n" << endl;
336 }
337
338
340 Eigen::MatrixXd forecastStep(double startTime_, int startIndex_,
341 double endTime_)
342 {
343 word outputFolder = "ITHACAoutput/forwardSamples";
344 bool reconstructionFlag = 1;
345 Eigen::MatrixXd observationMat;
346 sampleFlag++;
347
348 for (int i = 0; i < Nseeds; i++)
349 {
350 word fieldName = "Tsample" + std::to_string(i);
351 volScalarField T(_T());
352
353 if (startIndex_ == 0)
354 {
355 restart();
356 T = _T();
357 Eigen::VectorXd internalField = priorSamples.col(i);
358 assignIF(T, internalField);
359 }
360 else
361 {
362 T = Tensemble.set(i, nullptr)();
363 }
364
365 resetRunTime(startTime_, startIndex_, endTime_);
366
367 if (observationMat.cols() == 0)
368 {
369 observationMat = solve(T, outputFolder, fieldName, reconstructionFlag);
370 }
371 else
372 {
373 observationMat.conservativeResize(observationMat.rows(),
374 observationMat.cols() + 1);
375 Eigen::MatrixXd observationForCheck = solve(T, outputFolder, fieldName,
376 reconstructionFlag);
377 M_Assert(observationForCheck.cols() == 1,
378 "The forecast step passed trough more than a sampling step");
379 observationMat.col(i) = observationForCheck;
380 }
381
382 Tensemble.set(i, T.clone());
383 }
384
385 return observationMat;
386 }
387
389 void assignIF(volScalarField& field_, Eigen::VectorXd internalField_)
390 {
391 for (int i = 0; i < internalField_.size(); i++)
392 {
393 field_.ref()[i] = internalField_(i);
394 }
395 }
396
398 Eigen::VectorXd sampleField(volScalarField field_, Foam::vector probeLocation_)
399 {
400 Foam::fvMesh& mesh = _mesh();
401 Eigen::VectorXd output(1);
402 output(0) = field_[mesh.findCell(probeLocation_)];
403 return output;
404 }
405
407 void restart()
408 {
409 Time& runTime = _runTime();
410 instantList Times = runTime.times();
411 runTime.setTime(Times[1], 0);
412 _simple.clear();
413 _T.clear();
414 Foam::fvMesh& mesh = _mesh();
415 _simple = autoPtr<simpleControl>
416 (
417 new simpleControl
418 (
419 mesh
420 )
421 );
422 _T = autoPtr<volScalarField>
423 (
424 new volScalarField
425 (
426 IOobject
427 (
428 "T",
429 runTime.timeName(),
430 mesh,
431 IOobject::MUST_READ,
432 IOobject::AUTO_WRITE
433 ),
434 mesh
435 )
436 );
437 }
438
440 void resetRunTime(double startTime_, int startIndex_, double endTime_)
441 {
442 Time& runTime = _runTime();
443 instantList Times = runTime.times();
444 runTime.setTime(startTime_, startIndex_);
445 runTime.setEndTime(endTime_);
446 _simple.clear();
447 Foam::fvMesh& mesh = _mesh();
448 _simple = autoPtr<simpleControl>
449 (
450 new simpleControl
451 (
452 mesh
453 )
454 );
455 }
456
458 void priorSetup(double mean, double cov)
459 {
460 volScalarField& T(_T());
461 int stateSize = T.size();
462 Eigen::VectorXd prior_mu = Eigen::MatrixXd::Ones(stateSize, 1) * mean;
463 Eigen::MatrixXd prior_cov = Eigen::MatrixXd::Identity(stateSize,
464 stateSize) * cov;
465 priorDensity = std::make_shared<muq::Modeling::Gaussian>(prior_mu, prior_cov);
466 }
467
470 {
471 for (int i = 0; i < Nseeds; i++)
472 {
473 priorSamples.col(i) = priorDensity->Sample();
474 }
475
477 }
478
480 void modelErrorSetup(double mean, double cov)
481 {
482 volScalarField& T(_T());
483 int stateSize = T.size();
484 Eigen::VectorXd modelError_mu = Eigen::MatrixXd::Ones(stateSize, 1) * mean;
485 Eigen::MatrixXd modelError_cov = Eigen::MatrixXd::Identity(stateSize,
486 stateSize) * cov;
487 modelErrorDensity = std::make_shared<muq::Modeling::Gaussian>(modelError_mu,
488 modelError_cov);
489 }
490
492 void measNoiseSetup(double mean, double cov)
493 {
494 meas_cov = cov;
495 int obsSize = measurements.rows();
496 M_Assert(obsSize > 0, "Read measurements before setting up the noise");
497 Eigen::VectorXd measNoise_mu = Eigen::MatrixXd::Ones(obsSize, 1) * mean;
498 Eigen::MatrixXd measNoise_cov = Eigen::MatrixXd::Identity(obsSize,
499 obsSize) * cov;
500 measNoiseDensity = std::make_shared<muq::Modeling::Gaussian>(measNoise_mu,
501 measNoise_cov);
502 }
503};
504
505#endif
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)
fv::options & fvOptions
Definition NLsolve.H:25
TEqn solve()
Eigen::VectorXd observe(volScalarField field)
Returns the input field values at the measurement points defined in the measurementsDict.
PtrList< volScalarField > Tmean
Mean field of the ensemble.
label left_ind
Index of the left patch.
void resetRunTime(double startTime_, int startIndex_, double endTime_)
Reset runTime to given values.
std::shared_ptr< muq::Modeling::Gaussian > priorDensity
std::shared_ptr< muq::Modeling::Gaussian > measNoiseDensity
void priorSetup(double mean, double cov)
Setup of the prior distribution.
int Nseeds
Number of seeds in the ensemble.
Eigen::VectorXd timeVector
Timesteps vector.
void assignIF(volScalarField &field_, Eigen::VectorXd internalField_)
Assign internalField given an Eigen Vector.
EnKF_1DinverseHeatTransfer(int argc, char *argv[], int Nseeds_)
autoPtr< simpleControl > _simple
[tutorial02]
void measNoiseSetup(double mean, double cov)
Setup of the measurement noise distribution.
std::shared_ptr< muq::Modeling::Gaussian > modelErrorDensity
void modelErrorSetup(double mean, double cov)
Setup of the model error distribution.
double updateBC(bool reconstruction=0)
Updates the boundary conditions according to runTime.
Foam::vector probePosition
Probles position, probes are used only for visualization and postprocessing.
void reconstruct()
Reconstruction phase.
void resetSamplingCounters()
Set all the sampling counters to 0.
Eigen::MatrixXd forecastStep(double startTime_, int startIndex_, double endTime_)
Forecasting step.
PtrList< volScalarField > Tensemble
Ensemble.
void restart()
Restart before a now solution.
void solveDirect()
Preforming a true solution.
int NtimeStepsBetweenSamps
Number of timesteps between each sampling.
Eigen::MatrixXd solve(volScalarField &T, word outputFolder, word outputFieldName, bool reconstruction=0)
Solve the heat transfer problem.
void priorSampling()
Samples the prior density.
Eigen::VectorXd sampleField(volScalarField field_, Foam::vector probeLocation_)
Samples a field in a given point.
static Eigen::MatrixXd PtrList2Eigen(PtrList< GeometricField< Type, PatchField, GeoMesh > > &fields, label Nfields=-1)
Convert a PtrList of snapshots to Eigen matrix (only internal field)
Definition Foam2Eigen.C:646
autoPtr< volScalarField > _T
Temperature field.
autoPtr< fvMesh > _mesh
Mesh.
autoPtr< Time > _runTime
Time.
volScalarField & T
Definition createT.H:46
fvScalarMatrix & TEqn
Definition TEqn.H:15
Eigen::MatrixXd EnsembleKalmanFilter(Eigen::MatrixXd prior, Eigen::VectorXd measurements, Eigen::MatrixXd measurementsCov, Eigen::MatrixXd observedState)
Ensemble Kalman Filter.
Definition muq2ithaca.C:7
double quantile(Eigen::VectorXd samps, double p, int method)
Returns quantile for a vector of samples.
Definition muq2ithaca.C:134
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 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 assignBC(GeometricField< scalar, fvPatchField, volMesh > &s, label BC_ind, double value)
Assign uniform Boundary Condition to a volScalarField.
simpleControl simple(mesh)
label i
Definition pEqn.H:46