]> SALOME platform Git repositories - modules/adao.git/commitdiff
Salome HOME
Models and code update for crossobs, minor review update
authorJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Tue, 11 Jun 2024 14:53:39 +0000 (16:53 +0200)
committerJean-Philippe ARGAUD <jean-philippe.argaud@edf.fr>
Tue, 11 Jun 2024 14:53:39 +0000 (16:53 +0200)
src/daComposant/daCore/Aidsm.py
src/daComposant/daCore/BasicObjects.py
src/daComposant/daCore/Interfaces.py
src/daComposant/daCore/Persistence.py
src/daComposant/daCore/PlatformInfo.py
src/daComposant/daNumerics/Models/TwoDimensionalRosenbrockFunctionR1960.py
src/daComposant/daNumerics/pst4mod/modelica_libraries/around_simulation.py

index 6e0a336dfa51096b10e45ef5b8a5eb3964182823..0fa4cb6ec6c1845e2e9235b386fc71b0d404eb59 100644 (file)
@@ -109,6 +109,7 @@ class Aidsm(object):
             Checked              = False,
             ColMajor             = False,
             ColNames             = None,
+            CrossObs             = False,
             DataFile             = None,
             DiagonalSparseMatrix = None,
             ExtraArguments       = None,
@@ -125,6 +126,7 @@ class Aidsm(object):
             Script               = None,
             Stored               = False,
             String               = None,
+            SyncObs              = True,
             Template             = None,
             ThreeFunctions       = None,
             Variable             = None,
@@ -154,7 +156,8 @@ class Aidsm(object):
             elif Concept == "NoDebug":
                 self.setNoDebug()
             elif Concept == "Observer":
-                self.setObserver( Variable, Template, String, Script, Info, ObjectFunction, Scheduler )
+                self.setObserver( Variable, Template, String, Script, Info,
+                    ObjectFunction, CrossObs, SyncObs, Scheduler )
             elif Concept == "UserPostAnalysis":
                 self.setUserPostAnalysis( Template, String, Script )
             elif Concept == "SupplementaryParameters":
@@ -598,6 +601,8 @@ class Aidsm(object):
             Script         = None,
             Info           = None,
             ObjectFunction = None,
+            CrossObs       = False,
+            SyncObs        = True,
             Scheduler      = None ):
         "Définition d'un concept de calcul"
         Concept = "Observer"
@@ -610,6 +615,8 @@ class Aidsm(object):
             asScript    = self.__with_directory(Script),
             asObsObject = ObjectFunction,
             withInfo    = Info,
+            crossObs    = CrossObs,
+            syncObs     = SyncObs,
             scheduledBy = Scheduler,
             withAlgo    = self.__adaoObject["AlgorithmParameters"]
         ))
index 60a478cf03302c1483331a905204cdaa5e6df5c0..838cb1dd7bbdd5939c6f8feab97ddad63c30b8f9 100644 (file)
@@ -1512,7 +1512,8 @@ class AlgorithmAndParameters(object):
         "Renvoie la liste des attributs selon l'algorithme"
         return self.__algorithm.setAttributes()
 
-    def setObserver(self, __V, __O, __I, __S):
+    def setObserver(self, __V, __O, __I, __A, __S):
+        "Associe un observer à une variable unique"
         if self.__algorithm is None \
                 or isinstance(self.__algorithm, dict) \
                 or not hasattr(self.__algorithm, "StoredVariables"):
@@ -1520,7 +1521,24 @@ class AlgorithmAndParameters(object):
         if __V not in self.__algorithm:
             raise ValueError("An observer requires to be set on a variable named %s which does not exist."%__V)
         else:
-            self.__algorithm.StoredVariables[ __V ].setDataObserver( Scheduler      = __S, HookFunction   = __O, HookParameters = __I )
+            self.__algorithm.StoredVariables[ __V ].setDataObserver( HookFunction = __O, HookParameters = __I, Scheduler = __S )
+
+    def setCrossObserver(self, __V, __O, __I, __A, __S):
+        "Associe un observer à une collection ordonnée de variables"
+        if self.__algorithm is None \
+                or isinstance(self.__algorithm, dict) \
+                or not hasattr(self.__algorithm, "StoredVariables"):
+            raise ValueError("No observer can be build before choosing an algorithm.")
+        if not isinstance(__V, (list, tuple)):
+            raise ValueError("A cross observer requires to be set on a variable series which is not the case of %s."%__V)
+        if len(__V) != len(__I):
+            raise ValueError("The number of information fields has to be the same than the number of variables on which to set the observer.")
+        #
+        for __eV in __V:
+            if __eV not in self.__algorithm:
+                raise ValueError("An observer requires to be set on a variable named %s which does not exist."%__eV)
+            else:
+                self.__algorithm.StoredVariables[ __eV ].setDataObserver( HookFunction = __O, HookParameters = __I, Scheduler = __S, Order = __V, OSync = __A, DOVar = self.__algorithm.StoredVariables )
 
     def removeObserver(self, __V, __O, __A = False):
         if self.__algorithm is None \
@@ -1818,6 +1836,8 @@ class DataObserver(object):
                  asScript    = None,
                  asObsObject = None,
                  withInfo    = None,
+                 crossObs    = False,
+                 syncObs     = True,
                  scheduledBy = None,
                  withAlgo    = None ):
         """
@@ -1829,10 +1849,12 @@ class DataObserver(object):
         #
         if onVariable is None:
             raise ValueError("setting an observer has to be done over a variable name or a list of variable names, not over None.")
-        elif type(onVariable) in (tuple, list):
+        elif isinstance(onVariable, (tuple, list)):
             self.__V = tuple(map( str, onVariable ))
             if withInfo is None:
                 self.__I = self.__V
+            elif crossObs or isinstance(withInfo, (tuple, list)):
+                self.__I = withInfo
             else:
                 self.__I = (str(withInfo),) * len(self.__V)
         elif isinstance(onVariable, str):
@@ -1852,12 +1874,14 @@ class DataObserver(object):
             self.__O = __Function.getfunc()
         #
         for k in range(len(self.__V)):
-            ename = self.__V[k]
-            einfo = self.__I[k]
-            if ename not in withAlgo:
-                raise ValueError("An observer is asked to be set on a variable named %s which does not exist."%ename)
-            else:
-                withAlgo.setObserver(ename, self.__O, einfo, scheduledBy)
+            if self.__V[k] not in withAlgo:
+                raise ValueError("An observer is asked to be set on a variable named %s which does not exist."%self.__V[k])
+        #
+        if bool(crossObs):
+            withAlgo.setCrossObserver(self.__V, self.__O, self.__I, syncObs, scheduledBy)
+        else:
+            for k in range(len(self.__V)):
+                withAlgo.setObserver(self.__V[k], self.__O, self.__I[k], syncObs, scheduledBy)
 
     def __repr__(self):
         "x.__repr__() <==> repr(x)"
index eaa902471ee86c87e7914b793480f2b2da9f0b87..786683ab0925387348af885a6fe7a766440a4a96 100644 (file)
@@ -162,12 +162,14 @@ class _TUIViewer(GenericCaseViewer):
                 if k not in __local: continue                           # noqa: E701
                 __v = __local[k]
                 if __v is None: continue                                # noqa: E701
+                if   k == "SyncObs"              and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "Checked"              and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "ColMajor"             and not __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "CrossObs"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "InputFunctionAsMulti" and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "PerformanceProfile"   and     __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "noDetails":                        continue  # noqa: E241,E271,E272,E701
                 if isinstance(__v, Persistence.Persistence):
                     __v = __v.values()
@@ -555,7 +557,7 @@ class _SCDViewer(GenericCaseViewer):
                     __text += "%s_config['Data'] = %s\n"%(__command, __v)
                     __text = __text.replace("''", "'")
                     __vectorIsScript = True
-                elif __k in ('Stored', 'Checked', 'ColMajor', 'InputFunctionAsMulti', 'nextStep'):
+                elif __k in ('Stored', 'Checked', 'ColMajor', 'CrossObs', 'SyncObs', 'InputFunctionAsMulti', 'nextStep'):
                     if bool(__v):
                         __text += "%s_config['%s'] = '%s'\n"%(__command, __k, int(bool(__v)))
                 elif __k in ('PerformanceProfile', 'noDetails'):
@@ -723,12 +725,14 @@ class _ReportViewer(GenericCaseViewer):
                 if k not in __local: continue                           # noqa: E701
                 __v = __local[k]
                 if __v is None: continue                                # noqa: E701
+                if   k == "SyncObs"              and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "Checked"              and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "ColMajor"             and not __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "CrossObs"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "InputFunctionAsMulti" and not __v: continue  # noqa: E241,E271,E272,E701
-                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "PerformanceProfile"   and     __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "Stored"               and not __v: continue  # noqa: E241,E271,E272,E701
+                if   k == "nextStep"             and not __v: continue  # noqa: E241,E271,E272,E701
                 if   k == "noDetails":                        continue  # noqa: E241,E271,E272,E701
                 if   k == "Concept":                          continue  # noqa: E241,E271,E272,E701
                 if   k == "self":                             continue  # noqa: E241,E271,E272,E701
index 9bb55decc398efcc3d2b10aa67b1b401dd42ec2d..f814f3861ef62a364ab4ab19180c623f1e93fb2b 100644 (file)
@@ -100,9 +100,23 @@ class Persistence(object):
         if self.__dynamic:
             self.__replots()
         __step = len(self.__values) - 1
-        for hook, parameters, scheduler in self.__dataobservers:
+        for hook, parameters, scheduler, order, osync, dovar in self.__dataobservers:
             if __step in scheduler:
-                hook( self, parameters )
+                if order is None or dovar is None:
+                    hook( self, parameters )
+                else:
+                    if not isinstance(order, (list, tuple)):
+                        continue
+                    if not isinstance(dovar, dict):
+                        continue
+                    if not bool(osync):  # Async observation
+                        hook( self, parameters, order, dovar )
+                    else:  # Sync observations
+                        for v in order:
+                            if len(dovar[v]) != len(self):
+                                break
+                        else:
+                            hook( self, parameters, order, dovar )
 
     def pop(self, item=None):
         """
@@ -765,12 +779,13 @@ class Persistence(object):
             raise TypeError("Base type is incompatible with numpy")
 
     # ---------------------------------------------------------
-    def setDataObserver(self, HookFunction = None, HookParameters = None, Scheduler = None):
+    def setDataObserver(self, HookFunction = None, HookParameters = None, Scheduler = None, Order = None, OSync = True, DOVar = None):
         """
-        Association à la variable d'un triplet définissant un observer
+        Association à la variable d'un triplet définissant un observer.
 
-        Le Scheduler attendu est une fréquence, une simple liste d'index ou un
-        range des index.
+        Les variables Order et DOVar sont utilisées pour un observer
+        multi-variable. Le Scheduler attendu est une fréquence, une simple
+        liste d'index ou un range des index.
         """
         #
         # Vérification du Scheduler
@@ -787,13 +802,13 @@ class Persistence(object):
         #
         # Stockage interne de l'observer dans la variable
         # -----------------------------------------------
-        self.__dataobservers.append( [HookFunction, HookParameters, Schedulers] )
+        self.__dataobservers.append( [HookFunction, HookParameters, Schedulers, Order, OSync, DOVar] )
 
     def removeDataObserver(self, HookFunction = None, AllObservers = False):
         """
         Suppression d'un observer nommé sur la variable.
 
-        On peut donner dans HookFunction la meme fonction que lors de la
+        On peut donner dans HookFunction la même fonction que lors de la
         définition, ou un simple string qui est le nom de la fonction. Si
         AllObservers est vrai, supprime tous les observers enregistrés.
         """
@@ -808,7 +823,7 @@ class Persistence(object):
         #
         ih = -1
         index_to_remove = []
-        for [hf, hp, hs] in self.__dataobservers:
+        for [hf, _, _, _, _, _] in self.__dataobservers:
             ih = ih + 1
             if name is hf.__name__ or AllObservers:
                 index_to_remove.append( ih )
index 8777c01cecad38a47cc9649e5db56c8c48fb7f76..147d61352ac6938a8d0550e131a04726bbb2de3e 100644 (file)
@@ -72,6 +72,7 @@ class PathManagement(object):
         parent = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
         self.__paths = {}
         self.__paths["daNumerics"] = os.path.join(parent, "daNumerics")
+        self.__paths["pst4mod"] = os.path.join(parent, "daNumerics", "pst4mod")
         #
         for v in self.__paths.values():
             if os.path.isdir(v):
index d7c36e2412af80e679ef901d42b44a3e27d7210f..7f7b27a68e402db0709387ff2533181ee77949d4 100644 (file)
@@ -101,8 +101,12 @@ class LocalTest(unittest.TestCase):
     def test001(self):
         numpy.random.seed(123456789)
         Equation = TwoDimensionalRosenbrockFunctionR1960()
-        optimum = Equation.ValueZ( [1, 1] )
-        self.assertTrue( max(optimum) <= 0.)
+
+        optimum = Equation.FunctionH( [1, 1] )
+        self.assertTrue( max(optimum.flat) <= 0.)
+
+        optimum = Equation.FunctionH( [0.5, 0.25], a=0.5 )
+        self.assertTrue( max(optimum.flat) <= 0.)
 
     def tearDown(cls):
         print("\n    Tests OK\n")
index 3785b4d30c7cee87759f4bed4e5dfd0a15da5eff..8b605e48780e224573497726a6b8674ce4d4f24a 100644 (file)
@@ -628,11 +628,11 @@ class Around_Simulation(object):
                     except KeyError: #The variable is not found
 
                         try:
-                            node_pos = re.search("\[\d+\]",res_name_var).span() #Position of the node number if any (in case the error is due to a remesh of the model)
+                            node_pos = re.search(r"\[\d+\]",res_name_var).span() #Position of the node number if any (in case the error is due to a remesh of the model)
                         except AttributeError: #No node number found
 
                             try:
-                                node_pos = re.search("\[\]",res_name_var).span() #Position of empty brakets (all array values are due)
+                                node_pos = re.search(r"\[\]",res_name_var).span() #Position of empty brakets (all array values are due)
                             except AttributeError :
                                 pass
                             else:
@@ -640,7 +640,7 @@ class Around_Simulation(object):
                                     print('Filters and prefixes still have to be implemented for arrays of unknown size')
                                 else :
                                     print(f'{name_var}: unknown size -> Taking all values in .mat (if any)')
-                                    tmp = f'{res_name_var[:node_pos[0]]}\[\d\{res_name_var[node_pos[0]+1:]}'
+                                    tmp = rf'{res_name_var[:node_pos[0]]}\[\d\{res_name_var[node_pos[0]+1:]}'
                                     expanded_vars = structData.varNames(tmp)
                                     for tmp_var in expanded_vars :
                                         self.__dict_iter_var[tmp_var] = structData.values(tmp_var)[1][mom]