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 #include "_hypre_struct_ls.h"
9 
10 /*--------------------------------------------------------------------------
11  *--------------------------------------------------------------------------*/
12 
13 typedef struct
14 {
15    HYPRE_Int               setup_temp_vec;
16    HYPRE_Int               setup_a_rem;
17    HYPRE_Int               setup_a_sol;
18 
19    MPI_Comm                comm;
20 
21    HYPRE_Int               memory_use;
22    HYPRE_Real              tol;
23    HYPRE_Int               max_iter;
24    HYPRE_Int               zero_guess;
25 
26    HYPRE_Int               num_spaces;
27    HYPRE_Int              *space_indices;
28    HYPRE_Int              *space_strides;
29 
30    HYPRE_Int               num_pre_spaces;
31    HYPRE_Int               num_reg_spaces;
32    HYPRE_Int              *pre_space_ranks;
33    HYPRE_Int              *reg_space_ranks;
34 
35    hypre_Index             base_index;
36    hypre_Index             base_stride;
37    hypre_BoxArray         *base_box_array;
38 
39    HYPRE_Int               stencil_dim;
40 
41    hypre_StructMatrix     *A;
42    hypre_StructVector     *b;
43    hypre_StructVector     *x;
44 
45    hypre_StructVector     *temp_vec;
46    hypre_StructMatrix     *A_sol;  /* Coefficients of A that make up
47                                       the (sol)ve part of the relaxation */
48    hypre_StructMatrix     *A_rem;  /* Coefficients of A (rem)aining:
49                                       A_rem = A - A_sol                  */
50    void                  **residual_data;  /* Array of size `num_spaces' */
51    void                  **solve_data;     /* Array of size `num_spaces' */
52 
53    /* log info (always logged) */
54    HYPRE_Int               num_iterations;
55    HYPRE_Int               time_index;
56 
57    HYPRE_Int               num_pre_relax;
58    HYPRE_Int               num_post_relax;
59 
60    HYPRE_Int               max_level;
61 } hypre_SMGRelaxData;
62 
63 /*--------------------------------------------------------------------------
64  *--------------------------------------------------------------------------*/
65 
66 void *
hypre_SMGRelaxCreate(MPI_Comm comm)67 hypre_SMGRelaxCreate( MPI_Comm  comm )
68 {
69    hypre_SMGRelaxData *relax_data;
70 
71    relax_data = hypre_CTAlloc(hypre_SMGRelaxData,  1, HYPRE_MEMORY_HOST);
72    (relax_data -> setup_temp_vec) = 1;
73    (relax_data -> setup_a_rem)    = 1;
74    (relax_data -> setup_a_sol)    = 1;
75    (relax_data -> comm)           = comm;
76    (relax_data -> base_box_array) = NULL;
77    (relax_data -> time_index)     = hypre_InitializeTiming("SMGRelax");
78    /* set defaults */
79    (relax_data -> memory_use)         = 0;
80    (relax_data -> tol)                = 1.0e-06;
81    (relax_data -> max_iter)           = 1000;
82    (relax_data -> zero_guess)         = 0;
83    (relax_data -> num_spaces)         = 1;
84    (relax_data -> space_indices)      = hypre_TAlloc(HYPRE_Int,  1, HYPRE_MEMORY_HOST);
85    (relax_data -> space_strides)      = hypre_TAlloc(HYPRE_Int,  1, HYPRE_MEMORY_HOST);
86    (relax_data -> space_indices[0])   = 0;
87    (relax_data -> space_strides[0])   = 1;
88    (relax_data -> num_pre_spaces)     = 0;
89    (relax_data -> num_reg_spaces)     = 1;
90    (relax_data -> pre_space_ranks)    = NULL;
91    (relax_data -> reg_space_ranks)    = hypre_TAlloc(HYPRE_Int,  1, HYPRE_MEMORY_HOST);
92    (relax_data -> reg_space_ranks[0]) = 0;
93    hypre_SetIndex3((relax_data -> base_index), 0, 0, 0);
94    hypre_SetIndex3((relax_data -> base_stride), 1, 1, 1);
95    (relax_data -> A)                  = NULL;
96    (relax_data -> b)                  = NULL;
97    (relax_data -> x)                  = NULL;
98    (relax_data -> temp_vec)           = NULL;
99 
100    (relax_data -> num_pre_relax)  = 1;
101    (relax_data -> num_post_relax) = 1;
102    (relax_data -> max_level)      = -1;
103    return (void *) relax_data;
104 }
105 
106 /*--------------------------------------------------------------------------
107  *--------------------------------------------------------------------------*/
108 
109 HYPRE_Int
hypre_SMGRelaxDestroyTempVec(void * relax_vdata)110 hypre_SMGRelaxDestroyTempVec( void *relax_vdata )
111 {
112    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
113 
114    hypre_StructVectorDestroy(relax_data -> temp_vec);
115    (relax_data -> setup_temp_vec) = 1;
116 
117    return hypre_error_flag;
118 }
119 
120 /*--------------------------------------------------------------------------
121  *--------------------------------------------------------------------------*/
122 
123 HYPRE_Int
hypre_SMGRelaxDestroyARem(void * relax_vdata)124 hypre_SMGRelaxDestroyARem( void *relax_vdata )
125 {
126    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
127    HYPRE_Int            i;
128 
129    if (relax_data -> A_rem)
130    {
131       for (i = 0; i < (relax_data -> num_spaces); i++)
132       {
133          hypre_SMGResidualDestroy(relax_data -> residual_data[i]);
134       }
135       hypre_TFree(relax_data -> residual_data, HYPRE_MEMORY_HOST);
136       hypre_StructMatrixDestroy(relax_data -> A_rem);
137       (relax_data -> A_rem) = NULL;
138    }
139    (relax_data -> setup_a_rem) = 1;
140 
141    return hypre_error_flag;
142 }
143 
144 /*--------------------------------------------------------------------------
145  *--------------------------------------------------------------------------*/
146 
147 HYPRE_Int
hypre_SMGRelaxDestroyASol(void * relax_vdata)148 hypre_SMGRelaxDestroyASol( void *relax_vdata )
149 {
150    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
151    HYPRE_Int            stencil_dim;
152    HYPRE_Int            i;
153 
154    if (relax_data -> A_sol)
155    {
156       stencil_dim = (relax_data -> stencil_dim);
157       for (i = 0; i < (relax_data -> num_spaces); i++)
158       {
159          if (stencil_dim > 2)
160             hypre_SMGDestroy(relax_data -> solve_data[i]);
161          else
162             hypre_CyclicReductionDestroy(relax_data -> solve_data[i]);
163       }
164       hypre_TFree(relax_data -> solve_data, HYPRE_MEMORY_HOST);
165       hypre_StructMatrixDestroy(relax_data -> A_sol);
166       (relax_data -> A_sol) = NULL;
167    }
168    (relax_data -> setup_a_sol) = 1;
169 
170    return hypre_error_flag;
171 }
172 
173 /*--------------------------------------------------------------------------
174  *--------------------------------------------------------------------------*/
175 
176 HYPRE_Int
hypre_SMGRelaxDestroy(void * relax_vdata)177 hypre_SMGRelaxDestroy( void *relax_vdata )
178 {
179    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
180 
181    if (relax_data)
182    {
183       hypre_TFree(relax_data -> space_indices, HYPRE_MEMORY_HOST);
184       hypre_TFree(relax_data -> space_strides, HYPRE_MEMORY_HOST);
185       hypre_TFree(relax_data -> pre_space_ranks, HYPRE_MEMORY_HOST);
186       hypre_TFree(relax_data -> reg_space_ranks, HYPRE_MEMORY_HOST);
187       hypre_BoxArrayDestroy(relax_data -> base_box_array);
188 
189       hypre_StructMatrixDestroy(relax_data -> A);
190       hypre_StructVectorDestroy(relax_data -> b);
191       hypre_StructVectorDestroy(relax_data -> x);
192 
193       hypre_SMGRelaxDestroyTempVec(relax_vdata);
194       hypre_SMGRelaxDestroyARem(relax_vdata);
195       hypre_SMGRelaxDestroyASol(relax_vdata);
196 
197       hypre_FinalizeTiming(relax_data -> time_index);
198       hypre_TFree(relax_data, HYPRE_MEMORY_HOST);
199    }
200 
201    return hypre_error_flag;
202 }
203 
204 /*--------------------------------------------------------------------------
205  *--------------------------------------------------------------------------*/
206 
207 HYPRE_Int
hypre_SMGRelax(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)208 hypre_SMGRelax( void               *relax_vdata,
209                 hypre_StructMatrix *A,
210                 hypre_StructVector *b,
211                 hypre_StructVector *x           )
212 {
213    hypre_SMGRelaxData   *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
214 
215    HYPRE_Int             zero_guess;
216    HYPRE_Int             stencil_dim;
217    hypre_StructVector   *temp_vec;
218    hypre_StructMatrix   *A_sol;
219    hypre_StructMatrix   *A_rem;
220    void                **residual_data;
221    void                **solve_data;
222 
223    hypre_IndexRef        base_stride;
224    hypre_BoxArray       *base_box_a;
225    HYPRE_Real            zero = 0.0;
226 
227    HYPRE_Int             max_iter;
228    HYPRE_Int             num_spaces;
229    HYPRE_Int            *space_ranks;
230 
231    HYPRE_Int             i, j, k, is;
232 
233    /*----------------------------------------------------------
234     * Note: The zero_guess stuff is not handled correctly
235     * for general relaxation parameters.  It is correct when
236     * the spaces are independent sets in the direction of
237     * relaxation.
238     *----------------------------------------------------------*/
239 
240    hypre_BeginTiming(relax_data -> time_index);
241 
242    /*----------------------------------------------------------
243     * Set up the solver
244     *----------------------------------------------------------*/
245 
246    /* insure that the solver memory gets fully set up */
247    if ((relax_data -> setup_a_sol) > 0)
248    {
249       (relax_data -> setup_a_sol) = 2;
250    }
251 
252    hypre_SMGRelaxSetup(relax_vdata, A, b, x);
253 
254    zero_guess      = (relax_data -> zero_guess);
255    stencil_dim     = (relax_data -> stencil_dim);
256    temp_vec        = (relax_data -> temp_vec);
257    A_sol           = (relax_data -> A_sol);
258    A_rem           = (relax_data -> A_rem);
259    residual_data   = (relax_data -> residual_data);
260    solve_data      = (relax_data -> solve_data);
261 
262    /*----------------------------------------------------------
263     * Set zero values
264     *----------------------------------------------------------*/
265 
266    if (zero_guess)
267    {
268       base_stride = (relax_data -> base_stride);
269       base_box_a = (relax_data -> base_box_array);
270       hypre_SMGSetStructVectorConstantValues(x, zero, base_box_a, base_stride);
271    }
272 
273    /*----------------------------------------------------------
274     * Iterate
275     *----------------------------------------------------------*/
276 
277    for (k = 0; k < 2; k++)
278    {
279       switch(k)
280       {
281          /* Do pre-relaxation iterations */
282          case 0:
283             max_iter    = 1;
284             num_spaces  = (relax_data -> num_pre_spaces);
285             space_ranks = (relax_data -> pre_space_ranks);
286             break;
287 
288          /* Do regular relaxation iterations */
289          case 1:
290             max_iter    = (relax_data -> max_iter);
291             num_spaces  = (relax_data -> num_reg_spaces);
292             space_ranks = (relax_data -> reg_space_ranks);
293             break;
294       }
295 
296       for (i = 0; i < max_iter; i++)
297       {
298          for (j = 0; j < num_spaces; j++)
299          {
300             is = space_ranks[j];
301 
302             hypre_SMGResidual(residual_data[is], A_rem, x, b, temp_vec);
303 
304             if (stencil_dim > 2)
305             {
306                hypre_SMGSolve(solve_data[is], A_sol, temp_vec, x);
307             }
308             else
309             {
310                hypre_CyclicReduction(solve_data[is], A_sol, temp_vec, x);
311             }
312          }
313 
314          (relax_data -> num_iterations) = (i + 1);
315       }
316    }
317 
318    /*----------------------------------------------------------
319     * Free up memory according to memory_use parameter
320     *----------------------------------------------------------*/
321 
322    if ((stencil_dim - 1) <= (relax_data -> memory_use))
323    {
324       hypre_SMGRelaxDestroyASol(relax_vdata);
325    }
326 
327    hypre_EndTiming(relax_data -> time_index);
328 
329    return hypre_error_flag;
330 }
331 
332 /*--------------------------------------------------------------------------
333  *--------------------------------------------------------------------------*/
334 
335 HYPRE_Int
hypre_SMGRelaxSetup(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)336 hypre_SMGRelaxSetup( void               *relax_vdata,
337                      hypre_StructMatrix *A,
338                      hypre_StructVector *b,
339                      hypre_StructVector *x           )
340 {
341    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
342    HYPRE_Int            stencil_dim;
343    HYPRE_Int            a_sol_test;
344 
345    stencil_dim = hypre_StructStencilNDim(hypre_StructMatrixStencil(A));
346    (relax_data -> stencil_dim) = stencil_dim;
347    hypre_StructMatrixDestroy(relax_data -> A);
348    hypre_StructVectorDestroy(relax_data -> b);
349    hypre_StructVectorDestroy(relax_data -> x);
350    (relax_data -> A) = hypre_StructMatrixRef(A);
351    (relax_data -> b) = hypre_StructVectorRef(b);
352    (relax_data -> x) = hypre_StructVectorRef(x);
353 
354    /*----------------------------------------------------------
355     * Set up memory according to memory_use parameter.
356     *
357     * If a subset of the solver memory is not to be set up
358     * until the solve is actually done, it's "setup" tag
359     * should have a value greater than 1.
360     *----------------------------------------------------------*/
361 
362    if ((stencil_dim - 1) <= (relax_data -> memory_use))
363    {
364       a_sol_test = 1;
365    }
366    else
367    {
368       a_sol_test = 0;
369    }
370 
371    /*----------------------------------------------------------
372     * Set up the solver
373     *----------------------------------------------------------*/
374 
375    if ((relax_data -> setup_temp_vec) > 0)
376    {
377       hypre_SMGRelaxSetupTempVec(relax_vdata, A, b, x);
378    }
379 
380    if ((relax_data -> setup_a_rem) > 0)
381    {
382       hypre_SMGRelaxSetupARem(relax_vdata, A, b, x);
383    }
384 
385    if ((relax_data -> setup_a_sol) > a_sol_test)
386    {
387       hypre_SMGRelaxSetupASol(relax_vdata, A, b, x);
388    }
389 
390    if ((relax_data -> base_box_array) == NULL)
391    {
392       hypre_SMGRelaxSetupBaseBoxArray(relax_vdata, A, b, x);
393    }
394 
395 
396    return hypre_error_flag;
397 }
398 
399 /*--------------------------------------------------------------------------
400  *--------------------------------------------------------------------------*/
401 
402 HYPRE_Int
hypre_SMGRelaxSetupTempVec(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)403 hypre_SMGRelaxSetupTempVec( void               *relax_vdata,
404                             hypre_StructMatrix *A,
405                             hypre_StructVector *b,
406                             hypre_StructVector *x           )
407 {
408    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
409    hypre_StructVector  *temp_vec   = (relax_data -> temp_vec);
410 
411    /*----------------------------------------------------------
412     * Set up data
413     *----------------------------------------------------------*/
414 
415    if ((relax_data -> temp_vec) == NULL)
416    {
417       temp_vec = hypre_StructVectorCreate(hypre_StructVectorComm(b),
418                                           hypre_StructVectorGrid(b));
419       hypre_StructVectorSetNumGhost(temp_vec, hypre_StructVectorNumGhost(b));
420       hypre_StructVectorInitialize(temp_vec);
421       hypre_StructVectorAssemble(temp_vec);
422       (relax_data -> temp_vec) = temp_vec;
423    }
424    (relax_data -> setup_temp_vec) = 0;
425 
426    return hypre_error_flag;
427 }
428 
429 /*--------------------------------------------------------------------------
430  * hypre_SMGRelaxSetupARem
431  *--------------------------------------------------------------------------*/
432 
433 HYPRE_Int
hypre_SMGRelaxSetupARem(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)434 hypre_SMGRelaxSetupARem( void               *relax_vdata,
435                          hypre_StructMatrix *A,
436                          hypre_StructVector *b,
437                          hypre_StructVector *x           )
438 {
439    hypre_SMGRelaxData   *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
440 
441    HYPRE_Int             num_spaces    = (relax_data -> num_spaces);
442    HYPRE_Int            *space_indices = (relax_data -> space_indices);
443    HYPRE_Int            *space_strides = (relax_data -> space_strides);
444    hypre_StructVector   *temp_vec      = (relax_data -> temp_vec);
445 
446    hypre_StructStencil  *stencil       = hypre_StructMatrixStencil(A);
447    hypre_Index          *stencil_shape = hypre_StructStencilShape(stencil);
448    HYPRE_Int             stencil_size  = hypre_StructStencilSize(stencil);
449    HYPRE_Int             stencil_dim   = hypre_StructStencilNDim(stencil);
450 
451    hypre_StructMatrix   *A_rem;
452    void                **residual_data;
453 
454    hypre_Index           base_index;
455    hypre_Index           base_stride;
456 
457    HYPRE_Int             num_stencil_indices;
458    HYPRE_Int            *stencil_indices;
459 
460    HYPRE_Int             i;
461 
462    /*----------------------------------------------------------
463     * Free up old data before putting new data into structure
464     *----------------------------------------------------------*/
465 
466    hypre_SMGRelaxDestroyARem(relax_vdata);
467 
468    /*----------------------------------------------------------
469     * Set up data
470     *----------------------------------------------------------*/
471 
472    hypre_CopyIndex((relax_data -> base_index),  base_index);
473    hypre_CopyIndex((relax_data -> base_stride), base_stride);
474 
475    stencil_indices = hypre_TAlloc(HYPRE_Int,  stencil_size, HYPRE_MEMORY_HOST);
476    num_stencil_indices = 0;
477    for (i = 0; i < stencil_size; i++)
478    {
479       if (hypre_IndexD(stencil_shape[i], (stencil_dim - 1)) != 0)
480       {
481          stencil_indices[num_stencil_indices] = i;
482          num_stencil_indices++;
483       }
484    }
485    A_rem = hypre_StructMatrixCreateMask(A, num_stencil_indices, stencil_indices);
486    hypre_TFree(stencil_indices, HYPRE_MEMORY_HOST);
487 
488    /* Set up residual_data */
489    residual_data = hypre_TAlloc(void *,  num_spaces, HYPRE_MEMORY_HOST);
490 
491    for (i = 0; i < num_spaces; i++)
492    {
493       hypre_IndexD(base_index,  (stencil_dim - 1)) = space_indices[i];
494       hypre_IndexD(base_stride, (stencil_dim - 1)) = space_strides[i];
495 
496       residual_data[i] = hypre_SMGResidualCreate();
497       hypre_SMGResidualSetBase(residual_data[i], base_index, base_stride);
498       hypre_SMGResidualSetup(residual_data[i], A_rem, x, b, temp_vec);
499    }
500 
501    (relax_data -> A_rem)         = A_rem;
502    (relax_data -> residual_data) = residual_data;
503 
504    (relax_data -> setup_a_rem) = 0;
505 
506    return hypre_error_flag;
507 }
508 
509 /*--------------------------------------------------------------------------
510  *--------------------------------------------------------------------------*/
511 
512 HYPRE_Int
hypre_SMGRelaxSetupASol(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)513 hypre_SMGRelaxSetupASol( void               *relax_vdata,
514                          hypre_StructMatrix *A,
515                          hypre_StructVector *b,
516                          hypre_StructVector *x           )
517 {
518    hypre_SMGRelaxData   *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
519 
520    HYPRE_Int             num_spaces    = (relax_data -> num_spaces);
521    HYPRE_Int            *space_indices = (relax_data -> space_indices);
522    HYPRE_Int            *space_strides = (relax_data -> space_strides);
523    hypre_StructVector   *temp_vec      = (relax_data -> temp_vec);
524 
525    HYPRE_Int             num_pre_relax   = (relax_data -> num_pre_relax);
526    HYPRE_Int             num_post_relax  = (relax_data -> num_post_relax);
527 
528    hypre_StructStencil  *stencil       = hypre_StructMatrixStencil(A);
529    hypre_Index          *stencil_shape = hypre_StructStencilShape(stencil);
530    HYPRE_Int             stencil_size  = hypre_StructStencilSize(stencil);
531    HYPRE_Int             stencil_dim   = hypre_StructStencilNDim(stencil);
532 
533    hypre_StructMatrix   *A_sol;
534    void                **solve_data;
535 
536    hypre_Index           base_index;
537    hypre_Index           base_stride;
538 
539    HYPRE_Int             num_stencil_indices;
540    HYPRE_Int            *stencil_indices;
541 
542    HYPRE_Int             i;
543 
544    /*----------------------------------------------------------
545     * Free up old data before putting new data into structure
546     *----------------------------------------------------------*/
547 
548    hypre_SMGRelaxDestroyASol(relax_vdata);
549 
550    /*----------------------------------------------------------
551     * Set up data
552     *----------------------------------------------------------*/
553 
554    hypre_CopyIndex((relax_data -> base_index),  base_index);
555    hypre_CopyIndex((relax_data -> base_stride), base_stride);
556 
557    stencil_indices = hypre_TAlloc(HYPRE_Int,  stencil_size, HYPRE_MEMORY_HOST);
558    num_stencil_indices = 0;
559    for (i = 0; i < stencil_size; i++)
560    {
561       if (hypre_IndexD(stencil_shape[i], (stencil_dim - 1)) == 0)
562       {
563          stencil_indices[num_stencil_indices] = i;
564          num_stencil_indices++;
565       }
566    }
567 
568    A_sol = hypre_StructMatrixCreateMask(A, num_stencil_indices, stencil_indices);
569    hypre_StructStencilNDim(hypre_StructMatrixStencil(A_sol)) = stencil_dim - 1;
570    hypre_TFree(stencil_indices, HYPRE_MEMORY_HOST);
571 
572    /* Set up solve_data */
573    solve_data    = hypre_TAlloc(void *,  num_spaces, HYPRE_MEMORY_HOST);
574 
575    for (i = 0; i < num_spaces; i++)
576    {
577       hypre_IndexD(base_index,  (stencil_dim - 1)) = space_indices[i];
578       hypre_IndexD(base_stride, (stencil_dim - 1)) = space_strides[i];
579 
580       if (stencil_dim > 2)
581       {
582          solve_data[i] = hypre_SMGCreate(relax_data -> comm);
583          hypre_SMGSetNumPreRelax( solve_data[i], num_pre_relax);
584          hypre_SMGSetNumPostRelax( solve_data[i], num_post_relax);
585          hypre_SMGSetBase(solve_data[i], base_index, base_stride);
586          hypre_SMGSetMemoryUse(solve_data[i], (relax_data -> memory_use));
587          hypre_SMGSetTol(solve_data[i], 0.0);
588          hypre_SMGSetMaxIter(solve_data[i], 1);
589          hypre_StructSMGSetMaxLevel(solve_data[i], (relax_data -> max_level));
590          hypre_SMGSetup(solve_data[i], A_sol, temp_vec, x);
591       }
592       else
593       {
594          solve_data[i] = hypre_CyclicReductionCreate(relax_data -> comm);
595          hypre_CyclicReductionSetBase(solve_data[i], base_index, base_stride);
596          //hypre_CyclicReductionSetMaxLevel(solve_data[i], -1);//(relax_data -> max_level)+10);
597          hypre_CyclicReductionSetup(solve_data[i], A_sol, temp_vec, x);
598       }
599    }
600 
601    (relax_data -> A_sol)      = A_sol;
602    (relax_data -> solve_data) = solve_data;
603 
604    (relax_data -> setup_a_sol) = 0;
605 
606    return hypre_error_flag;
607 }
608 
609 /*--------------------------------------------------------------------------
610  *--------------------------------------------------------------------------*/
611 
612 HYPRE_Int
hypre_SMGRelaxSetTempVec(void * relax_vdata,hypre_StructVector * temp_vec)613 hypre_SMGRelaxSetTempVec( void               *relax_vdata,
614                           hypre_StructVector *temp_vec    )
615 {
616    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
617 
618    hypre_SMGRelaxDestroyTempVec(relax_vdata);
619    (relax_data -> temp_vec) = hypre_StructVectorRef(temp_vec);
620 
621    (relax_data -> setup_temp_vec) = 1;
622    (relax_data -> setup_a_rem)    = 1;
623    (relax_data -> setup_a_sol)    = 1;
624 
625    return hypre_error_flag;
626 }
627 
628 /*--------------------------------------------------------------------------
629  *--------------------------------------------------------------------------*/
630 
631 HYPRE_Int
hypre_SMGRelaxSetMemoryUse(void * relax_vdata,HYPRE_Int memory_use)632 hypre_SMGRelaxSetMemoryUse( void *relax_vdata,
633                             HYPRE_Int   memory_use  )
634 {
635    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
636 
637    (relax_data -> memory_use) = memory_use;
638 
639    return hypre_error_flag;
640 }
641 
642 /*--------------------------------------------------------------------------
643  *--------------------------------------------------------------------------*/
644 
645 HYPRE_Int
hypre_SMGRelaxSetTol(void * relax_vdata,HYPRE_Real tol)646 hypre_SMGRelaxSetTol( void   *relax_vdata,
647                       HYPRE_Real  tol         )
648 {
649    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
650 
651    (relax_data -> tol) = tol;
652 
653    return hypre_error_flag;
654 }
655 
656 /*--------------------------------------------------------------------------
657  *--------------------------------------------------------------------------*/
658 
659 HYPRE_Int
hypre_SMGRelaxSetMaxIter(void * relax_vdata,HYPRE_Int max_iter)660 hypre_SMGRelaxSetMaxIter( void *relax_vdata,
661                           HYPRE_Int   max_iter    )
662 {
663    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
664 
665    (relax_data -> max_iter) = max_iter;
666 
667    return hypre_error_flag;
668 }
669 
670 /*--------------------------------------------------------------------------
671  *--------------------------------------------------------------------------*/
672 
673 HYPRE_Int
hypre_SMGRelaxSetZeroGuess(void * relax_vdata,HYPRE_Int zero_guess)674 hypre_SMGRelaxSetZeroGuess( void *relax_vdata,
675                             HYPRE_Int   zero_guess  )
676 {
677    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
678 
679    (relax_data -> zero_guess) = zero_guess;
680 
681    return hypre_error_flag;
682 }
683 
684 /*--------------------------------------------------------------------------
685  *--------------------------------------------------------------------------*/
686 
687 HYPRE_Int
hypre_SMGRelaxSetNumSpaces(void * relax_vdata,HYPRE_Int num_spaces)688 hypre_SMGRelaxSetNumSpaces( void *relax_vdata,
689                             HYPRE_Int   num_spaces      )
690 {
691    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
692    HYPRE_Int           i;
693 
694    (relax_data -> num_spaces) = num_spaces;
695 
696    hypre_TFree(relax_data -> space_indices, HYPRE_MEMORY_HOST);
697    hypre_TFree(relax_data -> space_strides, HYPRE_MEMORY_HOST);
698    hypre_TFree(relax_data -> pre_space_ranks, HYPRE_MEMORY_HOST);
699    hypre_TFree(relax_data -> reg_space_ranks, HYPRE_MEMORY_HOST);
700    (relax_data -> space_indices)   = hypre_TAlloc(HYPRE_Int,  num_spaces, HYPRE_MEMORY_HOST);
701    (relax_data -> space_strides)   = hypre_TAlloc(HYPRE_Int,  num_spaces, HYPRE_MEMORY_HOST);
702    (relax_data -> num_pre_spaces)  = 0;
703    (relax_data -> num_reg_spaces)  = num_spaces;
704    (relax_data -> pre_space_ranks) = NULL;
705    (relax_data -> reg_space_ranks) = hypre_TAlloc(HYPRE_Int,  num_spaces, HYPRE_MEMORY_HOST);
706 
707    for (i = 0; i < num_spaces; i++)
708    {
709       (relax_data -> space_indices[i]) = 0;
710       (relax_data -> space_strides[i]) = 1;
711       (relax_data -> reg_space_ranks[i]) = i;
712    }
713 
714    (relax_data -> setup_temp_vec) = 1;
715    (relax_data -> setup_a_rem)    = 1;
716    (relax_data -> setup_a_sol)    = 1;
717 
718    return hypre_error_flag;
719 }
720 
721 /*--------------------------------------------------------------------------
722  *--------------------------------------------------------------------------*/
723 
724 HYPRE_Int
hypre_SMGRelaxSetNumPreSpaces(void * relax_vdata,HYPRE_Int num_pre_spaces)725 hypre_SMGRelaxSetNumPreSpaces( void *relax_vdata,
726                                HYPRE_Int   num_pre_spaces )
727 {
728    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
729    HYPRE_Int           i;
730 
731    (relax_data -> num_pre_spaces) = num_pre_spaces;
732 
733    hypre_TFree(relax_data -> pre_space_ranks, HYPRE_MEMORY_HOST);
734    (relax_data -> pre_space_ranks) = hypre_TAlloc(HYPRE_Int,  num_pre_spaces, HYPRE_MEMORY_HOST);
735 
736    for (i = 0; i < num_pre_spaces; i++)
737       (relax_data -> pre_space_ranks[i]) = 0;
738 
739    return hypre_error_flag;
740 }
741 
742 /*--------------------------------------------------------------------------
743  *--------------------------------------------------------------------------*/
744 
745 HYPRE_Int
hypre_SMGRelaxSetNumRegSpaces(void * relax_vdata,HYPRE_Int num_reg_spaces)746 hypre_SMGRelaxSetNumRegSpaces( void *relax_vdata,
747                                HYPRE_Int   num_reg_spaces )
748 {
749    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
750    HYPRE_Int           i;
751 
752    (relax_data -> num_reg_spaces) = num_reg_spaces;
753 
754    hypre_TFree(relax_data -> reg_space_ranks, HYPRE_MEMORY_HOST);
755    (relax_data -> reg_space_ranks) = hypre_TAlloc(HYPRE_Int,  num_reg_spaces, HYPRE_MEMORY_HOST);
756 
757    for (i = 0; i < num_reg_spaces; i++)
758       (relax_data -> reg_space_ranks[i]) = 0;
759 
760    return hypre_error_flag;
761 }
762 
763 /*--------------------------------------------------------------------------
764  *--------------------------------------------------------------------------*/
765 
766 HYPRE_Int
hypre_SMGRelaxSetSpace(void * relax_vdata,HYPRE_Int i,HYPRE_Int space_index,HYPRE_Int space_stride)767 hypre_SMGRelaxSetSpace( void *relax_vdata,
768                         HYPRE_Int   i,
769                         HYPRE_Int   space_index,
770                         HYPRE_Int   space_stride )
771 {
772    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
773 
774    (relax_data -> space_indices[i]) = space_index;
775    (relax_data -> space_strides[i]) = space_stride;
776 
777    (relax_data -> setup_temp_vec) = 1;
778    (relax_data -> setup_a_rem)    = 1;
779    (relax_data -> setup_a_sol)    = 1;
780 
781    return hypre_error_flag;
782 }
783 
784 /*--------------------------------------------------------------------------
785  *--------------------------------------------------------------------------*/
786 
787 HYPRE_Int
hypre_SMGRelaxSetRegSpaceRank(void * relax_vdata,HYPRE_Int i,HYPRE_Int reg_space_rank)788 hypre_SMGRelaxSetRegSpaceRank( void *relax_vdata,
789                                HYPRE_Int   i,
790                                HYPRE_Int   reg_space_rank )
791 {
792    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
793 
794    (relax_data -> reg_space_ranks[i]) = reg_space_rank;
795 
796    return hypre_error_flag;
797 }
798 
799 /*--------------------------------------------------------------------------
800  *--------------------------------------------------------------------------*/
801 
802 HYPRE_Int
hypre_SMGRelaxSetPreSpaceRank(void * relax_vdata,HYPRE_Int i,HYPRE_Int pre_space_rank)803 hypre_SMGRelaxSetPreSpaceRank( void *relax_vdata,
804                                HYPRE_Int   i,
805                                HYPRE_Int   pre_space_rank  )
806 {
807    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
808 
809    (relax_data -> pre_space_ranks[i]) = pre_space_rank;
810 
811    return hypre_error_flag;
812 }
813 
814 /*--------------------------------------------------------------------------
815  *--------------------------------------------------------------------------*/
816 
817 HYPRE_Int
hypre_SMGRelaxSetBase(void * relax_vdata,hypre_Index base_index,hypre_Index base_stride)818 hypre_SMGRelaxSetBase( void        *relax_vdata,
819                        hypre_Index  base_index,
820                        hypre_Index  base_stride )
821 {
822    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
823    HYPRE_Int           d;
824 
825    for (d = 0; d < 3; d++)
826    {
827       hypre_IndexD((relax_data -> base_index),  d) =
828          hypre_IndexD(base_index,  d);
829       hypre_IndexD((relax_data -> base_stride), d) =
830          hypre_IndexD(base_stride, d);
831    }
832 
833    if ((relax_data -> base_box_array) != NULL)
834    {
835       hypre_BoxArrayDestroy((relax_data -> base_box_array));
836       (relax_data -> base_box_array) = NULL;
837    }
838 
839    (relax_data -> setup_temp_vec) = 1;
840    (relax_data -> setup_a_rem)    = 1;
841    (relax_data -> setup_a_sol)    = 1;
842 
843    return hypre_error_flag;
844 }
845 
846 /*--------------------------------------------------------------------------
847  * Note that we require at least 1 pre-relax sweep.
848  *--------------------------------------------------------------------------*/
849 
850 HYPRE_Int
hypre_SMGRelaxSetNumPreRelax(void * relax_vdata,HYPRE_Int num_pre_relax)851 hypre_SMGRelaxSetNumPreRelax( void *relax_vdata,
852                               HYPRE_Int   num_pre_relax )
853 {
854    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
855 
856    (relax_data -> num_pre_relax) = hypre_max(num_pre_relax,1);
857 
858    return hypre_error_flag;
859 }
860 
861 /*--------------------------------------------------------------------------
862  *--------------------------------------------------------------------------*/
863 
864 HYPRE_Int
hypre_SMGRelaxSetNumPostRelax(void * relax_vdata,HYPRE_Int num_post_relax)865 hypre_SMGRelaxSetNumPostRelax( void *relax_vdata,
866                                HYPRE_Int   num_post_relax )
867 {
868    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
869 
870    (relax_data -> num_post_relax) = num_post_relax;
871 
872    return hypre_error_flag;
873 }
874 
875 /*--------------------------------------------------------------------------
876  *--------------------------------------------------------------------------*/
877 
878 HYPRE_Int
hypre_SMGRelaxSetNewMatrixStencil(void * relax_vdata,hypre_StructStencil * diff_stencil)879 hypre_SMGRelaxSetNewMatrixStencil( void                *relax_vdata,
880                                    hypre_StructStencil *diff_stencil )
881 {
882    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
883 
884    hypre_Index        *stencil_shape = hypre_StructStencilShape(diff_stencil);
885    HYPRE_Int           stencil_size  = hypre_StructStencilSize(diff_stencil);
886    HYPRE_Int           stencil_dim   = hypre_StructStencilNDim(diff_stencil);
887 
888    HYPRE_Int           i;
889 
890    for (i = 0; i < stencil_size; i++)
891    {
892       if (hypre_IndexD(stencil_shape[i], (stencil_dim - 1)) != 0)
893       {
894          (relax_data -> setup_a_rem) = 1;
895       }
896       else
897       {
898          (relax_data -> setup_a_sol) = 1;
899       }
900    }
901 
902    return hypre_error_flag;
903 }
904 
905 
906 /*--------------------------------------------------------------------------
907  * hypre_SMGRelaxSetupBaseBoxArray
908  *--------------------------------------------------------------------------*/
909 
910 HYPRE_Int
hypre_SMGRelaxSetupBaseBoxArray(void * relax_vdata,hypre_StructMatrix * A,hypre_StructVector * b,hypre_StructVector * x)911 hypre_SMGRelaxSetupBaseBoxArray( void               *relax_vdata,
912                                  hypre_StructMatrix *A,
913                                  hypre_StructVector *b,
914                                  hypre_StructVector *x           )
915 {
916    hypre_SMGRelaxData  *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
917 
918    hypre_StructGrid    *grid;
919    hypre_BoxArray      *boxes;
920    hypre_BoxArray      *base_box_array;
921 
922    grid  = hypre_StructVectorGrid(x);
923    boxes = hypre_StructGridBoxes(grid);
924 
925    base_box_array = hypre_BoxArrayDuplicate(boxes);
926    hypre_ProjectBoxArray(base_box_array,
927                          (relax_data -> base_index),
928                          (relax_data -> base_stride));
929 
930    (relax_data -> base_box_array) = base_box_array;
931 
932    return hypre_error_flag;
933 }
934 
935 /*--------------------------------------------------------------------------
936  *--------------------------------------------------------------------------*/
937 
938 HYPRE_Int
hypre_SMGRelaxSetMaxLevel(void * relax_vdata,HYPRE_Int num_max_level)939 hypre_SMGRelaxSetMaxLevel( void *relax_vdata,
940                            HYPRE_Int   num_max_level )
941 {
942    hypre_SMGRelaxData *relax_data = (hypre_SMGRelaxData  *)relax_vdata;
943 
944    (relax_data -> max_level) = num_max_level;
945 
946    return hypre_error_flag;
947 }
948