Salome HOME
- Nouvelle version de Jean-Philippe ARGAUD
[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             - Analysis : l'analyse
125             - Innovation : l'innovation : d = Y - H Xb
126             - SigmaObs2 : correction optimale des erreurs d'observation
127             - SigmaBck2 : correction optimale des erreurs d'ébauche
128             - OMA : Observation moins Analysis : Y - Xa
129             - OMB : Observation moins Background : Y - Xb
130             - AMB : Analysis moins Background : Xa - Xb
131             - CovarianceAPosteriori : matrice A
132         On peut rajouter des variables à stocker dans l'initialisation de
133         l'algorithme élémentaire qui va hériter de cette classe
134         """
135         self.StoredVariables = {}
136         self.StoredVariables["CostFunctionJ"]            = Persistence.OneScalar(name = "CostFunctionJ")
137         self.StoredVariables["CostFunctionJb"]           = Persistence.OneScalar(name = "CostFunctionJb")
138         self.StoredVariables["CostFunctionJo"]           = Persistence.OneScalar(name = "CostFunctionJo")
139         self.StoredVariables["GradientOfCostFunctionJ"]  = Persistence.OneScalar(name = "GradientOfCostFunctionJ")
140         self.StoredVariables["GradientOfCostFunctionJb"] = Persistence.OneScalar(name = "GradientOfCostFunctionJb")
141         self.StoredVariables["GradientOfCostFunctionJo"] = Persistence.OneScalar(name = "GradientOfCostFunctionJo")
142         self.StoredVariables["Analysis"]                 = Persistence.OneVector(name = "Analysis")
143         self.StoredVariables["Innovation"]               = Persistence.OneVector(name = "Innovation")
144         self.StoredVariables["SigmaObs2"]                = Persistence.OneScalar(name = "SigmaObs2")
145         self.StoredVariables["SigmaBck2"]                = Persistence.OneScalar(name = "SigmaBck2")
146         self.StoredVariables["OMA"]                      = Persistence.OneVector(name = "OMA")
147         self.StoredVariables["OMB"]                      = Persistence.OneVector(name = "OMB")
148         self.StoredVariables["BMA"]                      = Persistence.OneVector(name = "BMA")
149         self.StoredVariables["CovarianceAPosteriori"]    = Persistence.OneMatrix(name = "CovarianceAPosteriori")
150         self._name = None
151
152     def get(self, key=None):
153         """
154         Renvoie l'une des variables stockées identifiée par la clé, ou le
155         dictionnaire de l'ensemble des variables disponibles en l'absence de
156         clé. Ce sont directement les variables sous forme objet qui sont
157         renvoyées, donc les méthodes d'accès à l'objet individuel sont celles
158         des classes de persistance.
159         """
160         if key is not None:
161             return self.StoredVariables[key]
162         else:
163             return self.StoredVariables
164
165     def has_key(self, key=None):
166         """
167         Vérifie si l'une des variables stockées est identifiée par la clé.
168         """
169         return self.StoredVariables.has_key(key)
170
171     def run(self, Xb=None, Y=None, H=None, M=None, R=None, B=None, Q=None, Par=None):
172         """
173         Doit implémenter l'opération élémentaire de calcul d'assimilation sous
174         sa forme mathématique la plus naturelle possible.
175         """
176         raise NotImplementedError("Mathematical assimilation calculation has not been implemented!")
177
178 # ==============================================================================
179 class Diagnostic:
180     """
181     Classe générale d'interface de type diagnostic
182         
183     Ce template s'utilise de la manière suivante : il sert de classe "patron" en
184     même temps que l'une des classes de persistance, comme "OneScalar" par
185     exemple.
186     
187     Une classe élémentaire de diagnostic doit implémenter ses deux méthodes, la
188     méthode "_formula" pour écrire explicitement et proprement la formule pour
189     l'écriture mathématique du calcul du diagnostic (méthode interne non
190     publique), et "calculate" pour activer la précédente tout en ayant vérifié
191     et préparé les données, et pour stocker les résultats à chaque pas (méthode
192     externe d'activation).
193     """
194     def __init__(self, name = "", parameters = {}):
195         self.name       = str(name)
196         self.parameters = dict( parameters )
197
198     def _formula(self, *args):
199         """
200         Doit implémenter l'opération élémentaire de diagnostic sous sa forme
201         mathématique la plus naturelle possible.
202         """
203         raise NotImplementedError("Diagnostic mathematical formula has not been implemented!")
204
205     def calculate(self, *args):
206         """
207         Active la formule de calcul avec les arguments correctement rangés
208         """
209         raise NotImplementedError("Diagnostic activation method has not been implemented!")
210
211 # ==============================================================================
212 if __name__ == "__main__":
213     print '\n AUTODIAGNOSTIC \n'