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