1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2008-2024 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
23 import sys, unittest, numpy
25 # ==============================================================================
26 class TwoDimensionalInverseDistanceCS2010:
28 Two-dimensional inverse distance function of parameter µ=(µ1,µ2):
30 s(x,y,µ) = 1 / sqrt( (x-µ1)² + (y-µ2)² + 0.1² )
32 avec (x,y) ∈ [0.1,0.9]² et µ=(µ1,µ2) ∈ [-1,-0.01]².
34 This is the non-linear parametric function (3.38) of the reference:
35 Chaturantabut, S., Sorensen, D. C.,
36 Nonlinear Model Reduction via Discrete Empirical Interpolation,
37 SIAM Journal on Scientific Computing, 32(5), pp. 2737-2764 (2010).
39 def __init__(self, nx: int = 20, ny: int = 20):
40 "Définition du maillage spatial"
43 self.x = numpy.linspace(0.1, 0.9, self.nx, dtype=float)
44 self.y = numpy.linspace(0.1, 0.9, self.ny, dtype=float)
46 def FunctionH(self, XX ):
47 "Fonction simulation pour un paramètre donné"
48 __mu1, __mu2 = numpy.ravel(XX)
50 __x, __y = numpy.meshgrid( self.x, self.y )
51 __sxymu = 1. / numpy.sqrt( (__x - __mu1)**2 + (__y - __mu2)**2 + 0.1**2 )
56 "Renvoie le maillage spatial"
59 def get_sample_of_mu(self, ns1: int = 20, ns2: int = 20):
60 "Renvoie l'échantillonnage paramétrique régulier"
61 smu1 = numpy.linspace(-1, -0.01, ns1, dtype=float)
62 smu2 = numpy.linspace(-1, -0.01, ns2, dtype=float)
63 smu = numpy.array([(mu1, mu2) for mu1 in smu1 for mu2 in smu2])
66 def get_random_sample_of_mu(self, ns1: int = 1, ns2: int = 1):
67 "Renvoie l'échantillonnage paramétrique aléatoire"
69 for i in range(ns1 * ns2):
70 smu1 = numpy.random.uniform(-1, -0.01)
71 smu2 = numpy.random.uniform(-1, -0.01)
72 smu.append((smu1, smu2))
73 smu = numpy.array(smu)
76 def get_bounds_on_space(self):
77 "Renvoie les bornes sur le maillage spatial"
78 return [[min(self.x), max(self.x)], [min(self.y), max(self.y)]]
80 def get_bounds_on_parameter(self):
81 "Renvoie les bornes sur le maillage paramétrique"
82 return [[-1, -0.01]] * 2
84 OneRealisation = FunctionH
86 # ==============================================================================
87 class LocalTest(unittest.TestCase):
90 print('\nAUTODIAGNOSTIC\n==============\n')
91 print(" " + TwoDimensionalInverseDistanceCS2010().__doc__.strip())
94 numpy.random.seed(123456789)
95 Equation = TwoDimensionalInverseDistanceCS2010()
96 for mu in Equation.get_sample_of_mu(5, 5):
97 solution = Equation.OneRealisation( mu )
98 # Nappe maximale au coin (0,0)
99 self.assertTrue(numpy.max(solution.flat) <= solution[0, 0])
100 # Nappe minimale au coin [-1,-1]
101 self.assertTrue(numpy.min(solution.flat) >= solution[-1, -1])
104 print("\n Tests OK\n")
106 # ==============================================================================
107 if __name__ == "__main__":
108 sys.stderr = sys.stdout
109 unittest.main(verbosity=0)