66import numpy as np
77import pytest
88from conftest import ComplexGeneratorFromMatrix , GeneratorFromMatrix
9- from scipy .linalg import eig , eigh
9+ from scipy .linalg import eig , eigh , ldl , solve_triangular
10+ from scipy .sparse .linalg import LinearOperator , eigsh
1011
1112
12- class CustomGeneoCoarseSpaceDenseBuilder (Htool .VirtualGeneoCoarseSpaceDenseBuilder ):
13+ class CustomDenseGeneoCoarseSpaceDenseBuilder (
14+ Htool .VirtualGeneoCoarseSpaceDenseBuilder
15+ ):
1316 def compute_coarse_space (self , Ai , Bi ):
1417 coarse_space = None
1518 if self .symmetry == "S" or self .symmetry == "H" :
@@ -30,6 +33,102 @@ def compute_coarse_space(self, Ai, Bi):
3033 self .set_coarse_space (coarse_space )
3134
3235
36+ class CustomGeneoCoarseSpaceBuilder (Htool .VirtualGeneoCoarseSpaceBuilder ):
37+ class DirichletHMatrix (LinearOperator ):
38+ def __init__ (self , hmatrix_callback , size , dtype ):
39+ self .hmatrix_callback = hmatrix_callback
40+ self .shape = (size , size )
41+ self .dtype = dtype
42+
43+ def _matvec (self , x ):
44+ return self .hmatrix_callback (x )
45+
46+ class DenseNeumannMatrix (LinearOperator ):
47+ def __init__ (self , Bi ):
48+ self .L , self .D , self .perm = ldl (Bi )
49+ self .shape = Bi .shape
50+ self .dtype = Bi .dtype
51+
52+ def _matvec (self , x ):
53+ tmp = solve_triangular (self .L [self .perm , :], x [self .perm ], lower = True )
54+ for index , coef in enumerate (self .D .diagonal ()):
55+ # if coef>1e-4:
56+ tmp [index ] /= coef
57+ # else :
58+ # tmp[index]=0
59+ res = np .empty_like (x )
60+ res [self .perm ] = solve_triangular (
61+ self .L [self .perm , :], tmp , lower = True , trans = "T"
62+ )
63+ return res
64+
65+ def __init__ (
66+ self ,
67+ size_wo_overlap ,
68+ size_with_overlap ,
69+ Ai ,
70+ Bi ,
71+ geneo_nu = 2 ,
72+ geneo_threshold = None ,
73+ ):
74+ if not geneo_threshold :
75+ Htool .VirtualGeneoCoarseSpaceBuilder .__init__ (
76+ self ,
77+ size_wo_overlap ,
78+ size_with_overlap ,
79+ Ai ,
80+ geneo_nu = geneo_nu ,
81+ )
82+ else :
83+ Htool .VirtualGeneoCoarseSpaceBuilder .__init__ (
84+ self ,
85+ size_wo_overlap ,
86+ size_with_overlap ,
87+ Ai ,
88+ geneo_threshold = geneo_threshold ,
89+ )
90+ self .local_size = size_with_overlap
91+ self .Bi = Bi
92+ self .Ai = Ai
93+
94+ def compute_coarse_space (self , hmatrix_callback ):
95+ self .coarse_space = None
96+ self .eigenvalues = None
97+
98+ if self .geneo_threshold > 0 :
99+ [w , v ] = eigsh (
100+ self .Bi ,
101+ 10 ,
102+ M = self .DirichletHMatrix (
103+ hmatrix_callback , self .local_size , np .dtype ("float64" )
104+ ),
105+ OPinv = self .DenseNeumannMatrix (self .Bi ),
106+ return_eigenvectors = True ,
107+ sigma = 0 ,
108+ )
109+ else :
110+ [w , v ] = eigsh (
111+ self .Bi ,
112+ self .geneo_nu ,
113+ M = self .DirichletHMatrix (
114+ hmatrix_callback , self .local_size , np .dtype ("float64" )
115+ ),
116+ OPinv = self .DenseNeumannMatrix (self .Bi ),
117+ return_eigenvectors = True ,
118+ sigma = 0 ,
119+ )
120+ idx = w .argsort ()
121+ if self .geneo_threshold > 0 :
122+ nb_eig = (w < 1.0 / self .geneo_threshold ).sum ()
123+ self .coarse_space = v [:, idx [0 :nb_eig ]].real
124+ self .eigenvalues = 1.0 / w [idx [:]]
125+ else :
126+ self .coarse_space = v [:, idx [0 : self .geneo_nu ]]
127+ self .eigenvalues = 1.0 / w [idx [:]]
128+
129+ self .set_coarse_space (self .coarse_space )
130+
131+
33132@pytest .mark .parametrize ("epsilon" , [1e-6 ])
34133@pytest .mark .parametrize ("eta" , [10 ])
35134@pytest .mark .parametrize ("tol" , [1e-6 ])
@@ -96,6 +195,70 @@ def compute_coarse_space(self, Ai, Bi):
96195 "additive" ,
97196 "geneo_threshold" ,
98197 ),
198+ (
199+ 1 ,
200+ "S" ,
201+ "DDMWithHMatrixPlusOverlap" ,
202+ "asm" ,
203+ "additive" ,
204+ "custom_dense_geneo_nu" ,
205+ ),
206+ (
207+ 1 ,
208+ "S" ,
209+ "DDMWithHMatrixPlusOverlap" ,
210+ "ras" ,
211+ "additive" ,
212+ "custom_dense_geneo_nu" ,
213+ ),
214+ (
215+ 10 ,
216+ "S" ,
217+ "DDMWithHMatrixPlusOverlap" ,
218+ "asm" ,
219+ "additive" ,
220+ "custom_dense_geneo_nu" ,
221+ ),
222+ (
223+ 10 ,
224+ "S" ,
225+ "DDMWithHMatrixPlusOverlap" ,
226+ "ras" ,
227+ "additive" ,
228+ "custom_dense_geneo_nu" ,
229+ ),
230+ (
231+ 1 ,
232+ "S" ,
233+ "DDMWithHMatrixPlusOverlap" ,
234+ "asm" ,
235+ "additive" ,
236+ "custom_dense_geneo_threshold" ,
237+ ),
238+ (
239+ 1 ,
240+ "S" ,
241+ "DDMWithHMatrixPlusOverlap" ,
242+ "ras" ,
243+ "additive" ,
244+ "custom_dense_geneo_threshold" ,
245+ ),
246+ (
247+ 10 ,
248+ "S" ,
249+ "DDMWithHMatrixPlusOverlap" ,
250+ "asm" ,
251+ "additive" ,
252+ "custom_dense_geneo_threshold" ,
253+ ),
254+ (
255+ 10 ,
256+ "S" ,
257+ "DDMWithHMatrixPlusOverlap" ,
258+ "ras" ,
259+ "additive" ,
260+ "custom_dense_geneo_threshold" ,
261+ ),
99262 (1 , "S" , "DDMWithHMatrixPlusOverlap" , "asm" , "additive" , "custom_geneo_nu" ),
100263 (1 , "S" , "DDMWithHMatrixPlusOverlap" , "ras" , "additive" , "custom_geneo_nu" ),
101264 (
@@ -156,6 +319,14 @@ def compute_coarse_space(self, Ai, Bi):
156319 (1 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "geneo_threshold" ),
157320 (10 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "geneo_threshold" ),
158321 (10 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "geneo_threshold" ),
322+ (1 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_dense_geneo_nu" ),
323+ (1 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "custom_dense_geneo_nu" ),
324+ (10 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_dense_geneo_nu" ),
325+ (10 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "custom_dense_geneo_nu" ),
326+ (1 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_dense_geneo_threshold" ),
327+ (1 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "custom_dense_geneo_threshold" ),
328+ (10 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_dense_geneo_threshold" ),
329+ (10 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "custom_dense_geneo_threshold" ),
159330 (1 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_geneo_nu" ),
160331 (1 , "S" , "DDMWithHMatrix" , "ras" , "additive" , "custom_geneo_nu" ),
161332 (10 , "S" , "DDMWithHMatrix" , "asm" , "additive" , "custom_geneo_nu" ),
@@ -383,7 +554,24 @@ def test_ddm_solver(
383554 geneo_threshold = 100 ,
384555 )
385556 elif geneo_type == "custom_geneo_nu" :
386- geneo_space_operator_builder = CustomGeneoCoarseSpaceDenseBuilder (
557+ print ("ICI" )
558+ geneo_space_operator_builder = CustomGeneoCoarseSpaceBuilder (
559+ local_size_wo_overlap ,
560+ local_size_with_overlap ,
561+ default_approximation .block_diagonal_hmatrix ,
562+ local_neumann_matrix ,
563+ geneo_nu = 2 ,
564+ )
565+ elif geneo_type == "custom_geneo_threshold" :
566+ geneo_space_operator_builder = CustomGeneoCoarseSpaceBuilder (
567+ local_size_wo_overlap ,
568+ local_size_with_overlap ,
569+ default_approximation .block_diagonal_hmatrix ,
570+ local_neumann_matrix ,
571+ geneo_threshold = 100 ,
572+ )
573+ elif geneo_type == "custom_dense_geneo_nu" :
574+ geneo_space_operator_builder = CustomDenseGeneoCoarseSpaceDenseBuilder (
387575 local_size_wo_overlap ,
388576 local_size_with_overlap ,
389577 default_approximation .block_diagonal_hmatrix .to_dense (),
@@ -392,8 +580,8 @@ def test_ddm_solver(
392580 UPLO ,
393581 geneo_nu = 2 ,
394582 )
395- elif geneo_type == "custom_geneo_threshold " :
396- geneo_space_operator_builder = CustomGeneoCoarseSpaceDenseBuilder (
583+ elif geneo_type == "custom_dense_geneo_threshold " :
584+ geneo_space_operator_builder = CustomDenseGeneoCoarseSpaceDenseBuilder (
397585 local_size_wo_overlap ,
398586 local_size_with_overlap ,
399587 default_approximation .block_diagonal_hmatrix .to_dense (),
0 commit comments