Salome HOME
4f5a216d547ace5e38eda16bd861cf3ba90174e3
[modules/adao.git] / src / daComposant / daCore / BasicObjects.py
1 #-*-coding:iso-8859-1-*-
2 #
3 #  Copyright (C) 2008-2012 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 __doc__ = """
24     Définit les outils généraux élémentaires.
25     
26     Ce module est destiné à etre appelée par AssimilationStudy pour constituer
27     les objets élémentaires de l'algorithme.
28 """
29 __author__ = "Jean-Philippe ARGAUD"
30
31 import numpy
32 import Persistence
33
34 # ==============================================================================
35 class Operator:
36     """
37     Classe générale d'interface de type opérateur
38     """
39     def __init__(self, fromMethod=None, fromMatrix=None):
40         """
41         On construit un objet de ce type en fournissant à l'aide de l'un des
42         deux mots-clé, soit une fonction python, soit matrice.
43         Arguments :
44         - fromMethod : argument de type fonction Python
45         - fromMatrix : argument adapté au constructeur numpy.matrix
46         """
47         if   fromMethod is not None:
48             self.__Method = fromMethod
49             self.__Matrix = None
50         elif fromMatrix is not None:
51             self.__Method = None
52             self.__Matrix = numpy.matrix( fromMatrix, numpy.float )
53         else:
54             self.__Method = None
55             self.__Matrix = None
56
57     def appliedTo(self, xValue):
58         """
59         Permet de restituer le résultat de l'application de l'opérateur à un
60         argument xValue. Cette méthode se contente d'appliquer, son argument
61         devant a priori être du bon type.
62         Arguments :
63         - xValue : argument adapté pour appliquer l'opérateur
64         """
65         if self.__Matrix is not None:
66             return self.__Matrix * xValue
67         else:
68             return self.__Method( xValue )
69
70     def appliedInXTo(self, (xNominal, xValue) ):
71         """
72         Permet de restituer le résultat de l'application de l'opérateur à un
73         argument xValue, sachant que l'opérateur est valable en xNominal.
74         Cette méthode se contente d'appliquer, son argument devant a priori
75         être du bon type. Si l'opérateur est linéaire car c'est une matrice,
76         alors il est valable en tout point nominal et il n'est pas nécessaire
77         d'utiliser xNominal.
78         Arguments : une liste contenant
79         - xNominal : argument permettant de donner le point où l'opérateur
80           est construit pour etre ensuite appliqué
81         - xValue : argument adapté pour appliquer l'opérateur
82         """
83         if self.__Matrix is not None:
84             return self.__Matrix * xValue
85         else:
86             return self.__Method( (xNominal, xValue) )
87
88     def asMatrix(self):
89         """
90         Permet de renvoyer l'opérateur sous la forme d'une matrice
91         """
92         if self.__Matrix is not None:
93             return self.__Matrix
94         else:
95             raise ValueError("Matrix form of the operator is not available")
96
97     def shape(self):
98         """
99         Renvoie la taille sous forme numpy si l'opérateur est disponible sous
100         la forme d'une matrice
101         """
102         if self.__Matrix is not None:
103             return self.__Matrix.shape
104         else:
105             raise ValueError("Matrix form of the operator is not available, nor the shape")
106
107 # ==============================================================================
108 class Algorithm:
109     """
110     Classe générale d'interface de type algorithme
111     
112     Elle donne un cadre pour l'écriture d'une classe élémentaire d'algorithme
113     d'assimilation, en fournissant un container (dictionnaire) de variables
114     persistantes initialisées, et des méthodes d'accès à ces variables stockées.
115     
116     Une classe élémentaire d'algorithme doit implémenter la méthode "run".
117     """
118     def __init__(self):
119         """
120         L'initialisation présente permet de fabriquer des variables de stockage
121         disponibles de manière générique dans les algorithmes élémentaires. Ces
122         variables de stockage sont ensuite conservées dans un dictionnaire
123         interne à l'objet, mais auquel on accède par la méthode "get".
124         
125         Les variables prévues sont :
126             - CostFunctionJ  : fonction-cout globale, somme des deux parties suivantes
127             - CostFunctionJb : partie ébauche ou background de la fonction-cout
128             - CostFunctionJo : partie observations de la fonction-cout
129             - GradientOfCostFunctionJ  : gradient de la fonction-cout globale
130             - GradientOfCostFunctionJb : gradient de la partie ébauche de la fonction-cout
131             - GradientOfCostFunctionJo : gradient de la partie observations de la fonction-cout
132             - CurrentState : état courant lors d'itérations
133             - Analysis : l'analyse
134             - Innovation : l'innovation : d = Y - H Xb
135             - SigmaObs2 : correction optimale des erreurs d'observation
136             - SigmaBck2 : correction optimale des erreurs d'ébauche
137             - OMA : Observation moins Analysis : Y - Xa
138             - OMB : Observation moins Background : Y - Xb
139             - AMB : Analysis moins Background : Xa - Xb
140             - APosterioriCovariance : matrice A
141         On peut rajouter des variables à stocker dans l'initialisation de
142         l'algorithme élémentaire qui va hériter de cette classe
143         """
144         self._name = None
145         self.StoredVariables = {}
146         #
147         self.StoredVariables["CostFunctionJ"]            = Persistence.OneScalar(name = "CostFunctionJ")
148         self.StoredVariables["CostFunctionJb"]           = Persistence.OneScalar(name = "CostFunctionJb")
149         self.StoredVariables["CostFunctionJo"]           = Persistence.OneScalar(name = "CostFunctionJo")
150         self.StoredVariables["GradientOfCostFunctionJ"]  = Persistence.OneVector(name = "GradientOfCostFunctionJ")
151         self.StoredVariables["GradientOfCostFunctionJb"] = Persistence.OneVector(name = "GradientOfCostFunctionJb")
152         self.StoredVariables["GradientOfCostFunctionJo"] = Persistence.OneVector(name = "GradientOfCostFunctionJo")
153         self.StoredVariables["CurrentState"]             = Persistence.OneVector(name = "CurrentState")
154         self.StoredVariables["Analysis"]                 = Persistence.OneVector(name = "Analysis")
155         self.StoredVariables["Innovation"]               = Persistence.OneVector(name = "Innovation")
156         self.StoredVariables["SigmaObs2"]                = Persistence.OneScalar(name = "SigmaObs2")
157         self.StoredVariables["SigmaBck2"]                = Persistence.OneScalar(name = "SigmaBck2")
158         self.StoredVariables["OMA"]                      = Persistence.OneVector(name = "OMA")
159         self.StoredVariables["OMB"]                      = Persistence.OneVector(name = "OMB")
160         self.StoredVariables["BMA"]                      = Persistence.OneVector(name = "BMA")
161         self.StoredVariables["APosterioriCovariance"]    = Persistence.OneMatrix(name = "APosterioriCovariance")
162
163     def get(self, key=None):
164         """
165         Renvoie l'une des variables stockées identifiée par la clé, ou le
166         dictionnaire de l'ensemble des variables disponibles en l'absence de
167         clé. Ce sont directement les variables sous forme objet qui sont
168         renvoyées, donc les méthodes d'accès à l'objet individuel sont celles
169         des classes de persistance.
170         """
171         if key is not None:
172             return self.StoredVariables[key]
173         else:
174             return self.StoredVariables
175
176     def has_key(self, key=None):
177         """
178         Vérifie si l'une des variables stockées est identifiée par la clé.
179         """
180         return self.StoredVariables.has_key(key)
181
182     def keys(self):
183         """
184         Renvoie la liste des clés de variables stockées.
185         """
186         return self.StoredVariables.keys()
187
188     def run(self, Xb=None, Y=None, H=None, M=None, R=None, B=None, Q=None, Parameters=None):
189         """
190         Doit implémenter l'opération élémentaire de calcul d'assimilation sous
191         sa forme mathématique la plus naturelle possible.
192         """
193         raise NotImplementedError("Mathematical assimilation calculation has not been implemented!")
194
195 # ==============================================================================
196 class Diagnostic:
197     """
198     Classe générale d'interface de type diagnostic
199         
200     Ce template s'utilise de la manière suivante : il sert de classe "patron" en
201     même temps que l'une des classes de persistance, comme "OneScalar" par
202     exemple.
203     
204     Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la
205     méthode "_formula" pour écrire explicitement et proprement la formule pour
206     l'écriture mathématique du calcul du diagnostic (méthode interne non
207     publique), et "calculate" pour activer la précédente tout en ayant vérifié
208     et préparé les données, et pour stocker les résultats à chaque pas (méthode
209     externe d'activation).
210     """
211     def __init__(self, name = "", parameters = {}):
212         self.name       = str(name)
213         self.parameters = dict( parameters )
214
215     def _formula(self, *args):
216         """
217         Doit implémenter l'opération élémentaire de diagnostic sous sa forme
218         mathématique la plus naturelle possible.
219         """
220         raise NotImplementedError("Diagnostic mathematical formula has not been implemented!")
221
222     def calculate(self, *args):
223         """
224         Active la formule de calcul avec les arguments correctement rangés
225         """
226         raise NotImplementedError("Diagnostic activation method has not been implemented!")
227
228 # ==============================================================================
229 if __name__ == "__main__":
230     print '\n AUTODIAGNOSTIC \n'