1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2023 EDF R&D
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.
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.
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
19 # See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 # Author: Jean-Philippe Argaud, jean-philippe.argaud@edf.fr, EDF R&D
24 Empirical Interpolation Method DEIM & lcDEIM
26 __author__ = "Jean-Philippe ARGAUD"
28 import numpy, scipy, logging
29 import daCore.Persistence
30 from daCore.NumericObjects import FindIndexesFromNames
32 # ==============================================================================
33 def DEIM_offline(selfA, EOS = None, Verbose = False):
35 Établissement de la base
40 if isinstance(EOS, (numpy.ndarray, numpy.matrix)):
41 __EOS = numpy.asarray(EOS)
42 elif isinstance(EOS, (list, tuple, daCore.Persistence.Persistence)):
43 __EOS = numpy.stack([numpy.ravel(_sn) for _sn in EOS], axis=1)
44 # __EOS = numpy.asarray(EOS).T
46 raise ValueError("EnsembleOfSnapshots has to be an array/matrix (each column being a vector) or a list/tuple (each element being a vector).")
47 __dimS, __nbmS = __EOS.shape
48 logging.debug("%s Building a RB using a collection of %i snapshots of individual size of %i"%(selfA._name,__nbmS,__dimS))
50 if selfA._parameters["Variant"] in ["DEIM", "PositioningByDEIM"]:
54 if __LcCsts and "ExcludeLocations" in selfA._parameters:
55 __ExcludedMagicPoints = selfA._parameters["ExcludeLocations"]
57 __ExcludedMagicPoints = ()
58 if __LcCsts and "NameOfLocations" in selfA._parameters:
59 if isinstance(selfA._parameters["NameOfLocations"], (list, numpy.ndarray, tuple)) and len(selfA._parameters["NameOfLocations"]) == __dimS:
60 __NameOfLocations = selfA._parameters["NameOfLocations"]
62 __NameOfLocations = ()
64 __NameOfLocations = ()
65 if __LcCsts and len(__ExcludedMagicPoints) > 0:
66 __ExcludedMagicPoints = FindIndexesFromNames( __NameOfLocations, __ExcludedMagicPoints )
67 __ExcludedMagicPoints = numpy.ravel(numpy.asarray(__ExcludedMagicPoints, dtype=int))
68 __IncludedMagicPoints = numpy.setdiff1d(
69 numpy.arange(__EOS.shape[0]),
70 __ExcludedMagicPoints,
74 __IncludedMagicPoints = []
76 if "MaximumNumberOfLocations" in selfA._parameters and "MaximumRBSize" in selfA._parameters:
77 selfA._parameters["MaximumRBSize"] = min(selfA._parameters["MaximumNumberOfLocations"],selfA._parameters["MaximumRBSize"])
78 elif "MaximumNumberOfLocations" in selfA._parameters:
79 selfA._parameters["MaximumRBSize"] = selfA._parameters["MaximumNumberOfLocations"]
80 elif "MaximumRBSize" in selfA._parameters:
83 selfA._parameters["MaximumRBSize"] = __nbmS
84 __maxM = min(selfA._parameters["MaximumRBSize"], __dimS, __nbmS)
85 if "ErrorNormTolerance" in selfA._parameters:
86 selfA._parameters["EpsilonEIM"] = selfA._parameters["ErrorNormTolerance"]
88 selfA._parameters["EpsilonEIM"] = 1.e-2
90 __U, __vs, _ = scipy.linalg.svd( __EOS )
91 __rhoM = numpy.compress(__vs > selfA._parameters["EpsilonEIM"], __U, axis=1)
92 __lVs, __svdM = __rhoM.shape
93 assert __lVs == __dimS, "Différence entre lVs et dim(EOS)"
94 __qivs = (1. - __vs[:__svdM].cumsum()/__vs.sum())
95 __maxM = min(__maxM,__svdM)
97 if __LcCsts and len(__IncludedMagicPoints) > 0:
98 __im = numpy.argmax( numpy.abs(
99 numpy.take(__rhoM[:,0], __IncludedMagicPoints, mode='clip')
102 __im = numpy.argmax( numpy.abs(
106 __mu = [None,] # Convention
108 __Q = __rhoM[:,0].reshape((-1,1))
111 __M = 1 # Car le premier est déjà construit
112 __errors.append(__qivs[0])
118 __restrictedQi = __Q[__I,:]
120 __Qi_inv = numpy.linalg.inv(__restrictedQi)
122 __Qi_inv = 1. / __restrictedQi
124 __restrictedrhoMi = __rhoM[__I,__M].reshape((-1,1))
127 __interpolator = numpy.dot(__Q,numpy.dot(__Qi_inv,__restrictedrhoMi))
129 __interpolator = numpy.outer(__Q,numpy.outer(__Qi_inv,__restrictedrhoMi))
131 __residuM = __rhoM[:,__M].reshape((-1,1)) - __interpolator
133 if __LcCsts and len(__IncludedMagicPoints) > 0:
134 __im = numpy.argmax( numpy.abs(
135 numpy.take(__residuM, __IncludedMagicPoints, mode='clip')
138 __im = numpy.argmax( numpy.abs(
141 __Q = numpy.column_stack((__Q, __rhoM[:,__M]))
144 __errors.append(__qivs[__M])
145 __mu.append(None) # Convention
149 #--------------------------
150 if __errors[-1] < selfA._parameters["EpsilonEIM"]:
151 logging.debug("%s %s (%.1e)"%(selfA._name,"The convergence is obtained when reaching the required EIM tolerance",selfA._parameters["EpsilonEIM"]))
153 logging.debug("%s %s (%i)"%(selfA._name,"The convergence is obtained when reaching the maximum number of RB dimension",__maxM))
154 logging.debug("%s The RB of size %i has been correctly build"%(selfA._name,__Q.shape[1]))
155 logging.debug("%s There are %i points that have been excluded from the potential optimal points"%(selfA._name,len(__ExcludedMagicPoints)))
156 if hasattr(selfA, "StoredVariables"):
157 selfA.StoredVariables["OptimalPoints"].store( __I )
158 if selfA._toStore("ReducedBasis"):
159 selfA.StoredVariables["ReducedBasis"].store( __Q )
160 if selfA._toStore("Residus"):
161 selfA.StoredVariables["Residus"].store( __errors )
162 if selfA._toStore("ExcludedPoints"):
163 selfA.StoredVariables["ExcludedPoints"].store( __ExcludedMagicPoints )
164 if selfA._toStore("SingularValues"):
165 selfA.StoredVariables["SingularValues"].store( __vs )
167 return __mu, __I, __Q, __errors
169 # ==============================================================================
170 # DEIM_online == EIM_online
171 # ==============================================================================
172 if __name__ == "__main__":
173 print('\n AUTODIAGNOSTIC\n')