1 /******************************************************************************
2 * Copyright 1998-2019 Lawrence Livermore National Security, LLC and other
3 * HYPRE Project Developers. See the top-level COPYRIGHT file for details.
4 *
5 * SPDX-License-Identifier: (Apache-2.0 OR MIT)
6 ******************************************************************************/
7
8 /******************************************************************************
9 *
10 * Schwarz functions
11 *
12 *****************************************************************************/
13
14 #include "_hypre_parcsr_ls.h"
15 #include "schwarz.h"
16
17 /*--------------------------------------------------------------------------
18 * hypre_SchwarzCreate
19 *--------------------------------------------------------------------------*/
20
21 void *
hypre_SchwarzCreate()22 hypre_SchwarzCreate()
23 {
24 hypre_SchwarzData *schwarz_data;
25
26 HYPRE_Int variant;
27 HYPRE_Int domain_type;
28 HYPRE_Int overlap;
29 HYPRE_Int num_functions;
30 HYPRE_Int use_nonsymm;
31 HYPRE_Real relax_weight;
32
33 /*-----------------------------------------------------------------------
34 * Setup default values for parameters
35 *-----------------------------------------------------------------------*/
36
37 /* setup params */
38 variant = 0; /* multiplicative Schwarz */
39 overlap = 1; /* minimal overlap */
40 domain_type = 2; /* domains generated by agglomeration */
41 num_functions = 1;
42 use_nonsymm = 0;
43 relax_weight = 1.0;
44
45 schwarz_data = hypre_CTAlloc(hypre_SchwarzData, 1, HYPRE_MEMORY_HOST);
46
47 hypre_SchwarzSetVariant(schwarz_data, variant);
48 hypre_SchwarzSetDomainType(schwarz_data, domain_type);
49 hypre_SchwarzSetOverlap(schwarz_data, overlap);
50 hypre_SchwarzSetNumFunctions(schwarz_data, num_functions);
51 hypre_SchwarzSetNonSymm(schwarz_data, use_nonsymm);
52 hypre_SchwarzSetRelaxWeight(schwarz_data, relax_weight);
53
54 hypre_SchwarzDataDomainStructure(schwarz_data) = NULL;
55 hypre_SchwarzDataABoundary(schwarz_data) = NULL;
56 hypre_SchwarzDataScale(schwarz_data) = NULL;
57 hypre_SchwarzDataVtemp(schwarz_data) = NULL;
58 hypre_SchwarzDataDofFunc(schwarz_data) = NULL;
59
60 return (void *) schwarz_data;
61 }
62
63 /*--------------------------------------------------------------------------
64 * hypre_SchwarzDestroy
65 *--------------------------------------------------------------------------*/
66
67 HYPRE_Int
hypre_SchwarzDestroy(void * data)68 hypre_SchwarzDestroy( void *data )
69 {
70 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
71
72 if (hypre_SchwarzDataScale(schwarz_data))
73 hypre_TFree(hypre_SchwarzDataScale(schwarz_data), HYPRE_MEMORY_HOST);
74 if (hypre_SchwarzDataDofFunc(schwarz_data))
75 hypre_TFree(hypre_SchwarzDataDofFunc(schwarz_data), HYPRE_MEMORY_HOST);
76 hypre_CSRMatrixDestroy(hypre_SchwarzDataDomainStructure(schwarz_data));
77 if (hypre_SchwarzDataVariant(schwarz_data) == 3)
78 hypre_CSRMatrixDestroy(hypre_SchwarzDataABoundary(schwarz_data));
79 hypre_ParVectorDestroy(hypre_SchwarzDataVtemp(schwarz_data));
80
81 if (hypre_SchwarzDataPivots(schwarz_data))
82 hypre_TFree(hypre_SchwarzDataPivots(schwarz_data), HYPRE_MEMORY_HOST);
83
84
85 hypre_TFree(schwarz_data, HYPRE_MEMORY_HOST);
86 return hypre_error_flag;
87
88 }
89
90 HYPRE_Int
hypre_SchwarzSetup(void * schwarz_vdata,hypre_ParCSRMatrix * A,hypre_ParVector * f,hypre_ParVector * u)91 hypre_SchwarzSetup(void *schwarz_vdata,
92 hypre_ParCSRMatrix *A,
93 hypre_ParVector *f,
94 hypre_ParVector *u )
95 {
96
97 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) schwarz_vdata;
98 HYPRE_Int *dof_func;
99 HYPRE_Real *scale;
100 hypre_CSRMatrix *domain_structure;
101 hypre_CSRMatrix *A_boundary;
102 hypre_ParVector *Vtemp;
103
104 HYPRE_Int *pivots = NULL;
105
106 HYPRE_Int variant = hypre_SchwarzDataVariant(schwarz_data);
107 HYPRE_Int domain_type = hypre_SchwarzDataDomainType(schwarz_data);
108 HYPRE_Int overlap = hypre_SchwarzDataOverlap(schwarz_data);
109 HYPRE_Int num_functions = hypre_SchwarzDataNumFunctions(schwarz_data);
110 HYPRE_Real relax_weight = hypre_SchwarzDataRelaxWeight(schwarz_data);
111 HYPRE_Int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
112
113
114 dof_func = hypre_SchwarzDataDofFunc(schwarz_data);
115
116 Vtemp = hypre_ParVectorCreate(hypre_ParCSRMatrixComm(A),
117 hypre_ParCSRMatrixGlobalNumRows(A),
118 hypre_ParCSRMatrixRowStarts(A));
119 hypre_ParVectorInitialize(Vtemp);
120 hypre_SchwarzDataVtemp(schwarz_data) = Vtemp;
121
122 if (variant > 1)
123 {
124 hypre_ParAMGCreateDomainDof(A,
125 domain_type, overlap,
126 num_functions, dof_func,
127 &domain_structure, &pivots, use_nonsymm);
128
129 if (domain_structure)
130 {
131 if (variant == 2)
132 {
133 hypre_ParGenerateScale(A, domain_structure, relax_weight,
134 &scale);
135 hypre_SchwarzDataScale(schwarz_data) = scale;
136 }
137 else
138 {
139 hypre_ParGenerateHybridScale(A, domain_structure, &A_boundary, &scale);
140 hypre_SchwarzDataScale(schwarz_data) = scale;
141 if (hypre_CSRMatrixNumCols(hypre_ParCSRMatrixOffd(A)))
142 hypre_SchwarzDataABoundary(schwarz_data) = A_boundary;
143 else
144 hypre_SchwarzDataABoundary(schwarz_data) = NULL;
145 }
146 }
147 }
148 else
149 {
150 hypre_AMGCreateDomainDof (hypre_ParCSRMatrixDiag(A),
151 domain_type, overlap,
152 num_functions, dof_func,
153 &domain_structure, &pivots, use_nonsymm);
154 if (domain_structure)
155 {
156 if (variant == 1)
157 {
158 hypre_GenerateScale(domain_structure,
159 hypre_CSRMatrixNumRows(hypre_ParCSRMatrixDiag(A)),
160 relax_weight, &scale);
161 hypre_SchwarzDataScale(schwarz_data) = scale;
162 }
163 }
164 }
165
166 hypre_SchwarzDataDomainStructure(schwarz_data) = domain_structure;
167 hypre_SchwarzDataPivots(schwarz_data) = pivots;
168
169 return hypre_error_flag;
170
171 }
172
173 /*--------------------------------------------------------------------
174 * hypre_SchwarzSolve
175 *--------------------------------------------------------------------*/
176
177 HYPRE_Int
hypre_SchwarzSolve(void * schwarz_vdata,hypre_ParCSRMatrix * A,hypre_ParVector * f,hypre_ParVector * u)178 hypre_SchwarzSolve(void *schwarz_vdata,
179 hypre_ParCSRMatrix *A,
180 hypre_ParVector *f,
181 hypre_ParVector *u )
182 {
183 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) schwarz_vdata;
184
185 hypre_CSRMatrix *domain_structure =
186 hypre_SchwarzDataDomainStructure(schwarz_data);
187 hypre_CSRMatrix *A_boundary = hypre_SchwarzDataABoundary(schwarz_data);
188 HYPRE_Real *scale = hypre_SchwarzDataScale(schwarz_data);
189 hypre_ParVector *Vtemp = hypre_SchwarzDataVtemp(schwarz_data);
190 HYPRE_Int variant = hypre_SchwarzDataVariant(schwarz_data);
191 HYPRE_Real relax_wt = hypre_SchwarzDataRelaxWeight(schwarz_data);
192 HYPRE_Int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
193
194 HYPRE_Int *pivots = hypre_SchwarzDataPivots(schwarz_data);
195
196 if (domain_structure)
197 {
198 if (variant == 2)
199 {
200 hypre_ParAdSchwarzSolve(A, f, domain_structure, scale, u, Vtemp, pivots, use_nonsymm);
201 }
202 else if (variant == 3)
203 {
204 hypre_ParMPSchwarzSolve(A, A_boundary, f, domain_structure, u,
205 relax_wt, scale, Vtemp, pivots, use_nonsymm);
206 }
207 else if (variant == 1)
208 {
209 hypre_AdSchwarzSolve(A, f, domain_structure, scale, u, Vtemp, pivots, use_nonsymm);
210 }
211 else if (variant == 4)
212 {
213 hypre_MPSchwarzFWSolve(A, hypre_ParVectorLocalVector(f),
214 domain_structure, u, relax_wt,
215 hypre_ParVectorLocalVector(Vtemp), pivots, use_nonsymm);
216 }
217 else
218 {
219 hypre_MPSchwarzSolve(A, hypre_ParVectorLocalVector(f),
220 domain_structure, u, relax_wt,
221 hypre_ParVectorLocalVector(Vtemp), pivots, use_nonsymm);
222 }
223 }
224
225 return hypre_error_flag;
226 }
227 /*--------------------------------------------------------------------
228 * hypre_SchwarzCFSolve
229 *--------------------------------------------------------------------*/
230
231 HYPRE_Int
hypre_SchwarzCFSolve(void * schwarz_vdata,hypre_ParCSRMatrix * A,hypre_ParVector * f,hypre_ParVector * u,HYPRE_Int * CF_marker,HYPRE_Int rlx_pt)232 hypre_SchwarzCFSolve(void *schwarz_vdata,
233 hypre_ParCSRMatrix *A,
234 hypre_ParVector *f,
235 hypre_ParVector *u,
236 HYPRE_Int *CF_marker,
237 HYPRE_Int rlx_pt)
238 {
239 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) schwarz_vdata;
240
241 hypre_CSRMatrix *domain_structure =
242 hypre_SchwarzDataDomainStructure(schwarz_data);
243 HYPRE_Real *scale = hypre_SchwarzDataScale(schwarz_data);
244 hypre_ParVector *Vtemp = hypre_SchwarzDataVtemp(schwarz_data);
245 HYPRE_Int variant = hypre_SchwarzDataVariant(schwarz_data);
246 HYPRE_Real relax_wt = hypre_SchwarzDataRelaxWeight(schwarz_data);
247
248 HYPRE_Int use_nonsymm = hypre_SchwarzDataUseNonSymm(schwarz_data);
249
250 HYPRE_Int *pivots = hypre_SchwarzDataPivots(schwarz_data);
251
252 if (variant == 1)
253 {
254 hypre_AdSchwarzCFSolve(A, f, domain_structure, scale, u, Vtemp,
255 CF_marker, rlx_pt, pivots, use_nonsymm);
256 }
257 else if (variant == 4)
258 {
259 hypre_MPSchwarzCFFWSolve(A, hypre_ParVectorLocalVector(f),
260 domain_structure, u, relax_wt,
261 hypre_ParVectorLocalVector(Vtemp),
262 CF_marker, rlx_pt, pivots, use_nonsymm);
263 }
264 else
265 {
266 hypre_MPSchwarzCFSolve(A, hypre_ParVectorLocalVector(f),
267 domain_structure, u, relax_wt,
268 hypre_ParVectorLocalVector(Vtemp),
269 CF_marker, rlx_pt, pivots, use_nonsymm);
270 }
271
272 return hypre_error_flag;
273 }
274
275 /*--------------------------------------------------------------------------
276 * Routines to set various parameters
277 *--------------------------------------------------------------------------*/
278
279 HYPRE_Int
hypre_SchwarzSetVariant(void * data,HYPRE_Int variant)280 hypre_SchwarzSetVariant( void *data, HYPRE_Int variant )
281 {
282
283 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
284
285 hypre_SchwarzDataVariant(schwarz_data) = variant;
286 return hypre_error_flag;
287
288 }
289
290 HYPRE_Int
hypre_SchwarzSetDomainType(void * data,HYPRE_Int domain_type)291 hypre_SchwarzSetDomainType( void *data, HYPRE_Int domain_type )
292 {
293
294 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
295
296 hypre_SchwarzDataDomainType(schwarz_data) = domain_type;
297 return hypre_error_flag;
298
299 }
300
301 HYPRE_Int
hypre_SchwarzSetOverlap(void * data,HYPRE_Int overlap)302 hypre_SchwarzSetOverlap( void *data, HYPRE_Int overlap )
303 {
304
305 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
306
307 hypre_SchwarzDataOverlap(schwarz_data) = overlap;
308
309 return hypre_error_flag;
310 }
311
312 HYPRE_Int
hypre_SchwarzSetNumFunctions(void * data,HYPRE_Int num_functions)313 hypre_SchwarzSetNumFunctions( void *data, HYPRE_Int num_functions )
314 {
315
316 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
317
318 hypre_SchwarzDataNumFunctions(schwarz_data) = num_functions;
319
320 return hypre_error_flag;
321 }
322
323 HYPRE_Int
hypre_SchwarzSetNonSymm(void * data,HYPRE_Int value)324 hypre_SchwarzSetNonSymm( void *data, HYPRE_Int value )
325 {
326
327 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
328
329 hypre_SchwarzDataUseNonSymm(schwarz_data) = value;
330
331 return hypre_error_flag;
332
333 }
334
335 HYPRE_Int
hypre_SchwarzSetRelaxWeight(void * data,HYPRE_Real relax_weight)336 hypre_SchwarzSetRelaxWeight( void *data, HYPRE_Real relax_weight )
337 {
338
339 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
340
341 hypre_SchwarzDataRelaxWeight(schwarz_data) = relax_weight;
342
343 return hypre_error_flag;
344 }
345
346 HYPRE_Int
hypre_SchwarzSetDomainStructure(void * data,hypre_CSRMatrix * domain_structure)347 hypre_SchwarzSetDomainStructure( void *data, hypre_CSRMatrix *domain_structure )
348 {
349
350 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
351
352 hypre_SchwarzDataDomainStructure(schwarz_data) = domain_structure;
353
354 return hypre_error_flag;
355 }
356
357 HYPRE_Int
hypre_SchwarzSetScale(void * data,HYPRE_Real * scale)358 hypre_SchwarzSetScale( void *data, HYPRE_Real *scale)
359 {
360
361 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
362
363 hypre_SchwarzDataScale(schwarz_data) = scale;
364
365 return hypre_error_flag;
366 }
367
368 HYPRE_Int
hypre_SchwarzReScale(void * data,HYPRE_Int size,HYPRE_Real value)369 hypre_SchwarzReScale( void *data, HYPRE_Int size, HYPRE_Real value)
370 {
371
372 HYPRE_Int i;
373 HYPRE_Real *scale;
374 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
375
376 scale = hypre_SchwarzDataScale(schwarz_data);
377 for (i=0; i < size; i++)
378 scale[i] *= value;
379
380 return hypre_error_flag;
381
382 }
383
384 HYPRE_Int
hypre_SchwarzSetDofFunc(void * data,HYPRE_Int * dof_func)385 hypre_SchwarzSetDofFunc( void *data, HYPRE_Int *dof_func)
386 {
387
388 hypre_SchwarzData *schwarz_data = (hypre_SchwarzData*) data;
389
390 hypre_SchwarzDataDofFunc(schwarz_data) = dof_func;
391
392 return hypre_error_flag;
393 }
394