Salome HOME
Improvement and extension of EnKF algorithm (ETKF-N)
[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                 "StochasticEnKF",
38                 "ETKF",     # Default ETKF
39                 "ETKF-KFF",
40                 "ETKF-VAR",
41                 "ETKF-N",   # Default ETKF-N
42                 "ETKF-N-11",
43                 "ETKF-N-15",
44                 "ETKF-N-16",
45                 ],
46             )
47         self.defineRequiredParameter(
48             name     = "NumberOfMembers",
49             default  = 100,
50             typecast = int,
51             message  = "Nombre de membres dans l'ensemble",
52             minval   = 2,
53             )
54         self.defineRequiredParameter(
55             name     = "EstimationOf",
56             default  = "State",
57             typecast = str,
58             message  = "Estimation d'etat ou de parametres",
59             listval  = ["State", "Parameters"],
60             )
61         self.defineRequiredParameter(
62             name     = "InflationType",
63             default  = "MultiplicativeOnAnalysisCovariance",
64             typecast = str,
65             message  = "Méthode d'inflation d'ensemble",
66             listval  = [
67                 "MultiplicativeOnAnalysisCovariance",
68                 "MultiplicativeOnBackgroundCovariance",
69                 "MultiplicativeOnAnalysisAnomalies",
70                 "MultiplicativeOnBackgroundAnomalies",
71                 "AdditiveOnBackgroundCovariance",
72                 "AdditiveOnAnalysisCovariance",
73                 "HybridOnBackgroundCovariance",
74                 ],
75             )
76         self.defineRequiredParameter(
77             name     = "InflationFactor",
78             default  = 1.,
79             typecast = float,
80             message  = "Facteur d'inflation",
81             minval   = 0.,
82             )
83         self.defineRequiredParameter(
84             name     = "LocalizationType",
85             default  = "SchurLocalization",
86             typecast = str,
87             message  = "Méthode d'inflation d'ensemble",
88             listval  = [
89                 "CovarianceLocalization",
90                 "DomainLocalization",
91                 "SchurLocalization",
92                 "GaspariCohnLocalization",
93                 ],
94             )
95         self.defineRequiredParameter(
96             name     = "LocalizationFactor",
97             default  = 1.,
98             typecast = float,
99             message  = "Facteur de localisation",
100             minval   = 0.,
101             )
102         self.defineRequiredParameter( # Pas de type
103             name     = "LocalizationMatrix",
104             message  = "Matrice de localisation ou de distances",
105             )
106         self.defineRequiredParameter(
107             name     = "SetSeed",
108             typecast = numpy.random.seed,
109             message  = "Graine fixée pour le générateur aléatoire",
110             )
111         self.defineRequiredParameter(
112             name     = "StoreInternalVariables",
113             default  = False,
114             typecast = bool,
115             message  = "Stockage des variables internes ou intermédiaires du calcul",
116             )
117         self.defineRequiredParameter(
118             name     = "StoreSupplementaryCalculations",
119             default  = [],
120             typecast = tuple,
121             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
122             listval  = [
123                 "Analysis",
124                 "APosterioriCorrelations",
125                 "APosterioriCovariance",
126                 "APosterioriStandardDeviations",
127                 "APosterioriVariances",
128                 "BMA",
129                 "CostFunctionJ",
130                 "CostFunctionJAtCurrentOptimum",
131                 "CostFunctionJb",
132                 "CostFunctionJbAtCurrentOptimum",
133                 "CostFunctionJo",
134                 "CostFunctionJoAtCurrentOptimum",
135                 "CurrentIterationNumber",
136                 "CurrentOptimum",
137                 "CurrentState",
138                 "ForecastState",
139                 "IndexOfOptimum",
140                 "InnovationAtCurrentAnalysis",
141                 "InnovationAtCurrentState",
142                 "SimulatedObservationAtCurrentAnalysis",
143                 "SimulatedObservationAtCurrentOptimum",
144                 "SimulatedObservationAtCurrentState",
145                 ]
146             )
147         self.requireInputArguments(
148             mandatory= ("Xb", "Y", "HO", "R", "B"),
149             optional = ("U", "EM", "CM", "Q"),
150             )
151         self.setAttributes(tags=(
152             "DataAssimilation",
153             "NonLinear",
154             "Filter",
155             "Ensemble",
156             "Dynamic",
157             ))
158
159     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
160         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
161         #
162         if self._parameters["Minimizer"] == "StochasticEnKF":
163             NumericObjects.senkf(self, Xb, Y, U, HO, EM, CM, R, B, Q)
164         #
165         elif self._parameters["Minimizer"] in ["ETKF-KFF", "ETKF"]:
166             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="KalmanFilterFormula")
167         #
168         elif self._parameters["Minimizer"] == "ETKF-VAR":
169             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="Variational")
170         #
171         elif self._parameters["Minimizer"] == "ETKF-N-11":
172             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="FiniteSize11")
173         #
174         elif self._parameters["Minimizer"] == "ETKF-N-15":
175             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="FiniteSize15")
176         #
177         elif self._parameters["Minimizer"] in ["ETKF-N-16", "ETKF-N"]:
178             NumericObjects.etkf(self, Xb, Y, U, HO, EM, CM, R, B, Q, KorV="FiniteSize16")
179         #
180         else:
181             raise ValueError("Error in Minimizer name: %s"%self._parameters["Minimizer"])
182         #
183         self._post_run(HO)
184         return 0
185
186 # ==============================================================================
187 if __name__ == "__main__":
188     print('\n AUTODIAGNOSTIC\n')