Salome HOME
Improvement and extension of EnKF algorithm (EnKF)
[modules/adao.git] / src / daComposant / daAlgorithms / EnsembleKalmanFilter.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2021 EDF R&D
4 #
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
9 #
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 # Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 #
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
22
23 import logging
24 from daCore import BasicObjects, NumericObjects
25 import numpy
26
27 # ==============================================================================
28 class ElementaryAlgorithm(BasicObjects.Algorithm):
29     def __init__(self):
30         BasicObjects.Algorithm.__init__(self, "ENSEMBLEKALMANFILTER")
31         self.defineRequiredParameter(
32             name     = "Minimizer",
33             default  = "StochasticEnKF",
34             typecast = str,
35             message  = "Minimiseur utilisé",
36             listval  = [
37                 "EnKF",
38                 "ETKF",
39                 "ETKF-N",
40                 "MLEF",
41                 "IEnKF",
42                 ],
43             listadv  = [
44                 "StochasticEnKF",
45                 "EnKF-05",
46                 "EnKF-16",
47                 "ETKF-KFF",
48                 "ETKF-VAR",
49                 "ETKF-N-11",
50                 "ETKF-N-15",
51                 "ETKF-N-16",
52                 "MLEF-T",
53                 "MLEF-B",
54                 "IEnKF-T",
55                 "IEnKF-B",
56                 "IEKF",
57                 ],
58             )
59         self.defineRequiredParameter(
60             name     = "NumberOfMembers",
61             default  = 100,
62             typecast = int,
63             message  = "Nombre de membres dans l'ensemble",
64             minval   = 2,
65             )
66         self.defineRequiredParameter(
67             name     = "EstimationOf",
68             default  = "State",
69             typecast = str,
70             message  = "Estimation d'etat ou de parametres",
71             listval  = ["State", "Parameters"],
72             )
73         self.defineRequiredParameter(
74             name     = "InflationType",
75             default  = "MultiplicativeOnAnalysisCovariance",
76             typecast = str,
77             message  = "Méthode d'inflation d'ensemble",
78             listval  = [
79                 "MultiplicativeOnAnalysisCovariance",
80                 "MultiplicativeOnBackgroundCovariance",
81                 "MultiplicativeOnAnalysisAnomalies",
82                 "MultiplicativeOnBackgroundAnomalies",
83                 "AdditiveOnBackgroundCovariance",
84                 "AdditiveOnAnalysisCovariance",
85                 "HybridOnBackgroundCovariance",
86                 ],
87             )
88         self.defineRequiredParameter(
89             name     = "InflationFactor",
90             default  = 1.,
91             typecast = float,
92             message  = "Facteur d'inflation",
93             minval   = 0.,
94             )
95         self.defineRequiredParameter(
96             name     = "LocalizationType",
97             default  = "SchurLocalization",
98             typecast = str,
99             message  = "Méthode d'inflation d'ensemble",
100             listval  = [
101                 "CovarianceLocalization",
102                 "DomainLocalization",
103                 "SchurLocalization",
104                 "GaspariCohnLocalization",
105                 ],
106             )
107         self.defineRequiredParameter(
108             name     = "LocalizationFactor",
109             default  = 1.,
110             typecast = float,
111             message  = "Facteur de localisation",
112             minval   = 0.,
113             )
114         self.defineRequiredParameter( # Pas de type
115             name     = "LocalizationMatrix",
116             message  = "Matrice de localisation ou de distances",
117             )
118         self.defineRequiredParameter(
119             name     = "SetSeed",
120             typecast = numpy.random.seed,
121             message  = "Graine fixée pour le générateur aléatoire",
122             )
123         self.defineRequiredParameter(
124             name     = "StoreInternalVariables",
125             default  = False,
126             typecast = bool,
127             message  = "Stockage des variables internes ou intermédiaires du calcul",
128             )
129         self.defineRequiredParameter(
130             name     = "StoreSupplementaryCalculations",
131             default  = [],
132             typecast = tuple,
133             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
134             listval  = [
135                 "Analysis",
136                 "APosterioriCorrelations",
137                 "APosterioriCovariance",
138                 "APosterioriStandardDeviations",
139                 "APosterioriVariances",
140                 "BMA",
141                 "CostFunctionJ",
142                 "CostFunctionJAtCurrentOptimum",
143                 "CostFunctionJb",
144                 "CostFunctionJbAtCurrentOptimum",
145                 "CostFunctionJo",
146                 "CostFunctionJoAtCurrentOptimum",
147                 "CurrentIterationNumber",
148                 "CurrentOptimum",
149                 "CurrentState",
150                 "ForecastState",
151                 "IndexOfOptimum",
152                 "InnovationAtCurrentAnalysis",
153                 "InnovationAtCurrentState",
154                 "SimulatedObservationAtCurrentAnalysis",
155                 "SimulatedObservationAtCurrentOptimum",
156                 "SimulatedObservationAtCurrentState",
157                 ]
158             )
159         self.requireInputArguments(
160             mandatory= ("Xb", "Y", "HO", "R", "B"),
161             optional = ("U", "EM", "CM", "Q"),
162             )
163         self.setAttributes(tags=(
164             "DataAssimilation",
165             "NonLinear",
166             "Filter",
167             "Ensemble",
168             "Dynamic",
169             ))
170
171     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
172         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
173         #
174         #--------------------------
175         # Default EnKF = EnKF-16 = StochasticEnKF
176         if   self._parameters["Minimizer"] in ["EnKF-05"]:
177             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula05")
178         #
179         elif self._parameters["Minimizer"] in ["EnKF-16", "StochasticEnKF", "EnKF"]:
180             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula16")
181         #
182         #--------------------------
183         # Default ETKF = ETKF-KFF
184         elif self._parameters["Minimizer"] in ["ETKF-KFF", "ETKF"]:
185             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula")
186         #
187         elif self._parameters["Minimizer"] == "ETKF-VAR":
188             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="Variational")
189         #
190         #--------------------------
191         # Default ETKF-N = ETKF-N-16
192         elif self._parameters["Minimizer"] == "ETKF-N-11":
193             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize11")
194         #
195         elif self._parameters["Minimizer"] == "ETKF-N-15":
196             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize15")
197         #
198         elif self._parameters["Minimizer"] in ["ETKF-N-16", "ETKF-N"]:
199             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize16")
200         #
201         #--------------------------
202         # Default MLEF = MLEF-T
203         elif self._parameters["Minimizer"] in ["MLEF-T", "MLEF"]:
204             NumericObjects.mlef(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=False)
205         #
206         elif self._parameters["Minimizer"] == "MLEF-B":
207             NumericObjects.mlef(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=True)
208         #
209         #--------------------------
210         # Default IEnKF = IEnKF-T
211         elif self._parameters["Minimizer"] in ["IEnKF-T", "IEnKF"]:
212             NumericObjects.ienkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=False)
213         #
214         elif self._parameters["Minimizer"] in ["IEnKF-B", "IEKF"]:
215             NumericObjects.ienkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=True)
216         #
217         #--------------------------
218         else:
219             raise ValueError("Error in Minimizer name: %s"%self._parameters["Minimizer"])
220         #
221         self._post_run(HO)
222         return 0
223
224 # ==============================================================================
225 if __name__ == "__main__":
226     print('\n AUTODIAGNOSTIC\n')