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