FrontISTR  5.9.0
Large-scale structural analysis program with finit element method
hecmw_ML_wrapper.c
Go to the documentation of this file.
1 /*****************************************************************************
2  * Copyright (c) 2021 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <errno.h>
9 #include "hecmw_util.h"
10 
11 #ifdef HECMW_WITH_ML
12 
13 #include "Trilinos_version.h"
14 #include "ml_include.h"
15 #include "ml_config.h"
16 #ifdef HAVE_ML_AMESOS
17 # include "Amesos_config.h"
18 #endif
19 #include "hecmw_ML_helper.h"
20 #include "hecmw_ML_helper_33.h"
21 #include "hecmw_ML_helper_nn.h"
22 
23 /*
24  * Options
25  */
26 
27 enum coarse_solver {Smoother, KLU, MUMPS};
28 enum smoother_type {Cheby, SymBlockGaussSeidel, Jacobi};
29 enum coarsen_scheme {UncoupledMIS, METIS, ParMETIS, Zoltan, DD};
30 
31 struct ml_options {
32  /* Coarse solver
33  * available solvers: Smoother, KLU, MUMPS
34  * Note:
35  * - Trilinos must be built with Amesos enabled to use KLU
36  * - Trilinos must be built with Amesos and MPI enabled to use MUMPS
37  */
38  enum coarse_solver CoarseSolver;
39 
40  /* Smoother type
41  * available types: Cheby, SymBlockGaussSeidel, Jacobi
42  */
43  enum smoother_type SmootherType;
44 
45  /* Whether HEC-MW smoother is used at finest level when SmootherType is SymBlockGaussSeidel
46  */
47  int FlgUseHECMWSmoother;
48 
49  /* Solver cycle
50  * available types: ML_MGV (V-cycle), ML_MGW (W-cycle), ML_MGFULLV (Full V-Cycle)
51  */
52  int MGType;
53 
54  /* Max num of levels
55  */
56  int MaxLevels;
57 
58  /* Coarsening scheme
59  * available types: UncoupledMIS, METIS, ParMETIS, Zoltan, DD
60  */
61  enum coarsen_scheme CoarsenScheme;
62 
63  /* Num of smoother sweeps (order of polynomial for Cheby)
64  */
65  int NumSweeps;
66 
67  /* Max coarse size
68  */
69  int MaxCoarseSize;
70 };
71 
72 
73 /* default values */
74 #ifdef HAVE_ML_AMESOS
75 # ifdef HAVE_AMESOS_MUMPS
76 # define DEFAULT_COARSE_SOLVER MUMPS
77 # else
78 # define DEFAULT_COARSE_SOLVER KLU
79 # endif
80 #else
81 # define DEFAULT_COARSE_SOLVER Smoother
82 #endif
83 #define DEFAULT_SMOOTHER_TYPE Cheby
84 #define DEFAULT_MG_TYPE ML_MGW
85 #define DEFAULT_MAX_LEVELS 4
86 #define DEFAULT_COARSEN_SCHEME UncoupledMIS
87 #define DEFAULT_NUM_SWEEPS 2
88 
89 #define MAX_COARSE_SIZE_MUMPS 50000
90 #define MAX_COARSE_SIZE_KLU 10000
91 
92 
93 static void ml_options_set(struct ml_options *mlopt, int *id, int myrank, int *ierr) {
94  int opt[10];
95 
96  hecmw_ml_get_opt_(id, opt, ierr);
97  if (*ierr != HECMW_SUCCESS) return;
98 
99  switch (opt[0]) {
100  case 0:
101  mlopt->CoarseSolver = DEFAULT_COARSE_SOLVER;
102  break;
103  case 1:
104  mlopt->CoarseSolver = Smoother;
105  break;
106 #ifdef HAVE_ML_AMESOS
107  case 2:
108  mlopt->CoarseSolver = KLU;
109  break;
110  case 3:
111 # ifdef HAVE_AMESOS_MUMPS
112  mlopt->CoarseSolver = MUMPS;
113  break;
114 # else
115  if (myrank == 0) fprintf(stderr, "WARNING: MUMPS not available as coarse solver (rebuild Trilinos with MUMPS and MPI enabled)\n");
116  break;
117 # endif
118 #else
119  case 2:
120  if (myrank == 0) fprintf(stderr, "WARNING: KLU not available as coarse solver (rebuild Trilinos with Amesos enabled)\n");
121  break;
122  case 3:
123  if (myrank == 0) fprintf(stderr, "WARNING: MUMPS not available as coarse solver (rebuild Trilinos with Amesos, MUMPS and MPI enabled)\n");
124  break;
125 #endif
126  default:
127  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_CoarseSolver=%d (ignored)\n", opt[0]);
128  }
129 
130  switch (opt[1]) {
131  case 0:
132  mlopt->SmootherType = DEFAULT_SMOOTHER_TYPE;
133  break;
134  case 1:
135  mlopt->SmootherType = Cheby;
136  break;
137  case 2:
138  mlopt->SmootherType = SymBlockGaussSeidel;
139  mlopt->FlgUseHECMWSmoother = 1;
140  break;
141  case 3:
142  mlopt->SmootherType = Jacobi;
143  mlopt->FlgUseHECMWSmoother = 1;
144  break;
145  default:
146  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_Smoother=%d (ignored)\n", opt[1]);
147  }
148 
149  switch (opt[2]) {
150  case 0:
151  mlopt->MGType = DEFAULT_MG_TYPE;
152  break;
153  case 1:
154  mlopt->MGType = ML_MGV;
155  break;
156  case 2:
157  mlopt->MGType = ML_MGW;
158  break;
159  case 3:
160  mlopt->MGType = ML_MGFULLV;
161  break;
162  default:
163  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_MGCycle=%d (ignored)\n", opt[2]);
164  }
165 
166  if (opt[3] > 0) {
167  mlopt->MaxLevels = opt[3];
168  } else {
169  if (opt[3] < 0) {
170  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_MaxLevels=%d (ignored)\n", opt[3]);
171  }
172  mlopt->MaxLevels = DEFAULT_MAX_LEVELS;
173  }
174 
175  switch (opt[4]) {
176  case 0:
177  mlopt->CoarsenScheme = DEFAULT_COARSEN_SCHEME;
178  break;
179  case 1:
180  mlopt->CoarsenScheme = UncoupledMIS;
181  break;
182  case 2:
183  mlopt->CoarsenScheme = METIS;
184  break;
185  case 3:
186  mlopt->CoarsenScheme = ParMETIS;
187  break;
188  case 4:
189  mlopt->CoarsenScheme = Zoltan;
190  break;
191  case 5:
192  mlopt->CoarsenScheme = DD;
193  break;
194  default:
195  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_CoarseningScheme=%d (ignored)\n", opt[4]);
196  }
197 
198  if (opt[5] > 0) {
199  mlopt->NumSweeps = opt[5];
200  } else {
201  if (opt[5] < 0) {
202  if (myrank == 0) fprintf(stderr, "WARNING: invalid ML_NumSweep=%d (ignored)\n", opt[5]);
203  }
204  mlopt->NumSweeps = DEFAULT_NUM_SWEEPS;
205  opt[5] = mlopt->NumSweeps;
206  hecmw_ml_set_opt_(id, opt, ierr);
207  if (*ierr != HECMW_SUCCESS) return;
208  }
209 
210  if (opt[6] > 0) {
211  mlopt->MaxCoarseSize = opt[6];
212  } else {
213  if (mlopt->CoarseSolver == MUMPS) {
214  mlopt->MaxCoarseSize = MAX_COARSE_SIZE_MUMPS;
215  } else if (mlopt->CoarseSolver == KLU) {
216  mlopt->MaxCoarseSize = MAX_COARSE_SIZE_KLU;
217  } else {
218  mlopt->MaxCoarseSize = -1; /* use default (128? 32?) */
219  }
220  }
221 }
222 
223 void ml_options_print(struct ml_options *mlopt, FILE *fp, int myrank, int loglevel) {
224  char optstr[7][32];
225  switch (mlopt->CoarseSolver) {
226  case Smoother:
227  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarse solver is smoother\n");
228  snprintf(optstr[0], sizeof(optstr[0]), "Smoother");
229  break;
230  case KLU:
231  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarse solver is KLU\n");
232  snprintf(optstr[0], sizeof(optstr[0]), "KLU");
233  break;
234  case MUMPS:
235  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarse solver is MUMPS\n");
236  snprintf(optstr[0], sizeof(optstr[0]), "MUMPS");
237  break;
238  }
239  switch (mlopt->SmootherType) {
240  case Cheby:
241  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML smoother is Cheby\n");
242  snprintf(optstr[1], sizeof(optstr[1]), "Cheby");
243  break;
244  case SymBlockGaussSeidel:
245  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML smoother is SymBlockGaussSeidel\n");
246  snprintf(optstr[1], sizeof(optstr[1]), "SymBlockGaussSeidel");
247  break;
248  case Jacobi:
249  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML smoother is Jacobi\n");
250  snprintf(optstr[1], sizeof(optstr[1]), "Jacobi");
251  break;
252  }
253  switch (mlopt->MGType) {
254  case ML_MGV:
255  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML multigrid type is V-cycle\n");
256  snprintf(optstr[2], sizeof(optstr[2]), "V-cycle");
257  break;
258  case ML_MGW:
259  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML multigrid type is W-cycle\n");
260  snprintf(optstr[2], sizeof(optstr[2]), "W-cycle");
261  break;
262  case ML_MGFULLV:
263  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML multigrid type is Full-V-cycle\n");
264  snprintf(optstr[2], sizeof(optstr[2]), "Full-V-cycle");
265  break;
266  }
267  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML num of max levels is %d\n", mlopt->MaxLevels);
268  snprintf(optstr[3], sizeof(optstr[3]), "MaxLevels=%d", mlopt->MaxLevels);
269  switch (mlopt->CoarsenScheme) {
270  case UncoupledMIS:
271  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarsening scheme is UncoupledMIS\n");
272  snprintf(optstr[4], sizeof(optstr[4]), "UncoupledMIS");
273  break;
274  case METIS:
275  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarsening scheme is METIS\n");
276  snprintf(optstr[4], sizeof(optstr[4]), "METIS");
277  break;
278  case ParMETIS:
279  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarsening scheme is ParMETIS\n");
280  snprintf(optstr[4], sizeof(optstr[4]), "ParMETIS");
281  break;
282  case Zoltan:
283  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarsening scheme is Zoltan\n");
284  snprintf(optstr[4], sizeof(optstr[4]), "Zoltan");
285  break;
286  case DD:
287  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML coarsening scheme is DD\n");
288  snprintf(optstr[4], sizeof(optstr[4]), "DD");
289  break;
290  }
291  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML num of smoother sweeps is %d\n", mlopt->NumSweeps);
292  snprintf(optstr[5], sizeof(optstr[5]), "NumSweeps=%d", mlopt->NumSweeps);
293  if (loglevel >= 2 && myrank == 0) fprintf(fp, "INFO: ML max coarse size is %d\n", mlopt->MaxCoarseSize);
294  snprintf(optstr[6], sizeof(optstr[6]), "MaxCoarseSize=%d", mlopt->MaxCoarseSize);
295  if (loglevel >= 1 && myrank == 0) {
296  fprintf(fp, "INFO: ML options: %s %s %s %s %s %s %s\n",
297  optstr[0], optstr[1], optstr[2], optstr[3], optstr[4], optstr[5], optstr[6]);
298  }
299 }
300 
301 /*
302  * static variable
303  */
304 
305 struct ml_info {
306  struct ml_options opt;
307  ML *ml_object;
308  ML_Aggregate *agg_object;
309  int ndof;
310 };
311 
312 #define MAX_MI 8
313 
314 static struct ml_info MLInfo[MAX_MI];
315 
316 /*
317  * public functions
318  */
319 
320 void hecmw_ML_wrapper_setup(int *id, int *sym, int *Ndof, int *ierr) {
321  int loglevel, myrank;
322  int N_grids, N_levels;
323  int nlocal, nlocal_allcolumns;
324  struct ml_options *mlopt;
325  ML *ml_object;
326  ML_Aggregate *agg_object;
327 
328  if (*id <= 0 && MAX_MI < *id) {
329  *ierr = HECMW_ERROR;
330  return;
331  }
332 
333  hecmw_ml_get_loglevel_(id, &loglevel);
334  ML_Set_PrintLevel(loglevel);
335 
337 
338  /* Get options */
339  mlopt = &(MLInfo[*id - 1].opt);
340  ml_options_set(mlopt, id, myrank, ierr);
341  ml_options_print(mlopt, stderr, myrank, loglevel);
342 
343  /* ML object */
344  N_grids = mlopt->MaxLevels;
345  ML_Create(&ml_object, N_grids);
346  hecmw_ml_get_nlocal_(id, &nlocal, &nlocal_allcolumns, ierr);
347  if (*ierr != HECMW_SUCCESS) return;
348  ML_Init_Amatrix(ml_object, 0, nlocal, nlocal, id);
349  if (*Ndof == 3) {
350  ML_Set_Amatrix_Getrow(ml_object, 0, hecmw_ML_getrow_33, hecmw_ML_comm_33, nlocal_allcolumns);
351  ML_Set_Amatrix_Matvec(ml_object, 0, hecmw_ML_matvec_33);
352  } else {
353  ML_Set_Amatrix_Getrow(ml_object, 0, hecmw_ML_getrow_nn, hecmw_ML_comm_nn, nlocal_allcolumns);
354  ML_Set_Amatrix_Matvec(ml_object, 0, hecmw_ML_matvec_nn);
355  }
356 
357  /* if (!(*sym)) ML_Set_Symmetrize(ml_object, ML_YES); */
358 
359  /* Aggregate */
360  ML_Aggregate_Create(&agg_object);
361 
362  /* Null Space (Rigid Body Mode) */
363  {
364  int num_PDE_eqns = *Ndof;
365  int null_dim;
366  double *null_vect;
367  int leng = nlocal;
368  if (*Ndof == 1) {
369  null_dim = 1;
370  } else if (*Ndof == 2) {
371  null_dim = 3;
372  } else {
373  null_dim = 6;
374  }
375  null_vect = (double *)HECMW_malloc(sizeof(double) * null_dim * leng);
376  if (!null_vect) {
377  HECMW_set_error(errno, "");
378  abort();
379  }
380  hecmw_ml_get_rbm_(id, null_vect, ierr);
381  if (*ierr != HECMW_SUCCESS) return;
382  ML_Aggregate_Set_NullSpace(agg_object, num_PDE_eqns, null_dim, null_vect, leng);
383  HECMW_free(null_vect);
384  }
385 
386  /* Max coarse size */
387  {
388  int nglobal;
389  HECMW_Allreduce(&nlocal, &nglobal, 1, HECMW_INT, HECMW_SUM, HECMW_comm_get_comm());
390  if (nglobal <= mlopt->MaxCoarseSize) mlopt->MaxCoarseSize = nglobal - 1; /* coarsen at least once */
391  if (mlopt->MaxCoarseSize > 0) ML_Aggregate_Set_MaxCoarseSize(agg_object, mlopt->MaxCoarseSize);
392  }
393 
394  /* options */
395  /* CoarsenScheme */
396  {
397  if (mlopt->CoarsenScheme == UncoupledMIS) {
398  ML_Aggregate_Set_CoarsenScheme_UncoupledMIS(agg_object);
399  } else if (mlopt->CoarsenScheme == METIS) {
400  ML_Aggregate_Set_CoarsenScheme_METIS(agg_object);
401  } else if (mlopt->CoarsenScheme == ParMETIS) {
402  ML_Aggregate_Set_CoarsenScheme_ParMETIS(agg_object);
403  } else if (mlopt->CoarsenScheme == Zoltan) {
404  ML_Aggregate_Set_CoarsenScheme_Zoltan(agg_object);
405  } else if (mlopt->CoarsenScheme == DD) {
406  ML_Aggregate_Set_CoarsenScheme_DD(agg_object);
407  }
408  /*
409  if (mlopt->MaxLevels == 2) {
410  ML_Aggregate_Set_LocalNumber(ml_object, agg_object, ML_ALL_LEVELS, 1);
411  } else if (mlopt->MaxLevels == 3) {
412  ML_Aggregate_Set_NodesPerAggr(ml_object, agg_object, ML_ALL_LEVELS, 512);
413  ML_Aggregate_Set_ReqLocalCoarseSize(ml_object->ML_num_levels, agg_object, ML_ALL_LEVELS, 128);
414  }
415  */
416  }
417  /* ML_Aggregate_Set_Threshold(agg_object, threshold); */
418  /* ML_Aggregate_Set_DampingFactor(agg_object, dampingfactor); */
419 
420  /* eigen-analysis */
421  /* ML_Set_SpectralNormScheme_PowerMethod(ml_object); */ /* power-method (default) */
422  if (*sym) {
423  ML_Set_SpectralNormScheme_Calc(ml_object); /* cg */
424  }
425  /* ML_Set_SpectralNorm_Iterations(ml_object, 10); */ /* default: 10 */
426 
427  /* repartitioning */
428  /* ML_Repartition_Activate(ml_object); */
429  /* ML_Repartition_Set_LargestMinMaxRatio(ml_object, 1.3); */ /* default: 1.3 */
430  /* ML_Repartition_Set_MinPerProc(ml_object, 512); */ /* default: 512 */
431  /* ML_Repartition_Set_PutOnSingleProc(ml_object, i); */
432  /* ML_Repartition_Set_StartLevel(ml_object, 1); */ /* default: 1 */
433  /* ML_Repartition_Set_Partitioner(ml_object, ML_USEPARMETIS); */ /* default: ML_USEZOLTAN */
434 
435  ML_Aggregate_Set_Dimensions(agg_object, *Ndof);
436 
437  /* Generate MultiGrid */
438  /* N_levels = ML_Gen_MGHierarchy_UsingAggregation(ml_object, 0, ML_INCREASING, agg_object); */
439  N_levels = ML_Gen_MultiLevelHierarchy_UsingAggregation(ml_object, 0, ML_INCREASING, agg_object);
440  if (loglevel >= 1 && myrank == 0) fprintf(stderr, "INFO: ML generated num of levels is %d\n", N_levels);
441  /* A non-positive level count means hierarchy generation failed (e.g. ML built
442  * no aggregates). Do not proceed with a corrupt hierarchy -- report and bail. */
443  if (N_levels < 1) {
444  if (myrank == 0)
445  fprintf(stderr, "ERROR: ML_Gen_MultiLevelHierarchy returned %d levels (aggregation failed)\n", N_levels);
446  *ierr = HECMW_ERROR;
447  return;
448  }
449 
450  /* Smoother */
451  /*
452  * Set pre- and post-smoother for each level
453  * level : num in (0, N_levels-1) or ML_ALL_LEVELS
454  * pre-or-post: ML_PRESMOOTHER, ML_POSTSMOOTHER or ML_BOTH
455  * omega : damping factor for Jacobi, GaussSeidel, etc. (ML_DEFAULT=1.0)
456  */
457  {
458  int level;
459  int coarsest_level = N_levels - 1;
460  /*
461  * levels other than the coarsest level
462  */
463  if (mlopt->SmootherType == Jacobi) {
464  level = 0;
465  if (mlopt->FlgUseHECMWSmoother) {
466  /* use HEC-MW's Block-Diag preconditioner at the finest level */
467  if (*Ndof == 3) {
468  hecmw_ml_smoother_diag_setup_33_(id, ierr);
469  if (*ierr != HECMW_SUCCESS) return;
470  ML_Set_Smoother(ml_object, 0, ML_BOTH, id, hecmw_ML_smoother_diag_apply_33, "HEC-MW");
471  } else {
472  hecmw_ml_smoother_diag_setup_nn_(id, ierr);
473  if (*ierr != HECMW_SUCCESS) return;
474  ML_Set_Smoother(ml_object, 0, ML_BOTH, id, hecmw_ML_smoother_diag_apply_nn, "HEC-MW");
475  }
476  level++;
477  }
478  /* use ML's smoother at other levels */
479  for (; level < coarsest_level; level++) {
480  ML_Gen_Smoother_Jacobi(ml_object, level, ML_BOTH, mlopt->NumSweeps, ML_DEFAULT);
481  }
482  } else if (mlopt->SmootherType == SymBlockGaussSeidel) {
483  level = 0;
484  if (mlopt->FlgUseHECMWSmoother) {
485  /* use HEC-MW's Block-SSOR preconditioner at the finest level */
486  if (*Ndof == 3) {
487  hecmw_ml_smoother_ssor_setup_33_(id, ierr);
488  if (*ierr != HECMW_SUCCESS) return;
489  ML_Set_Smoother(ml_object, 0, ML_BOTH, id, hecmw_ML_smoother_ssor_apply_33, "HEC-MW");
490  } else {
491  hecmw_ml_smoother_ssor_setup_nn_(id, ierr);
492  if (*ierr != HECMW_SUCCESS) return;
493  ML_Set_Smoother(ml_object, 0, ML_BOTH, id, hecmw_ML_smoother_ssor_apply_nn, "HEC-MW");
494  }
495  level++;
496  }
497  /* use ML's smoother at other levels */
498  for (; level < coarsest_level; level++) {
499  ML_Gen_Smoother_SymBlockGaussSeidel(ml_object, level, ML_BOTH, mlopt->NumSweeps, ML_DEFAULT, *Ndof);
500  }
501  } else /* if (mlopt->SmootherType == Cheby) */ {
502  for (level = 0; level < coarsest_level; level++) {
503  ML_Gen_Smoother_Cheby(ml_object, level, ML_BOTH, 20.0, mlopt->NumSweeps);
504  }
505  }
506  /*
507  * coarsest level
508  */
509  if (mlopt->CoarseSolver == MUMPS) {
510 #if TRILINOS_MAJOR_VERSION < 13
511  ML_Gen_Smoother_Amesos(ml_object, coarsest_level, ML_AMESOS_MUMPS, 1, 0.0);
512 #else
513  ML_Gen_Smoother_Amesos(ml_object, coarsest_level, ML_AMESOS_MUMPS, 1, 0.0, 1);
514 #endif
515  } else if (mlopt->CoarseSolver == KLU) {
516 #if TRILINOS_MAJOR_VERSION < 13
517  ML_Gen_Smoother_Amesos(ml_object, coarsest_level, ML_AMESOS_KLU, 1, 0.0);
518 #else
519  ML_Gen_Smoother_Amesos(ml_object, coarsest_level, ML_AMESOS_KLU, 1, 0.0, 1);
520 #endif
521  } else /* if (mlopt->CoarseSolver == Smoother) */ {
522  if (mlopt->SmootherType == Jacobi) {
523  ML_Gen_Smoother_Jacobi(ml_object, coarsest_level, ML_BOTH, 3, ML_DEFAULT);
524  } else if (mlopt->SmootherType == SymBlockGaussSeidel) {
525  ML_Gen_Smoother_SymBlockGaussSeidel(ml_object, coarsest_level, ML_BOTH, 3, ML_DEFAULT, *Ndof);
526  } else /* if (mlopt->SmootherType == Cheby) */ {
527  ML_Gen_Smoother_Cheby(ml_object, coarsest_level, ML_BOTH, 20.0, 2);
528  }
529  }
530  }
531 
532  /* Solver */
533  if (ML_Gen_Solver(ml_object, mlopt->MGType, 0, N_levels - 1) != 0) {
534  if (myrank == 0) fprintf(stderr, "ERROR: ML_Gen_Solver failed\n");
535  *ierr = HECMW_ERROR;
536  return;
537  }
538 
539  /* Save objects */
540  MLInfo[*id - 1].ml_object = ml_object;
541  MLInfo[*id - 1].agg_object = agg_object;
542  MLInfo[*id - 1].ndof = *Ndof;
543  *ierr = HECMW_SUCCESS; /* reached only on the fully-successful path */
544 }
545 
546 void hecmw_ML_wrapper_apply(int *id, double rhs[], int *ierr) {
547  int nlocal, nlocal_allcolumns;
548  double *sol;
549  int i;
550  ML *ml_object;
551  if (*id <= 0 && MAX_MI < *id) {
552  *ierr = HECMW_ERROR;
553  return;
554  }
555  ml_object = MLInfo[*id - 1].ml_object;
556  hecmw_ml_get_nlocal_(id, &nlocal, &nlocal_allcolumns, ierr);
557  if (*ierr != HECMW_SUCCESS) return;
558  sol = (double *)HECMW_malloc(sizeof(double) * nlocal_allcolumns);
559  if (!sol) {
560  HECMW_set_error(errno, "");
561  abort();
562  }
563  /* MultiGrid V-cycle */
564  ML_Solve_MGV(ml_object, rhs, sol);
565  for (i = 0; i < nlocal; i++) {
566  rhs[i] = sol[i];
567  }
568  HECMW_free(sol);
569 }
570 
571 void hecmw_ML_wrapper_clear(int *id, int *ierr) {
572  struct ml_options *mlopt = &(MLInfo[*id - 1].opt);
573  if (*id <= 0 && MAX_MI < *id) {
574  *ierr = HECMW_ERROR;
575  return;
576  }
577  ML_Aggregate_Destroy(&(MLInfo[*id - 1].agg_object));
578  ML_Destroy(&(MLInfo[*id - 1].ml_object));
579 
580  if (mlopt->FlgUseHECMWSmoother) {
581  if (mlopt->SmootherType == Jacobi) {
582  if (MLInfo[*id - 1].ndof == 3) {
583  hecmw_ml_smoother_diag_clear_33_(id, ierr);
584  } else {
585  hecmw_ml_smoother_diag_clear_nn_(id, ierr);
586  }
587  } else if (mlopt->SmootherType == SymBlockGaussSeidel) {
588  if (MLInfo[*id - 1].ndof == 3) {
589  hecmw_ml_smoother_ssor_clear_33_(id, ierr);
590  } else {
591  hecmw_ml_smoother_ssor_clear_nn_(id, ierr);
592  }
593  }
594  }
595 }
596 
597 #else /* WITH_ML */
598 
599 void hecmw_ML_wrapper_setup(int *id, int *sym, int *Ndof, int *ierr) {
600  fprintf(stderr, "ERROR: ML not enabled\n");
601  *ierr = HECMW_ERROR;
602 }
603 void hecmw_ML_wrapper_apply(int *id, double rhs[], int *ierr) {
604  fprintf(stderr, "ERROR: ML not enabled\n");
605  *ierr = HECMW_ERROR;
606 }
607 void hecmw_ML_wrapper_clear(int *id, int *ierr) {
608  fprintf(stderr, "ERROR: ML not enabled\n");
609  *ierr = HECMW_ERROR;
610 }
611 
612 #endif /* WITH_ML */
613 
614 /* Fortran interface */
615 
616 void hecmw_ml_wrapper_setup_(int *id, int *sym, int *ndof, int *ierr) {
617  hecmw_ML_wrapper_setup(id, sym, ndof, ierr);
618 }
619 void hecmw_ml_wrapper_setup__(int *id, int *sym, int *ndof, int *ierr) {
620  hecmw_ML_wrapper_setup(id, sym, ndof, ierr);
621 }
622 void HECMW_ML_WRAPPER_SETUP(int *id, int *sym, int *ndof, int *ierr) {
623  hecmw_ML_wrapper_setup(id, sym, ndof, ierr);
624 }
625 
626 void hecmw_ml_wrapper_apply_(int *id, double rhs[], int *ierr) {
627  hecmw_ML_wrapper_apply(id, rhs, ierr);
628 }
629 void hecmw_ml_wrapper_apply__(int *id, double rhs[], int *ierr) {
630  hecmw_ML_wrapper_apply(id, rhs, ierr);
631 }
632 void HECMW_ML_WRAPPER_APPLY(int *id, double rhs[], int *ierr) {
633  hecmw_ML_wrapper_apply(id, rhs, ierr);
634 }
635 
636 void hecmw_ml_wrapper_clear_(int *id, int *ierr) {
637  hecmw_ML_wrapper_clear(id, ierr);
638 }
639 void hecmw_ml_wrapper_clear__(int *id, int *ierr) {
640  hecmw_ML_wrapper_clear(id, ierr);
641 }
642 void HECMW_ML_WRAPPER_CLEAR(int *id, int *ierr) {
643  hecmw_ML_wrapper_clear(id, ierr);
644 }
void hecmw_ml_get_loglevel_(int *id, int *level)
void hecmw_ml_set_opt_(int *id, int opt[], int *ierr)
void hecmw_ml_get_opt_(int *id, int opt[], int *ierr)
void hecmw_ml_get_nlocal_(int *id, int *nlocal, int *nlocal_allcolumns, int *ierr)
void hecmw_ml_get_rbm_(int *id, double rbm[], int *ierr)
void hecmw_ml_wrapper_clear_(int *id, int *ierr)
void hecmw_ML_wrapper_apply(int *id, double rhs[], int *ierr)
void hecmw_ml_wrapper_apply__(int *id, double rhs[], int *ierr)
void hecmw_ml_wrapper_setup__(int *id, int *sym, int *ndof, int *ierr)
void hecmw_ml_wrapper_setup_(int *id, int *sym, int *ndof, int *ierr)
void hecmw_ML_wrapper_setup(int *id, int *sym, int *Ndof, int *ierr)
void hecmw_ML_wrapper_clear(int *id, int *ierr)
void HECMW_ML_WRAPPER_CLEAR(int *id, int *ierr)
void HECMW_ML_WRAPPER_SETUP(int *id, int *sym, int *ndof, int *ierr)
void HECMW_ML_WRAPPER_APPLY(int *id, double rhs[], int *ierr)
void hecmw_ml_wrapper_apply_(int *id, double rhs[], int *ierr)
void hecmw_ml_wrapper_clear__(int *id, int *ierr)
int HECMW_Comm_rank(HECMW_Comm comm, int *rank)
Definition: hecmw_comm.c:18
HECMW_Comm HECMW_comm_get_comm(void)
Definition: hecmw_comm.c:751
int HECMW_Allreduce(void *sendbuf, void *recvbuf, int count, HECMW_Datatype datatype, HECMW_Op op, HECMW_Comm comm)
Definition: hecmw_comm.c:404
#define HECMW_INT
Definition: hecmw_config.h:48
#define HECMW_SUM
Definition: hecmw_config.h:60
#define HECMW_ERROR
Definition: hecmw_config.h:81
#define HECMW_SUCCESS
Definition: hecmw_config.h:79
int HECMW_set_error(int errorno, const char *fmt,...)
Definition: hecmw_error.c:33
#define HECMW_free(ptr)
Definition: hecmw_malloc.h:24
#define HECMW_malloc(size)
Definition: hecmw_malloc.h:20
int * level
integer(kind=kint) myrank
PARALLEL EXECUTION.
Definition: m_fstr.F90:103