Loading...
Searching...
No Matches
01enKF.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 Test of the Ensemble Kalman filter implementation
26SourceFiles
27 01enKF.C
28\*---------------------------------------------------------------------------*/
29
30
31#include "MUQ/Modeling/Distributions/Gaussian.h"
32#include "MUQ/Modeling/Distributions/Density.h"
33
34#include <iostream>
35#include "fvCFD.H"
36#include "IOmanip.H"
37#include "ITHACAutilities.H"
38#include <Eigen/Dense>
39#define _USE_MATH_DEFINES
40#include <cmath>
41#include "Foam2Eigen.H"
42#include "muq2ithaca.H"
43
44int main(int argc, char* argv[])
45{
46 word outputFolder = "./ITHACAoutput/";
47 int Nseeds = 1000;
48 Eigen::MatrixXd A = ITHACAstream::readMatrix("A_mat.txt");
49 Eigen::MatrixXd Aw = ITHACAstream::readMatrix("Awrong_mat.txt");
50 Eigen::MatrixXd H = ITHACAstream::readMatrix("observation_mat.txt");
51 M_Assert(ITHACAstream::readMatrix("initialState_mat.txt").cols() == 1,
52 "Wrong initialState input");
53 Eigen::VectorXd x0 = ITHACAstream::readMatrix("initialState_mat.txt").col(0);
54 int stateSize = A.rows();
55 int obsSize = H.rows();
56 std::cout <<
57 "In this tutorial we have a dynamical system in the form:\ndx/dt = A * x" <<
58 std::endl;
59 std::cout << "with A = \n" << A << std::endl;
60 std::cout << "We observe the state x by mean of the observation matrix \nH = \n"
61 << H << std::endl;
62 std::cout <<
63 "The objective is to reconstruct the vector state knowing H and x0 = \n" <<
64 x0.transpose() <<
65 "\nbut having a wrong A" << std::endl;
66 std::cout << "A_wrong =\n" << Aw << std::endl;
67 int Ntimes = 201;
68 int sampleDeltaStep = 10;
69 double endTime = 10;
70 double deltaTime = endTime / Ntimes;
71 Eigen::VectorXd time = Eigen::VectorXd::LinSpaced(Ntimes, 0, endTime);
72 Eigen::VectorXd xOld = x0;
73 Eigen::MatrixXd X(stateSize, Ntimes);
74 X.col(0) = x0;
75 int sampleFlag = sampleDeltaStep;
76 int Nsamples = (Ntimes - 1) / sampleDeltaStep;
77 int sampleI = 0;
78 Eigen::MatrixXd obs(obsSize, Nsamples);
79
80 for (int timeI = 0; timeI < Ntimes - 1; timeI++)
81 {
82 Eigen::VectorXd xNew = (A * deltaTime + Eigen::MatrixXd::Identity(A.rows(),
83 A.cols())) * xOld;
84 xOld = xNew;
85 Eigen::VectorXd dNew = H * xNew;
86 X.col(timeI + 1) = xNew;
87 sampleFlag--;
88
89 if (sampleFlag == 0)
90 {
91 sampleFlag = sampleDeltaStep;
92 obs.col(sampleI) = dNew;
93 sampleI++;
94 }
95 }
96
97 M_Assert(Nsamples == sampleI, "Something went wrong in the sampling");
98 ITHACAstream::exportMatrix(time, "time", "eigen", outputFolder);
99 ITHACAstream::exportMatrix(X, "X", "eigen", outputFolder);
100 Eigen::VectorXd x = x0;
101 Eigen::VectorXd prior_mu = x * 0.0;
102 Eigen::MatrixXd prior_cov = Eigen::MatrixXd::Identity(stateSize,
103 stateSize) * 0.5;
104 auto priorDensity = std::make_shared<muq::Modeling::Gaussian>(prior_mu,
105 prior_cov);
106 Eigen::VectorXd modelError_mu = x * 0.0;
107 Eigen::MatrixXd modelError_cov = Eigen::MatrixXd::Identity(stateSize,
108 stateSize) * 0.7;
109 auto modelErrorDensity = std::make_shared<muq::Modeling::Gaussian>
110 (modelError_mu, modelError_cov);
111 Eigen::MatrixXd posteriorSamples(stateSize, Nseeds);
112 Eigen::MatrixXd priorSamples(stateSize, Nseeds);
113
114 for (int i = 0; i < Nseeds; i++)
115 {
116 priorSamples.col(i) = priorDensity->Sample();
117 }
118
119 posteriorSamples = priorSamples;
120 Eigen::MatrixXd meas_cov = Eigen::MatrixXd::Identity(obsSize, obsSize) * 0.3;
121 auto measNoise = std::make_shared<muq::Modeling::Gaussian>
122 (Eigen::VectorXd::Zero(obsSize), meas_cov);
123 Eigen::MatrixXd posteriorMean(stateSize, Ntimes);
124 Eigen::MatrixXd minConfidence = posteriorMean;
125 Eigen::MatrixXd maxConfidence = minConfidence;
126 posteriorMean.col(0) = posteriorSamples.rowwise().mean();
127 sampleFlag = sampleDeltaStep;
128 sampleI = 0;
129 Eigen::MatrixXd forwardSamples(stateSize, Nseeds);
130
131 for (int timeI = 0; timeI < Ntimes - 1; timeI++)
132 {
133 priorSamples = posteriorSamples;
134 Eigen::MatrixXd forwardSamplesOld = forwardSamples;
135
136 //Forecast step
137 for (int i = 0; i < Nseeds; i++)
138 {
139 forwardSamples.col(i) = (A * deltaTime + Eigen::MatrixXd::Identity(A.rows(),
140 A.cols())) * priorSamples.col(i) + modelErrorDensity->Sample();
141 }
142
143 sampleFlag--;
144
145 if (sampleFlag == 0)
146 {
147 sampleFlag = sampleDeltaStep;
148 Eigen::VectorXd meas = obs.col(sampleI);
149 //Kalman filter
150 posteriorSamples = ITHACAmuq::muq2ithaca::EnsembleKalmanFilter(forwardSamples,
151 meas, meas_cov, H * forwardSamples);
152 sampleI++;
153 }
154 else
155 {
156 posteriorSamples = forwardSamples;
157 }
158
159 posteriorMean.col(timeI + 1) = posteriorSamples.rowwise().mean();
160 minConfidence.col(timeI + 1) = ITHACAmuq::muq2ithaca::quantile(posteriorSamples,
161 0.05);
162 maxConfidence.col(timeI + 1) = ITHACAmuq::muq2ithaca::quantile(posteriorSamples,
163 0.95);
164 }
165
166 ITHACAstream::exportMatrix(posteriorMean, "posteriorMean", "eigen",
167 outputFolder);
168 ITHACAstream::exportMatrix(minConfidence, "minConfidence", "eigen",
169 outputFolder);
170 ITHACAstream::exportMatrix(maxConfidence, "maxConfidence", "eigen",
171 outputFolder);
172 return 0;
173}
int main(int argc, char *argv[])
Definition 01enKF.C:44
Header file of the Foam2Eigen class.
#define M_Assert(Expr, Msg)
Header file of the ITHACAutilities namespace.
volScalarField & A
Header file of the muq2ithaca namespace.
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 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.
label i
Definition pEqn.H:46