]> SALOME platform Git repositories - modules/adao.git/blob - src/daComposant/daAlgorithms/EnsembleBlue.py
Salome HOME
Documentation update with features and review corrections
[modules/adao.git] / src / daComposant / daAlgorithms / EnsembleBlue.py
1 # -*- coding: utf-8 -*-
2 #
3 # Copyright (C) 2008-2024 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 numpy
24 from daCore import BasicObjects
25
26 # ==============================================================================
27 class ElementaryAlgorithm(BasicObjects.Algorithm):
28     def __init__(self):
29         BasicObjects.Algorithm.__init__(self, "ENSEMBLEBLUE")
30         self.defineRequiredParameter(
31             name     = "StoreInternalVariables",
32             default  = False,
33             typecast = bool,
34             message  = "Stockage des variables internes ou intermédiaires du calcul",
35         )
36         self.defineRequiredParameter(
37             name     = "StoreSupplementaryCalculations",
38             default  = [],
39             typecast = tuple,
40             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
41             listval  = [
42                 "Analysis",
43                 "CurrentOptimum",
44                 "CurrentState",
45                 "Innovation",
46                 "SimulatedObservationAtBackground",
47                 "SimulatedObservationAtCurrentState",
48                 "SimulatedObservationAtOptimum",
49             ]
50         )
51         self.defineRequiredParameter(
52             name     = "SetSeed",
53             typecast = numpy.random.seed,
54             message  = "Graine fixée pour le générateur aléatoire",
55         )
56         self.requireInputArguments(
57             mandatory= ("Xb", "Y", "HO", "R", "B"),
58         )
59         self.setAttributes(
60             tags=(
61                 "DataAssimilation",
62                 "NonLinear",
63                 "Filter",
64                 "Ensemble",
65                 "Reduction",
66             ),
67             features=(
68                 "LocalOptimization",
69                 "DerivativeNeeded",
70                 "ParallelDerivativesOnly",
71             ),
72         )
73
74     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
75         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
76         #
77         # Précalcul des inversions de B et R
78         # ----------------------------------
79         BI = B.getI()
80         RI = R.getI()
81         #
82         # Nombre d'ensemble pour l'ébauche
83         # --------------------------------
84         nb_ens = Xb.stepnumber()
85         #
86         # Construction de l'ensemble des observations, par génération a partir
87         # de la diagonale de R
88         # --------------------------------------------------------------------
89         DiagonaleR = R.diag(Y.size)
90         EnsembleY = numpy.zeros([Y.size, nb_ens])
91         for npar in range(DiagonaleR.size):
92             bruit = numpy.random.normal(0, DiagonaleR[npar], nb_ens)
93             EnsembleY[npar, :] = Y[npar] + bruit
94         #
95         # Initialisation des opérateurs d'observation et de la matrice gain
96         # -----------------------------------------------------------------
97         Xbm = Xb.mean()
98         Hm = HO["Tangent"].asMatrix(Xbm)
99         Hm = Hm.reshape(Y.size, Xbm.size)  # ADAO & check shape
100         Ha = HO["Adjoint"].asMatrix(Xbm)
101         Ha = Ha.reshape(Xbm.size, Y.size)  # ADAO & check shape
102         #
103         # Calcul de la matrice de gain dans l'espace le plus petit et de l'analyse
104         # ------------------------------------------------------------------------
105         if Y.size <= Xb[0].size:
106             K  = B * Ha * (R + Hm * (B * Ha)).I
107         else:
108             K = (BI + Ha * (RI * Hm)).I * Ha * RI
109         #
110         # Calcul du BLUE pour chaque membre de l'ensemble
111         # -----------------------------------------------
112         for iens in range(nb_ens):
113             HXb = Hm @ Xb[iens]
114             if self._toStore("SimulatedObservationAtBackground"):
115                 self.StoredVariables["SimulatedObservationAtBackground"].store( HXb )
116             Innovation  = numpy.ravel(EnsembleY[:, iens]) - numpy.ravel(HXb)
117             if self._toStore("Innovation"):
118                 self.StoredVariables["Innovation"].store( Innovation )
119             Xa = Xb[iens] + K @ Innovation
120             self.StoredVariables["CurrentState"].store( Xa )
121             if self._toStore("SimulatedObservationAtCurrentState"):
122                 self.StoredVariables["SimulatedObservationAtCurrentState"].store( Hm @ numpy.ravel(Xa) )
123         #
124         # Fabrication de l'analyse
125         # ------------------------
126         Members = self.StoredVariables["CurrentState"][-nb_ens:]
127         Xa = numpy.array( Members ).mean(axis=0)
128         self.StoredVariables["Analysis"].store( Xa )
129         if self._toStore("CurrentOptimum"):
130             self.StoredVariables["CurrentOptimum"].store( Xa )
131         if self._toStore("SimulatedObservationAtOptimum"):
132             self.StoredVariables["SimulatedObservationAtOptimum"].store( Hm @ numpy.ravel(Xa) )
133         #
134         self._post_run(HO, EM)
135         return 0
136
137 # ==============================================================================
138 if __name__ == "__main__":
139     print("\n AUTODIAGNOSTIC\n")