Salome HOME
Improvement and extension of 3DVAR algorithm
[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     = "Variant",
33             default  = "EnKF",
34             typecast = str,
35             message  = "Variant ou formulation de la méthode",
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                 "AdditiveOnAnalysisCovariance",
84                 "AdditiveOnBackgroundCovariance",
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                 "SchurLocalization",
102                 ],
103             listadv  = [
104                 "CovarianceLocalization",
105                 "DomainLocalization",
106                 "GaspariCohnLocalization",
107                 ],
108             )
109         self.defineRequiredParameter(
110             name     = "LocalizationFactor",
111             default  = 1.,
112             typecast = float,
113             message  = "Facteur de localisation",
114             minval   = 0.,
115             )
116         self.defineRequiredParameter( # Pas de type
117             name     = "LocalizationMatrix",
118             message  = "Matrice de localisation ou de distances",
119             )
120         self.defineRequiredParameter(
121             name     = "SetSeed",
122             typecast = numpy.random.seed,
123             message  = "Graine fixée pour le générateur aléatoire",
124             )
125         self.defineRequiredParameter(
126             name     = "StoreInternalVariables",
127             default  = False,
128             typecast = bool,
129             message  = "Stockage des variables internes ou intermédiaires du calcul",
130             )
131         self.defineRequiredParameter(
132             name     = "StoreSupplementaryCalculations",
133             default  = [],
134             typecast = tuple,
135             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
136             listval  = [
137                 "Analysis",
138                 "APosterioriCorrelations",
139                 "APosterioriCovariance",
140                 "APosterioriStandardDeviations",
141                 "APosterioriVariances",
142                 "BMA",
143                 "CostFunctionJ",
144                 "CostFunctionJAtCurrentOptimum",
145                 "CostFunctionJb",
146                 "CostFunctionJbAtCurrentOptimum",
147                 "CostFunctionJo",
148                 "CostFunctionJoAtCurrentOptimum",
149                 "CurrentIterationNumber",
150                 "CurrentOptimum",
151                 "CurrentState",
152                 "ForecastState",
153                 "IndexOfOptimum",
154                 "InnovationAtCurrentAnalysis",
155                 "InnovationAtCurrentState",
156                 "SimulatedObservationAtCurrentAnalysis",
157                 "SimulatedObservationAtCurrentOptimum",
158                 "SimulatedObservationAtCurrentState",
159                 ]
160             )
161         self.requireInputArguments(
162             mandatory= ("Xb", "Y", "HO", "R", "B"),
163             optional = ("U", "EM", "CM", "Q"),
164             )
165         self.setAttributes(tags=(
166             "DataAssimilation",
167             "NonLinear",
168             "Filter",
169             "Ensemble",
170             "Dynamic",
171             ))
172
173     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
174         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
175         #
176         #--------------------------
177         # Default EnKF = EnKF-16 = StochasticEnKF
178         if   self._parameters["Variant"] == "EnKF-05":
179             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula05")
180         #
181         elif self._parameters["Variant"] in ["EnKF-16", "StochasticEnKF", "EnKF"]:
182             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula16")
183         #
184         #--------------------------
185         # Default ETKF = ETKF-KFF
186         elif self._parameters["Variant"] in ["ETKF-KFF", "ETKF"]:
187             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="KalmanFilterFormula")
188         #
189         elif self._parameters["Variant"] == "ETKF-VAR":
190             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="Variational")
191         #
192         #--------------------------
193         # Default ETKF-N = ETKF-N-16
194         elif self._parameters["Variant"] == "ETKF-N-11":
195             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize11")
196         #
197         elif self._parameters["Variant"] == "ETKF-N-15":
198             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize15")
199         #
200         elif self._parameters["Variant"] in ["ETKF-N-16", "ETKF-N"]:
201             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, VariantM="FiniteSize16")
202         #
203         #--------------------------
204         # Default MLEF = MLEF-T
205         elif self._parameters["Variant"] in ["MLEF-T", "MLEF"]:
206             NumericObjects.mlef(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=False)
207         #
208         elif self._parameters["Variant"] == "MLEF-B":
209             NumericObjects.mlef(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=True)
210         #
211         #--------------------------
212         # Default IEnKF = IEnKF-T
213         elif self._parameters["Variant"] in ["IEnKF-T", "IEnKF"]:
214             NumericObjects.ienkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=False)
215         #
216         elif self._parameters["Variant"] in ["IEnKF-B", "IEKF"]:
217             NumericObjects.ienkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, BnotT=True)
218         #
219         #--------------------------
220         else:
221             raise ValueError("Error in Variant name: %s"%self._parameters["Variant"])
222         #
223         self._post_run(HO)
224         return 0
225
226 # ==============================================================================
227 if __name__ == "__main__":
228     print('\n AUTODIAGNOSTIC\n')