Salome HOME
Documentation update with features and review corrections
[modules/adao.git] / src / daComposant / daAlgorithms / ParallelFunctionTest.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, copy, logging
24 from daCore import BasicObjects, PlatformInfo
25 mpr = PlatformInfo.PlatformInfo().MachinePrecision()
26 mfp = PlatformInfo.PlatformInfo().MaximumPrecision()
27
28 # ==============================================================================
29 class ElementaryAlgorithm(BasicObjects.Algorithm):
30     def __init__(self):
31         BasicObjects.Algorithm.__init__(self, "PARALLELFUNCTIONTEST")
32         self.defineRequiredParameter(
33             name     = "ShowElementarySummary",
34             default  = True,
35             typecast = bool,
36             message  = "Calcule et affiche un résumé à chaque évaluation élémentaire",
37         )
38         self.defineRequiredParameter(
39             name     = "NumberOfPrintedDigits",
40             default  = 5,
41             typecast = int,
42             message  = "Nombre de chiffres affichés pour les impressions de réels",
43             minval   = 0,
44         )
45         self.defineRequiredParameter(
46             name     = "NumberOfRepetition",
47             default  = 1,
48             typecast = int,
49             message  = "Nombre de fois où l'exécution de la fonction est répétée",
50             minval   = 1,
51         )
52         self.defineRequiredParameter(
53             name     = "ResultTitle",
54             default  = "",
55             typecast = str,
56             message  = "Titre du tableau et de la figure",
57         )
58         self.defineRequiredParameter(
59             name     = "SetDebug",
60             default  = False,
61             typecast = bool,
62             message  = "Activation du mode debug lors de l'exécution",
63         )
64         self.defineRequiredParameter(
65             name     = "StoreSupplementaryCalculations",
66             default  = [],
67             typecast = tuple,
68             message  = "Liste de calculs supplémentaires à stocker et/ou effectuer",
69             listval  = [
70                 "CurrentState",
71                 "SimulatedObservationAtCurrentState",
72             ]
73         )
74         self.requireInputArguments(
75             mandatory= ("Xb", "HO"),
76         )
77         self.setAttributes(
78             tags=(
79                 "Checking",
80             ),
81             features=(
82                 "DerivativeFree",
83                 "ParallelAlgorithm",
84             ),
85         )
86
87     def run(self, Xb=None, Y=None, U=None, HO=None, EM=None, CM=None, R=None, B=None, Q=None, Parameters=None):
88         self._pre_run(Parameters, Xb, Y, U, HO, EM, CM, R, B, Q)
89         #
90         Hm = HO["Direct"].appliedTo
91         #
92         X0 = copy.copy( Xb )
93         #
94         # ----------
95         __s = self._parameters["ShowElementarySummary"]
96         __p = self._parameters["NumberOfPrintedDigits"]
97         __r = self._parameters["NumberOfRepetition"]
98         #
99         __marge = 5 * u" "
100         __flech = 3 * "=" + "> "
101         msgs  = ("\n")  # 1
102         if len(self._parameters["ResultTitle"]) > 0:
103             __rt = str(self._parameters["ResultTitle"])
104             msgs += (__marge + "====" + "=" * len(__rt) + "====\n")
105             msgs += (__marge + "    " + __rt + "\n")
106             msgs += (__marge + "====" + "=" * len(__rt) + "====\n")
107         else:
108             msgs += (__marge + "%s\n"%self._name)
109             msgs += (__marge + "%s\n"%("=" * len(self._name),))
110         #
111         msgs += ("\n")
112         msgs += (__marge + "This test allows to analyze the (repetition of the) launch of some\n")
113         msgs += (__marge + "given simulation operator F, applied to one single vector argument x,\n")
114         msgs += (__marge + "in a parallel way.\n")
115         msgs += (__marge + "The output shows simple statistics related to its successful execution,\n")
116         msgs += (__marge + "or related to the similarities of repetition of its execution.\n")
117         msgs += ("\n")
118         msgs += (__flech + "Information before launching:\n")
119         msgs += (__marge + "-----------------------------\n")
120         msgs += ("\n")
121         msgs += (__marge + "Characteristics of input vector X, internally converted:\n")
122         msgs += (__marge + "  Type...............: %s\n")%type( X0 )
123         msgs += (__marge + "  Length of vector...: %i\n")%max(numpy.ravel( X0 ).shape)
124         msgs += (__marge + "  Minimum value......: %." + str(__p) + "e\n")%numpy.min(  X0 )
125         msgs += (__marge + "  Maximum value......: %." + str(__p) + "e\n")%numpy.max(  X0 )
126         msgs += (__marge + "  Mean of vector.....: %." + str(__p) + "e\n")%numpy.mean( X0, dtype=mfp )
127         msgs += (__marge + "  Standard error.....: %." + str(__p) + "e\n")%numpy.std(  X0, dtype=mfp )
128         msgs += (__marge + "  L2 norm of vector..: %." + str(__p) + "e\n")%numpy.linalg.norm( X0 )
129         msgs += ("\n")
130         msgs += (__marge + "%s\n\n"%("-" * 75,))
131         #
132         if self._parameters["SetDebug"]:
133             CUR_LEVEL = logging.getLogger().getEffectiveLevel()
134             logging.getLogger().setLevel(logging.DEBUG)
135             if __r > 1:
136                 msgs += (__flech + "Beginning of repeated evaluation, activating debug\n")
137             else:
138                 msgs += (__flech + "Beginning of evaluation, activating debug\n")
139         else:
140             if __r > 1:
141                 msgs += (__flech + "Beginning of repeated evaluation, without activating debug\n")
142             else:
143                 msgs += (__flech + "Beginning of evaluation, without activating debug\n")
144         msgs += ("\n")
145         msgs += (__marge + "%s\n"%("-" * 75,))
146         print(msgs)  # 1
147         #
148         # ----------
149         HO["Direct"].disableAvoidingRedundancy()
150         # ----------
151         Ys = []
152         Xs = []
153         msgs  = (__marge + "Appending the input vector to the agument set to be evaluated in parallel\n")  # 2-1
154         for i in range(__r):
155             if self._toStore("CurrentState"):
156                 self.StoredVariables["CurrentState"].store( X0 )
157             Xs.append( X0 )
158             if __s:
159                 # msgs += ("\n")
160                 if __r > 1:
161                     msgs += (__marge + "  Appending step number %i on a total of %i\n"%(i + 1, __r))
162         #
163         msgs += ("\n")
164         msgs += (__marge + "%s\n\n"%("-" * 75,))
165         msgs += (__flech + "Launching operator parallel evaluation for %i states\n"%__r)
166         print(msgs)  # 2-1
167         #
168         Ys = Hm( Xs, argsAsSerie = True )
169         #
170         msgs  = ("\n")  # 2-2
171         msgs += (__flech + "End of operator parallel evaluation for %i states\n"%__r)
172         msgs += ("\n")
173         msgs += (__marge + "%s\n"%("-" * 75,))
174         print(msgs)  # 2-2
175         #
176         # ----------
177         HO["Direct"].enableAvoidingRedundancy()
178         # ----------
179         #
180         msgs  = ("")  # 3
181         if self._parameters["SetDebug"]:
182             if __r > 1:
183                 msgs += (__flech + "End of repeated evaluation, deactivating debug if necessary\n")
184             else:
185                 msgs += (__flech + "End of evaluation, deactivating debug if necessary\n")
186             logging.getLogger().setLevel(CUR_LEVEL)
187         else:
188             if __r > 1:
189                 msgs += (__flech + "End of repeated evaluation, without deactivating debug\n")
190             else:
191                 msgs += (__flech + "End of evaluation, without deactivating debug\n")
192         #
193         if __s or self._toStore("SimulatedObservationAtCurrentState"):
194             for i in range(self._parameters["NumberOfRepetition"]):
195                 if __s:
196                     msgs += ("\n")
197                     msgs += (__marge + "%s\n\n"%("-" * 75,))
198                     if self._parameters["NumberOfRepetition"] > 1:
199                         msgs += (__flech + "Repetition step number %i on a total of %i\n"%(i + 1, self._parameters["NumberOfRepetition"]))  # noqa: E501
200                 #
201                 Yn = Ys[i]
202                 if __s:
203                     msgs += ("\n")
204                     msgs += (__flech + "Information after evaluation:\n")
205                     msgs += ("\n")
206                     msgs += (__marge + "Characteristics of simulated output vector Y=F(X), to compare to others:\n")
207                     msgs += (__marge + "  Type...............: %s\n")%type( Yn )
208                     msgs += (__marge + "  Length of vector...: %i\n")%max(numpy.ravel( Yn ).shape)
209                     msgs += (__marge + "  Minimum value......: %." + str(__p) + "e\n")%numpy.min(  Yn )
210                     msgs += (__marge + "  Maximum value......: %." + str(__p) + "e\n")%numpy.max(  Yn )
211                     msgs += (__marge + "  Mean of vector.....: %." + str(__p) + "e\n")%numpy.mean( Yn, dtype=mfp )  # noqa: E501
212                     msgs += (__marge + "  Standard error.....: %." + str(__p) + "e\n")%numpy.std(  Yn, dtype=mfp )  # noqa: E501
213                     msgs += (__marge + "  L2 norm of vector..: %." + str(__p) + "e\n")%numpy.linalg.norm( Yn )
214                     #
215                 if self._toStore("SimulatedObservationAtCurrentState"):
216                     self.StoredVariables["SimulatedObservationAtCurrentState"].store( numpy.ravel(Yn) )
217         #
218         msgs += ("\n")
219         msgs += (__marge + "%s\n"%("-" * 75,))
220         #
221         if __r > 1:
222             msgs += ("\n")
223             msgs += (__flech + "Launching statistical summary calculation for %i states\n"%__r)
224             msgs += ("\n")
225             msgs += (__marge + "%s\n"%("-" * 75,))
226             msgs += ("\n")
227             msgs += (__flech + "Statistical analysis of the outputs obtained through parallel repeated evaluations\n")  # noqa: E501
228             msgs += ("\n")
229             msgs += (__marge + "(Remark: numbers that are (about) under %.0e represent 0 to machine precision)\n"%mpr)  # noqa: E501
230             msgs += ("\n")
231             Yy = numpy.array( Ys )
232             msgs += (__marge + "Number of evaluations...........................: %i\n")%len( Ys )
233             msgs += ("\n")
234             msgs += (__marge + "Characteristics of the whole set of outputs Y:\n")
235             msgs += (__marge + "  Size of each of the outputs...................: %i\n")%Ys[0].size
236             msgs += (__marge + "  Minimum value of the whole set of outputs.....: %." + str(__p) + "e\n")%numpy.min(  Yy )  # noqa: E501
237             msgs += (__marge + "  Maximum value of the whole set of outputs.....: %." + str(__p) + "e\n")%numpy.max(  Yy )  # noqa: E501
238             msgs += (__marge + "  Mean of vector of the whole set of outputs....: %." + str(__p) + "e\n")%numpy.mean( Yy, dtype=mfp )  # noqa: E501
239             msgs += (__marge + "  Standard error of the whole set of outputs....: %." + str(__p) + "e\n")%numpy.std(  Yy, dtype=mfp )  # noqa: E501
240             msgs += ("\n")
241             Ym = numpy.mean( numpy.array( Ys ), axis=0, dtype=mfp )
242             msgs += (__marge + "Characteristics of the vector Ym, mean of the outputs Y:\n")
243             msgs += (__marge + "  Size of the mean of the outputs...............: %i\n")%Ym.size
244             msgs += (__marge + "  Minimum value of the mean of the outputs......: %." + str(__p) + "e\n")%numpy.min(  Ym )  # noqa: E501
245             msgs += (__marge + "  Maximum value of the mean of the outputs......: %." + str(__p) + "e\n")%numpy.max(  Ym )  # noqa: E501
246             msgs += (__marge + "  Mean of the mean of the outputs...............: %." + str(__p) + "e\n")%numpy.mean( Ym, dtype=mfp )  # noqa: E501
247             msgs += (__marge + "  Standard error of the mean of the outputs.....: %." + str(__p) + "e\n")%numpy.std(  Ym, dtype=mfp )  # noqa: E501
248             msgs += ("\n")
249             Ye = numpy.mean( numpy.array( Ys ) - Ym, axis=0, dtype=mfp )
250             msgs += (__marge + "Characteristics of the mean of the differences between the outputs Y and their mean Ym:\n")  # noqa: E501
251             msgs += (__marge + "  Size of the mean of the differences...........: %i\n")%Ye.size
252             msgs += (__marge + "  Minimum value of the mean of the differences..: %." + str(__p) + "e\n")%numpy.min(  Ye )  # noqa: E501
253             msgs += (__marge + "  Maximum value of the mean of the differences..: %." + str(__p) + "e\n")%numpy.max(  Ye )  # noqa: E501
254             msgs += (__marge + "  Mean of the mean of the differences...........: %." + str(__p) + "e\n")%numpy.mean( Ye, dtype=mfp )  # noqa: E501
255             msgs += (__marge + "  Standard error of the mean of the differences.: %." + str(__p) + "e\n")%numpy.std(  Ye, dtype=mfp )  # noqa: E501
256             msgs += ("\n")
257             msgs += (__marge + "%s\n"%("-" * 75,))
258         #
259         msgs += ("\n")
260         msgs += (__marge + "End of the \"%s\" verification\n\n"%self._name)
261         msgs += (__marge + "%s\n"%("-" * 75,))
262         print(msgs)  # 3
263         #
264         self._post_run(HO, EM)
265         return 0
266
267 # ==============================================================================
268 if __name__ == "__main__":
269     print("\n AUTODIAGNOSTIC\n")