Fast Auxiliary Space Preconditioning 2.7.7 Aug/28/2022
Loading...
Searching...
No Matches
PreAMGSetupSA.c
Go to the documentation of this file.
1
22#include <math.h>
23#include <time.h>
24
25#ifdef _OPENMP
26#include <omp.h>
27#endif
28
29#include "fasp.h"
30#include "fasp_functs.h"
31
32/*---------------------------------*/
33/*-- Declare Private Functions --*/
34/*---------------------------------*/
35
36#include "PreAMGAggregation.inl"
37#include "PreAMGAggregationCSR.inl"
38
39static SHORT amg_setup_smoothP_smoothR (AMG_data *, AMG_param *);
40static SHORT amg_setup_smoothP_unsmoothR (AMG_data *, AMG_param *);
41static void smooth_agg (dCSRmat *, dCSRmat *, dCSRmat *, AMG_param *, dCSRmat *);
42
43/*---------------------------------*/
44/*-- Public Functions --*/
45/*---------------------------------*/
46
64 AMG_param *param)
65{
66 const SHORT prtlvl = param->print_level;
67 const SHORT smoothR = param->smooth_restriction;
68 SHORT status = FASP_SUCCESS;
69
70 // Output some info for debuging
71 if ( prtlvl > PRINT_NONE ) printf("\nSetting up SA AMG ...\n");
72
73#if DEBUG_MODE > 0
74 printf("### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
75 printf("### DEBUG: nr=%d, nc=%d, nnz=%d\n",
76 mgl[0].A.row, mgl[0].A.col, mgl[0].A.nnz);
77#endif
78
79 if ( smoothR ) { // Default: smoothed P, smoothed R
80 status = amg_setup_smoothP_smoothR(mgl, param);
81 }
82 else { // smoothed P, unsmoothed R
83 status = amg_setup_smoothP_unsmoothR(mgl, param);
84 }
85
86#if DEBUG_MODE > 0
87 printf("### DEBUG: [--End--] %s ...\n", __FUNCTION__);
88#endif
89
90 return status;
91}
92
93/*---------------------------------*/
94/*-- Private Functions --*/
95/*---------------------------------*/
96
115static void smooth_agg (dCSRmat *A,
116 dCSRmat *tentp,
117 dCSRmat *P,
118 AMG_param *param,
119 dCSRmat *N)
120{
121 const SHORT filter = param->smooth_filter;
122 const INT row = A->row, col= A->col;
123 const REAL smooth_factor = param->tentative_smooth;
124
125 dCSRmat S;
126 dvector diag; // diagonal entries
127
128 REAL row_sum_A, row_sum_N;
129 INT i,j;
130
131 /* Step 1. Form smoother */
132
133 /* Without filter: Using A for damped Jacobian smoother */
134 if ( filter != ON ) {
135
136 // copy structure from A
137 S = fasp_dcsr_create(row, col, A->IA[row]);
138
139#ifdef _OPENMP
140#pragma omp parallel for if(row>OPENMP_HOLDS)
141#endif
142 for ( i=0; i<=row; ++i ) S.IA[i] = A->IA[i];
143 for ( i=0; i<S.IA[S.row]; ++i ) S.JA[i] = A->JA[i];
144
145 fasp_dcsr_getdiag(0, A, &diag); // get the diagonal entries of A
146
147 // check the diagonal entries.
148 // if it is too small, use Richardson smoother for the corresponding row
149#ifdef _OPENMP
150#pragma omp parallel for if(row>OPENMP_HOLDS)
151#endif
152 for (i=0; i<row; ++i) {
153 if (ABS(diag.val[i]) < 1e-6) diag.val[i] = 1.0;
154 }
155
156#ifdef _OPENMP
157#pragma omp parallel for if(row>OPENMP_HOLDS) private(j)
158#endif
159 for (i=0; i<row; ++i) {
160 for (j=S.IA[i]; j<S.IA[i+1]; ++j) {
161 if (S.JA[j] == i) {
162 S.val[j] = 1 - smooth_factor * A->val[j] / diag.val[i];
163 }
164 else {
165 S.val[j] = - smooth_factor * A->val[j] / diag.val[i];
166 }
167 }
168 }
169 }
170
171 /* Using filtered A for damped Jacobian smoother */
172 else {
173 /* Form filtered A and store in N */
174#ifdef _OPENMP
175#pragma omp parallel for private(j, row_sum_A, row_sum_N) if (row>OPENMP_HOLDS)
176#endif
177 for (i=0; i<row; ++i) {
178 for (row_sum_A = 0.0, j=A->IA[i]; j<A->IA[i+1]; ++j) {
179 if (A->JA[j] != i) row_sum_A += A->val[j];
180 }
181
182 for (row_sum_N = 0.0, j=N->IA[i]; j<N->IA[i+1]; ++j) {
183 if (N->JA[j] != i) row_sum_N += N->val[j];
184 }
185
186 for (j=N->IA[i]; j<N->IA[i+1]; ++j) {
187 if (N->JA[j] == i) {
188 // The original paper has a wrong sign!!! --Chensong
189 N->val[j] += row_sum_A - row_sum_N;
190 }
191 }
192 }
193
194 // copy structure from N (filtered A)
195 S = fasp_dcsr_create(row, col, N->IA[row]);
196
197#ifdef _OPENMP
198#pragma omp parallel for if(row>OPENMP_HOLDS)
199#endif
200 for (i=0; i<=row; ++i) S.IA[i] = N->IA[i];
201
202 for (i=0; i<S.IA[S.row]; ++i) S.JA[i] = N->JA[i];
203
204 fasp_dcsr_getdiag(0, N, &diag); // get the diagonal entries of N (filtered A)
205
206 // check the diagonal entries.
207 // if it is too small, use Richardson smoother for the corresponding row
208#ifdef _OPENMP
209#pragma omp parallel for if(row>OPENMP_HOLDS)
210#endif
211 for (i=0;i<row;++i) {
212 if (ABS(diag.val[i]) < 1e-6) diag.val[i] = 1.0;
213 }
214
215#ifdef _OPENMP
216#pragma omp parallel for if(row>OPENMP_HOLDS) private(i,j)
217#endif
218 for (i=0;i<row;++i) {
219 for (j=S.IA[i]; j<S.IA[i+1]; ++j) {
220 if (S.JA[j] == i) {
221 S.val[j] = 1 - smooth_factor * N->val[j] / diag.val[i];
222 }
223 else {
224 S.val[j] = - smooth_factor * N->val[j] / diag.val[i];
225 }
226 }
227 }
228
229 }
230
231 fasp_dvec_free(&diag);
232
233 /* Step 2. Smooth the tentative prolongation P = S*tenp */
234 fasp_blas_dcsr_mxm(&S, tentp, P); // Note: think twice about this.
235 P->nnz = P->IA[P->row];
236 fasp_dcsr_free(&S);
237}
238
254static SHORT amg_setup_smoothP_smoothR (AMG_data *mgl,
255 AMG_param *param)
256{
257 const SHORT prtlvl = param->print_level;
258 const SHORT cycle_type = param->cycle_type;
259 const SHORT csolver = param->coarse_solver;
260 const SHORT min_cdof = MAX(param->coarse_dof,50);
261 const INT m = mgl[0].A.row;
262
263 // local variables
264 SHORT max_levels = param->max_levels, lvl = 0, status = FASP_SUCCESS;
265 INT i, j;
266 REAL setup_start, setup_end;
267 ILU_param iluparam;
268 SWZ_param swzparam;
269
270#if DEBUG_MODE > 0
271 printf("### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
272#endif
273
274 fasp_gettime(&setup_start);
275
276 // level info (fine: 0; coarse: 1)
277 ivector *vertices = (ivector *)fasp_mem_calloc(max_levels,sizeof(ivector));
278
279 // each elvel stores the information of the number of aggregations
280 INT *num_aggs = (INT *)fasp_mem_calloc(max_levels,sizeof(INT));
281
282 // each level stores the information of the strongly coupled neighbourhood
283 dCSRmat *Neighbor = (dCSRmat *)fasp_mem_calloc(max_levels,sizeof(dCSRmat));
284
285 // each level stores the information of the tentative prolongations
286 dCSRmat *tentp = (dCSRmat *)fasp_mem_calloc(max_levels,sizeof(dCSRmat));
287
288 // Initialize level information
289 for ( i = 0; i < max_levels; ++i ) num_aggs[i] = 0;
290
291 mgl[0].near_kernel_dim = 1;
292 mgl[0].near_kernel_basis = (REAL **)fasp_mem_calloc(mgl->near_kernel_dim,sizeof(REAL*));
293
294 for ( i = 0; i < mgl->near_kernel_dim; ++i ) {
295 mgl[0].near_kernel_basis[i] = (REAL *)fasp_mem_calloc(m,sizeof(REAL));
296 for ( j = 0; j < m; ++j ) mgl[0].near_kernel_basis[i][j] = 1.0;
297 }
298
299 // Initialize ILU parameters
300 mgl->ILU_levels = param->ILU_levels;
301 if ( param->ILU_levels > 0 ) {
302 iluparam.print_level = param->print_level;
303 iluparam.ILU_lfil = param->ILU_lfil;
304 iluparam.ILU_droptol = param->ILU_droptol;
305 iluparam.ILU_relax = param->ILU_relax;
306 iluparam.ILU_type = param->ILU_type;
307 }
308
309 // Initialize Schwarz parameters
310 mgl->SWZ_levels = param->SWZ_levels;
311 if ( param->SWZ_levels > 0 ) {
312 swzparam.SWZ_mmsize = param->SWZ_mmsize;
313 swzparam.SWZ_maxlvl = param->SWZ_maxlvl;
314 swzparam.SWZ_type = param->SWZ_type;
315 swzparam.SWZ_blksolver = param->SWZ_blksolver;
316 }
317
318 // Initialize AMLI coefficients
319 if ( cycle_type == AMLI_CYCLE ) {
320 const INT amlideg = param->amli_degree;
321 param->amli_coef = (REAL *)fasp_mem_calloc(amlideg+1,sizeof(REAL));
322 REAL lambda_max = 2.0, lambda_min = lambda_max/4;
323 fasp_amg_amli_coef(lambda_max, lambda_min, amlideg, param->amli_coef);
324 }
325
326#if DIAGONAL_PREF
327 fasp_dcsr_diagpref(&mgl[0].A); // reorder each row to make diagonal appear first
328#endif
329
330 /*----------------------------*/
331 /*--- checking aggregation ---*/
332 /*----------------------------*/
333 if ( param->aggregation_type == PAIRWISE )
334 param->pair_number = MIN(param->pair_number, max_levels);
335
336 // Main AMG setup loop
337 while ( (mgl[lvl].A.row > min_cdof) && (lvl < max_levels-1) ) {
338
339#if DEBUG_MODE > 2
340 printf("### DEBUG: level = %d, row = %d, nnz = %d\n",
341 lvl, mgl[lvl].A.row, mgl[lvl].A.nnz);
342#endif
343
344 /*-- setup ILU decomposition if necessary */
345 if ( lvl < param->ILU_levels ) {
346 status = fasp_ilu_dcsr_setup(&mgl[lvl].A, &mgl[lvl].LU, &iluparam);
347 if ( status < 0 ) {
348 if ( prtlvl > PRINT_MIN ) {
349 printf("### WARNING: ILU setup on level-%d failed!\n", lvl);
350 printf("### WARNING: Disable ILU for level >= %d.\n", lvl);
351 }
352 param->ILU_levels = lvl;
353 }
354 }
355
356 /* -- setup Schwarz smoother if necessary */
357 if ( lvl < param->SWZ_levels ) {
358 mgl[lvl].Schwarz.A = fasp_dcsr_sympart(&mgl[lvl].A);
359 fasp_dcsr_shift(&(mgl[lvl].Schwarz.A), 1);
360 status = fasp_swz_dcsr_setup(&mgl[lvl].Schwarz, &swzparam);
361 if ( status < 0 ) {
362 if ( prtlvl > PRINT_MIN ) {
363 printf("### WARNING: Schwarz on level-%d failed!\n", lvl);
364 printf("### WARNING: Disable Schwarz for level >= %d.\n", lvl);
365 }
366 param->SWZ_levels = lvl;
367 }
368 }
369
370 /*-- Aggregation --*/
371 status = aggregation_vmb(&mgl[lvl].A, &vertices[lvl], param, lvl+1,
372 &Neighbor[lvl], &num_aggs[lvl]);
373
374 // Check 1: Did coarsening step succeed?
375 if ( status < 0 ) {
376 // When error happens, stop at the current multigrid level!
377 if ( prtlvl > PRINT_MIN ) {
378 printf("### WARNING: Forming aggregates on level-%d failed!\n", lvl);
379 }
380 status = FASP_SUCCESS;
381 fasp_ivec_free(&vertices[lvl]);
382 fasp_dcsr_free(&Neighbor[lvl]);
383 break;
384 }
385
386 /* -- Form Tentative prolongation --*/
387 form_tentative_p(&vertices[lvl], &tentp[lvl], mgl[0].near_kernel_basis,
388 num_aggs[lvl]);
389
390 /* -- Form smoothed prolongation -- */
391 smooth_agg(&mgl[lvl].A, &tentp[lvl], &mgl[lvl].P, param, &Neighbor[lvl]);
392
393 // Check 2: Is coarse sparse too small?
394 if ( mgl[lvl].P.col < MIN_CDOF ) {
395 fasp_ivec_free(&vertices[lvl]);
396 fasp_dcsr_free(&Neighbor[lvl]);
397 fasp_dcsr_free(&tentp[lvl]);
398 break;
399 }
400
401 // Check 3: Does this coarsening step too aggressive?
402 if ( mgl[lvl].P.row > mgl[lvl].P.col * MAX_CRATE ) {
403 if ( prtlvl > PRINT_MIN ) {
404 printf("### WARNING: Coarsening might be too aggressive!\n");
405 printf("### WARNING: Fine level = %d, coarse level = %d. Discard!\n",
406 mgl[lvl].P.row, mgl[lvl].P.col);
407 }
408 fasp_ivec_free(&vertices[lvl]);
409 fasp_dcsr_free(&Neighbor[lvl]);
410 fasp_dcsr_free(&tentp[lvl]);
411 break;
412 }
413
414 /*-- Form restriction --*/
415 fasp_dcsr_trans(&mgl[lvl].P, &mgl[lvl].R);
416
417 /*-- Form coarse level stiffness matrix --*/
418 fasp_blas_dcsr_rap(&mgl[lvl].R, &mgl[lvl].A, &mgl[lvl].P, &mgl[lvl+1].A);
419
420 fasp_dcsr_free(&Neighbor[lvl]);
421 fasp_dcsr_free(&tentp[lvl]);
422 fasp_ivec_free(&vertices[lvl]);
423
424 ++lvl;
425
426#if DIAGONAL_PREF
427 // reorder each row to make diagonal appear first
428 fasp_dcsr_diagpref(&mgl[lvl].A);
429#endif
430
431 // Check 4: Is this coarsening ratio too small?
432 if ( (REAL)mgl[lvl].P.col > mgl[lvl].P.row * MIN_CRATE ) {
433 if ( prtlvl > PRINT_MIN ) {
434 printf("### WARNING: Coarsening rate is too small!\n");
435 printf("### WARNING: Fine level = %d, coarse level = %d. Discard!\n",
436 mgl[lvl].P.row, mgl[lvl].P.col);
437 }
438
439 break;
440 }
441
442 } // end of the main while loop
443
444 // Setup coarse level systems for direct solvers
445 switch (csolver) {
446
447#if WITH_MUMPS
448 case SOLVER_MUMPS: {
449 // Setup MUMPS direct solver on the coarsest level
450 mgl[lvl].mumps.job = 1;
451 fasp_solver_mumps_steps(&mgl[lvl].A, &mgl[lvl].b, &mgl[lvl].x, &mgl[lvl].mumps);
452 break;
453 }
454#endif
455
456#if WITH_UMFPACK
457 case SOLVER_UMFPACK: {
458 // Need to sort the matrix A for UMFPACK to work
459 dCSRmat Ac_tran;
460 Ac_tran = fasp_dcsr_create(mgl[lvl].A.row, mgl[lvl].A.col, mgl[lvl].A.nnz);
461 fasp_dcsr_transz(&mgl[lvl].A, NULL, &Ac_tran);
462 // It is equivalent to do transpose and then sort
463 // fasp_dcsr_trans(&mgl[lvl].A, &Ac_tran);
464 // fasp_dcsr_sort(&Ac_tran);
465 fasp_dcsr_cp(&Ac_tran, &mgl[lvl].A);
466 fasp_dcsr_free(&Ac_tran);
467 mgl[lvl].Numeric = fasp_umfpack_factorize(&mgl[lvl].A, 0);
468 break;
469 }
470#endif
471
472#if WITH_PARDISO
473 case SOLVER_PARDISO: {
474 fasp_dcsr_sort(&mgl[lvl].A);
475 fasp_pardiso_factorize(&mgl[lvl].A, &mgl[lvl].pdata, prtlvl);
476 break;
477 }
478#endif
479
480 default:
481 // Do nothing!
482 break;
483 }
484
485 // setup total level number and current level
486 mgl[0].num_levels = max_levels = lvl+1;
487 mgl[0].w = fasp_dvec_create(m);
488
489 for ( lvl = 1; lvl < max_levels; ++lvl) {
490 INT mm = mgl[lvl].A.row;
491 mgl[lvl].num_levels = max_levels;
492 mgl[lvl].b = fasp_dvec_create(mm);
493 mgl[lvl].x = fasp_dvec_create(mm);
494
495 mgl[lvl].cycle_type = cycle_type; // initialize cycle type!
496 mgl[lvl].ILU_levels = param->ILU_levels - lvl; // initialize ILU levels!
497 mgl[lvl].SWZ_levels = param->SWZ_levels -lvl; // initialize Schwarz!
498
499 if ( cycle_type == NL_AMLI_CYCLE )
500 mgl[lvl].w = fasp_dvec_create(3*mm);
501 else
502 mgl[lvl].w = fasp_dvec_create(2*mm);
503 }
504
505#if MULTI_COLOR_ORDER
506 INT Colors,rowmax;
507#ifdef _OPENMP
508 int threads = fasp_get_num_threads();
509 if (threads > max_levels-1 ) threads = max_levels-1;
510#pragma omp parallel for private(lvl,rowmax,Colors) schedule(static, 1) num_threads(threads)
511#endif
512 for (lvl=0; lvl<max_levels-1; lvl++){
513
514#if 1
515 dCSRmat_Multicoloring(&mgl[lvl].A, &rowmax, &Colors);
516#else
517 dCSRmat_Multicoloring_Theta(&mgl[lvl].A, mgl[lvl].GS_Theta, &rowmax, &Colors);
518#endif
519 if ( prtlvl > 1 )
520 printf("mgl[%3d].A.row = %12d, rowmax = %5d, rowavg = %7.2lf, colors = %5d, Theta = %le.\n",
521 lvl, mgl[lvl].A.row, rowmax, (double)mgl[lvl].A.nnz/mgl[lvl].A.row,
522 mgl[lvl].A.color, mgl[lvl].GS_Theta);
523 }
524#endif
525
526 if ( prtlvl > PRINT_NONE ) {
527 fasp_gettime(&setup_end);
528 fasp_amgcomplexity(mgl,prtlvl);
529 fasp_cputime("Smoothed aggregation setup", setup_end - setup_start);
530 }
531
532 fasp_mem_free(vertices); vertices = NULL;
533 fasp_mem_free(num_aggs); num_aggs = NULL;
534 fasp_mem_free(Neighbor); Neighbor = NULL;
535 fasp_mem_free(tentp); tentp = NULL;
536
537#if DEBUG_MODE > 0
538 printf("### DEBUG: [--End--] %s ...\n", __FUNCTION__);
539#endif
540
541 return status;
542}
543
559static SHORT amg_setup_smoothP_unsmoothR (AMG_data *mgl,
560 AMG_param *param)
561{
562 const SHORT prtlvl = param->print_level;
563 const SHORT cycle_type = param->cycle_type;
564 const SHORT csolver = param->coarse_solver;
565 const SHORT min_cdof = MAX(param->coarse_dof,50);
566 const INT m = mgl[0].A.row;
567
568 // local variables
569 SHORT max_levels = param->max_levels, lvl = 0, status = FASP_SUCCESS;
570 INT i, j;
571 REAL setup_start, setup_end;
572 ILU_param iluparam;
573 SWZ_param swzparam;
574
575#if DEBUG_MODE > 0
576 printf("### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
577#endif
578
579 fasp_gettime(&setup_start);
580
581 // level info (fine: 0; coarse: 1)
582 ivector *vertices = (ivector *)fasp_mem_calloc(max_levels,sizeof(ivector));
583
584 // each level stores the information of the number of aggregations
585 INT *num_aggs = (INT *)fasp_mem_calloc(max_levels,sizeof(INT));
586
587 // each level stores the information of the strongly coupled neighbourhood
588 dCSRmat *Neighbor = (dCSRmat *)fasp_mem_calloc(max_levels,sizeof(dCSRmat));
589
590 // each level stores the information of the tentative prolongations
591 dCSRmat *tentp = (dCSRmat *)fasp_mem_calloc(max_levels,sizeof(dCSRmat));
592 dCSRmat *tentr = (dCSRmat *)fasp_mem_calloc(max_levels,sizeof(dCSRmat));
593
594 for ( i = 0; i < max_levels; ++i ) num_aggs[i] = 0;
595
596 mgl[0].near_kernel_dim = 1;
597
598 mgl[0].near_kernel_basis = (REAL **)fasp_mem_calloc(mgl->near_kernel_dim,sizeof(REAL*));
599
600 for ( i = 0; i < mgl->near_kernel_dim; ++i ) {
601 mgl[0].near_kernel_basis[i] = (REAL *)fasp_mem_calloc(m,sizeof(REAL));
602 for ( j = 0; j < m; ++j ) mgl[0].near_kernel_basis[i][j] = 1.0;
603 }
604
605 // Initialize ILU parameters
606 if ( param->ILU_levels > 0 ) {
607 iluparam.print_level = param->print_level;
608 iluparam.ILU_lfil = param->ILU_lfil;
609 iluparam.ILU_droptol = param->ILU_droptol;
610 iluparam.ILU_relax = param->ILU_relax;
611 iluparam.ILU_type = param->ILU_type;
612 }
613
614 // Initialize Schwarz parameters
615 mgl->SWZ_levels = param->SWZ_levels;
616 if ( param->SWZ_levels > 0 ) {
617 swzparam.SWZ_mmsize = param->SWZ_mmsize;
618 swzparam.SWZ_maxlvl = param->SWZ_maxlvl;
619 swzparam.SWZ_type = param->SWZ_type;
620 swzparam.SWZ_blksolver = param->SWZ_blksolver;
621 }
622
623 // Initialize AMLI coefficients
624 if ( cycle_type == AMLI_CYCLE ) {
625 const INT amlideg = param->amli_degree;
626 param->amli_coef = (REAL *)fasp_mem_calloc(amlideg+1,sizeof(REAL));
627 REAL lambda_max = 2.0, lambda_min = lambda_max/4;
628 fasp_amg_amli_coef(lambda_max, lambda_min, amlideg, param->amli_coef);
629 }
630
631 // Main AMG setup loop
632 while ( (mgl[lvl].A.row > min_cdof) && (lvl < max_levels-1) ) {
633
634 /*-- setup ILU decomposition if necessary */
635 if ( lvl < param->ILU_levels ) {
636 status = fasp_ilu_dcsr_setup(&mgl[lvl].A, &mgl[lvl].LU, &iluparam);
637 if ( status < 0 ) {
638 if ( prtlvl > PRINT_MIN ) {
639 printf("### WARNING: ILU setup on level-%d failed!\n", lvl);
640 printf("### WARNING: Disable ILU for level >= %d.\n", lvl);
641 }
642 param->ILU_levels = lvl;
643 }
644 }
645
646 /* -- setup Schwarz smoother if necessary */
647 if ( lvl < param->SWZ_levels ) {
648 mgl[lvl].Schwarz.A = fasp_dcsr_sympart(&mgl[lvl].A);
649 fasp_dcsr_shift(&(mgl[lvl].Schwarz.A), 1);
650 status = fasp_swz_dcsr_setup(&mgl[lvl].Schwarz, &swzparam);
651 if ( status < 0 ) {
652 if ( prtlvl > PRINT_MIN ) {
653 printf("### WARNING: Schwarz on level-%d failed!\n", lvl);
654 printf("### WARNING: Disable Schwarz for level >= %d.\n", lvl);
655 }
656 param->SWZ_levels = lvl;
657 }
658 }
659
660 /*-- Aggregation --*/
661 status = aggregation_vmb(&mgl[lvl].A, &vertices[lvl], param, lvl+1,
662 &Neighbor[lvl], &num_aggs[lvl]);
663
664 // Check 1: Did coarsening step succeeded?
665 if ( status < 0 ) {
666 // When error happens, stop at the current multigrid level!
667 if ( prtlvl > PRINT_MIN ) {
668 printf("### WARNING: Stop coarsening on level=%d!\n", lvl);
669 }
670 status = FASP_SUCCESS; break;
671 }
672
673 /* -- Form Tentative prolongation --*/
674 form_tentative_p(&vertices[lvl], &tentp[lvl], mgl[0].near_kernel_basis,
675 num_aggs[lvl]);
676
677 /* -- Form smoothed prolongation -- */
678 smooth_agg(&mgl[lvl].A, &tentp[lvl], &mgl[lvl].P, param, &Neighbor[lvl]);
679
680 // Check 2: Is coarse sparse too small?
681 if ( mgl[lvl].P.col < MIN_CDOF ) break;
682
683 // Check 3: Does this coarsening step too aggressive?
684 if ( mgl[lvl].P.row > mgl[lvl].P.col * MAX_CRATE ) {
685 if ( prtlvl > PRINT_MIN ) {
686 printf("### WARNING: Coarsening might be too aggressive!\n");
687 printf("### WARNING: Fine level = %d, coarse level = %d. Discard!\n",
688 mgl[lvl].P.row, mgl[lvl].P.col);
689 }
690 break;
691 }
692
693 // Check 4: Is this coarsening ratio too small?
694 if ( (REAL)mgl[lvl].P.col > mgl[lvl].P.row * MIN_CRATE ) {
695 if ( prtlvl > PRINT_MIN ) {
696 printf("### WARNING: Coarsening rate is too small!\n");
697 printf("### WARNING: Fine level = %d, coarse level = %d. Discard!\n",
698 mgl[lvl].P.row, mgl[lvl].P.col);
699 }
700 break;
701 }
702
703 /*-- Form restriction --*/
704 fasp_dcsr_trans(&mgl[lvl].P, &mgl[lvl].R);
705 fasp_dcsr_trans(&tentp[lvl], &tentr[lvl]);
706
707 /*-- Form coarse level stiffness matrix --*/
708 fasp_blas_dcsr_rap_agg(&tentr[lvl], &mgl[lvl].A, &tentp[lvl], &mgl[lvl+1].A);
709
710 fasp_dcsr_free(&Neighbor[lvl]);
711 fasp_dcsr_free(&tentp[lvl]);
712 fasp_ivec_free(&vertices[lvl]);
713
714 ++lvl;
715 }
716
717 // Setup coarse level systems for direct solvers
718 switch (csolver) {
719
720#if WITH_MUMPS
721 case SOLVER_MUMPS: {
722 // Setup MUMPS direct solver on the coarsest level
723 mgl[lvl].mumps.job = 1;
724 fasp_solver_mumps_steps(&mgl[lvl].A, &mgl[lvl].b, &mgl[lvl].x, &mgl[lvl].mumps);
725 break;
726 }
727#endif
728
729#if WITH_UMFPACK
730 case SOLVER_UMFPACK: {
731 // Need to sort the matrix A for UMFPACK to work
732 dCSRmat Ac_tran;
733 Ac_tran = fasp_dcsr_create(mgl[lvl].A.row, mgl[lvl].A.col, mgl[lvl].A.nnz);
734 fasp_dcsr_transz(&mgl[lvl].A, NULL, &Ac_tran);
735 // It is equivalent to do transpose and then sort
736 // fasp_dcsr_trans(&mgl[lvl].A, &Ac_tran);
737 // fasp_dcsr_sort(&Ac_tran);
738 fasp_dcsr_cp(&Ac_tran, &mgl[lvl].A);
739 fasp_dcsr_free(&Ac_tran);
740 mgl[lvl].Numeric = fasp_umfpack_factorize(&mgl[lvl].A, 0);
741 break;
742 }
743#endif
744
745#if WITH_PARDISO
746 case SOLVER_PARDISO: {
747 fasp_dcsr_sort(&mgl[lvl].A);
748 fasp_pardiso_factorize(&mgl[lvl].A, &mgl[lvl].pdata, prtlvl);
749 break;
750 }
751#endif
752
753 default:
754 // Do nothing!
755 break;
756 }
757
758 // setup total level number and current level
759 mgl[0].num_levels = max_levels = lvl+1;
760 mgl[0].w = fasp_dvec_create(m);
761
762 for ( lvl = 1; lvl < max_levels; ++lvl) {
763 INT mm = mgl[lvl].A.row;
764 mgl[lvl].num_levels = max_levels;
765 mgl[lvl].b = fasp_dvec_create(mm);
766 mgl[lvl].x = fasp_dvec_create(mm);
767
768 mgl[lvl].cycle_type = cycle_type; // initialize cycle type!
769 mgl[lvl].ILU_levels = param->ILU_levels - lvl; // initialize ILU levels!
770 mgl[lvl].SWZ_levels = param->SWZ_levels -lvl; // initialize Schwarz!
771
772 if ( cycle_type == NL_AMLI_CYCLE )
773 mgl[lvl].w = fasp_dvec_create(3*mm);
774 else
775 mgl[lvl].w = fasp_dvec_create(2*mm);
776 }
777
778#if MULTI_COLOR_ORDER
779 INT Colors,rowmax;
780#ifdef _OPENMP
781 int threads = fasp_get_num_threads();
782 if (threads > max_levels-1 ) threads = max_levels-1;
783#pragma omp parallel for private(lvl,rowmax,Colors) schedule(static, 1) num_threads(threads)
784#endif
785 for (lvl=0; lvl<max_levels-1; lvl++){
786
787#if 1
788 dCSRmat_Multicoloring(&mgl[lvl].A, &rowmax, &Colors);
789#else
790 dCSRmat_Multicoloring_Theta(&mgl[lvl].A, mgl[lvl].GS_Theta, &rowmax, &Colors);
791#endif
792 if ( prtlvl > 1 )
793 printf("mgl[%3d].A.row = %12d, rowmax = %5d, rowavg = %7.2lf, colors = %5d, Theta = %le.\n",
794 lvl, mgl[lvl].A.row, rowmax, (double)mgl[lvl].A.nnz/mgl[lvl].A.row,
795 mgl[lvl].A.color, mgl[lvl].GS_Theta);
796 }
797#endif
798
799 if ( prtlvl > PRINT_NONE ) {
800 fasp_gettime(&setup_end);
801 fasp_amgcomplexity(mgl,prtlvl);
802 fasp_cputime("Smoothed aggregation 1/2 setup", setup_end - setup_start);
803 }
804
805 fasp_mem_free(vertices); vertices = NULL;
806 fasp_mem_free(num_aggs); num_aggs = NULL;
807 fasp_mem_free(Neighbor); Neighbor = NULL;
808 fasp_mem_free(tentp); tentp = NULL;
809 fasp_mem_free(tentr); tentr = NULL;
810
811#if DEBUG_MODE > 0
812 printf("### DEBUG: [--End--] %s ...\n", __FUNCTION__);
813#endif
814
815 return status;
816}
817
818/*---------------------------------*/
819/*-- End of File --*/
820/*---------------------------------*/
void fasp_mem_free(void *mem)
Free up previous allocated memory body and set pointer to NULL.
Definition: AuxMemory.c:152
void * fasp_mem_calloc(const unsigned int size, const unsigned int type)
Allocate, initiate, and check memory.
Definition: AuxMemory.c:65
void fasp_cputime(const char *message, const REAL cputime)
Print CPU walltime.
Definition: AuxMessage.c:179
void fasp_amgcomplexity(const AMG_data *mgl, const SHORT prtlvl)
Print level and complexity information of AMG.
Definition: AuxMessage.c:84
void fasp_gettime(REAL *time)
Get system time.
Definition: AuxTiming.c:37
void fasp_dvec_free(dvector *u)
Free vector data space of REAL type.
Definition: AuxVector.c:145
void fasp_ivec_free(ivector *u)
Free vector data space of INT type.
Definition: AuxVector.c:164
dvector fasp_dvec_create(const INT m)
Create dvector data space of REAL type.
Definition: AuxVector.c:62
SHORT fasp_ilu_dcsr_setup(dCSRmat *A, ILU_data *iludata, ILU_param *iluparam)
Get ILU decomposition of a CSR matrix A.
INT fasp_swz_dcsr_setup(SWZ_data *swzdata, SWZ_param *swzparam)
Setup phase for the Schwarz methods.
void fasp_dcsr_diagpref(dCSRmat *A)
Re-order the column and data arrays of a CSR matrix, so that the first entry in each row is the diago...
Definition: BlaSparseCSR.c:680
dCSRmat fasp_dcsr_create(const INT m, const INT n, const INT nnz)
Create CSR sparse matrix data memory space.
Definition: BlaSparseCSR.c:47
void fasp_dcsr_shift(dCSRmat *A, const INT offset)
Re-index a REAL matrix in CSR format to make the index starting from 0 or 1.
void dCSRmat_Multicoloring_Theta(dCSRmat *A, REAL theta, INT *rowmax, INT *groups)
Use the greedy multicoloring algorithm to get color groups for for the adjacency graph of A.
void fasp_dcsr_free(dCSRmat *A)
Free CSR sparse matrix data memory space.
Definition: BlaSparseCSR.c:184
void fasp_dcsr_transz(dCSRmat *A, INT *p, dCSRmat *AT)
Generalized transpose of A: (n x m) matrix given in dCSRmat format.
void fasp_dcsr_sort(dCSRmat *A)
Sort each row of A in ascending order w.r.t. column indices.
Definition: BlaSparseCSR.c:385
void dCSRmat_Multicoloring(dCSRmat *A, INT *rowmax, INT *groups)
Use the greedy multicoloring algorithm to get color groups for for the adjacency graph of A.
void fasp_dcsr_cp(const dCSRmat *A, dCSRmat *B)
copy a dCSRmat to a new one B=A
Definition: BlaSparseCSR.c:851
void fasp_dcsr_getdiag(INT n, const dCSRmat *A, dvector *diag)
Get first n diagonal entries of a CSR matrix A.
Definition: BlaSparseCSR.c:537
dCSRmat fasp_dcsr_sympart(dCSRmat *A)
Get symmetric part of a dCSRmat matrix.
INT fasp_dcsr_trans(const dCSRmat *A, dCSRmat *AT)
Find transpose of dCSRmat matrix A.
Definition: BlaSparseCSR.c:952
void fasp_blas_dcsr_mxm(const dCSRmat *A, const dCSRmat *B, dCSRmat *C)
Sparse matrix multiplication C=A*B.
Definition: BlaSpmvCSR.c:893
void fasp_blas_dcsr_rap_agg(const dCSRmat *R, const dCSRmat *A, const dCSRmat *P, dCSRmat *RAP)
Triple sparse matrix multiplication B=R*A*P (nonzeros of R, P = 1)
Definition: BlaSpmvCSR.c:1276
void fasp_blas_dcsr_rap(const dCSRmat *R, const dCSRmat *A, const dCSRmat *P, dCSRmat *RAP)
Triple sparse matrix multiplication B=R*A*P.
Definition: BlaSpmvCSR.c:999
SHORT fasp_amg_setup_sa(AMG_data *mgl, AMG_param *param)
Set up phase of smoothed aggregation AMG.
Definition: PreAMGSetupSA.c:63
void fasp_amg_amli_coef(const REAL lambda_max, const REAL lambda_min, const INT degree, REAL *coef)
Compute the coefficients of the polynomial used by AMLI-cycle.
int fasp_solver_mumps_steps(dCSRmat *ptrA, dvector *b, dvector *u, Mumps_data *mumps)
Solve Ax=b by MUMPS in three steps.
Definition: XtrMumps.c:196
Main header file for the FASP project.
#define MIN(a, b)
Definition: fasp.h:83
#define REAL
Definition: fasp.h:75
#define SHORT
FASP integer and floating point numbers.
Definition: fasp.h:71
#define ABS(a)
Definition: fasp.h:84
#define MAX(a, b)
Definition of max, min, abs.
Definition: fasp.h:82
#define INT
Definition: fasp.h:72
#define AMLI_CYCLE
Definition: fasp_const.h:181
#define SOLVER_PARDISO
Definition: fasp_const.h:126
#define NL_AMLI_CYCLE
Definition: fasp_const.h:182
#define FASP_SUCCESS
Definition of return status and error messages.
Definition: fasp_const.h:19
#define MAX_CRATE
Definition: fasp_const.h:262
#define SOLVER_MUMPS
Definition: fasp_const.h:125
#define PAIRWISE
Definition of aggregation types.
Definition: fasp_const.h:170
#define SOLVER_UMFPACK
Definition: fasp_const.h:124
#define MIN_CRATE
Definition: fasp_const.h:261
#define ON
Definition of switch.
Definition: fasp_const.h:67
#define PRINT_NONE
Print level for all subroutines – not including DEBUG output.
Definition: fasp_const.h:73
#define MIN_CDOF
Definition: fasp_const.h:260
#define PRINT_MIN
Definition: fasp_const.h:74
Data for AMG methods.
Definition: fasp.h:804
INT near_kernel_dim
dimension of the near kernel for SAMG
Definition: fasp.h:849
dCSRmat A
pointer to the matrix at level level_num
Definition: fasp.h:817
INT cycle_type
cycle type
Definition: fasp.h:869
Mumps_data mumps
data for MUMPS
Definition: fasp.h:866
SWZ_data Schwarz
data of Schwarz smoother
Definition: fasp.h:860
dvector b
pointer to the right-hand side at level level_num
Definition: fasp.h:826
REAL ** near_kernel_basis
basis of near kernel space for SAMG
Definition: fasp.h:852
void * Numeric
pointer to the numerical factorization from UMFPACK
Definition: fasp.h:834
INT ILU_levels
number of levels use ILU smoother
Definition: fasp.h:843
INT SWZ_levels
number of levels use Schwarz smoother
Definition: fasp.h:857
dvector x
pointer to the iterative solution at level level_num
Definition: fasp.h:829
SHORT num_levels
number of levels in use <= max_levels
Definition: fasp.h:812
dvector w
temporary work space
Definition: fasp.h:863
Parameters for AMG methods.
Definition: fasp.h:455
INT ILU_lfil
level of fill-in for ILUs and ILUk
Definition: fasp.h:566
REAL ILU_relax
relaxation for ILUs
Definition: fasp.h:572
INT SWZ_mmsize
maximal block size
Definition: fasp.h:581
SHORT print_level
print level for AMG
Definition: fasp.h:461
INT SWZ_maxlvl
maximal levels
Definition: fasp.h:584
SHORT aggregation_type
aggregation type
Definition: fasp.h:518
SHORT smooth_filter
switch for filtered matrix used for smoothing the tentative prolongation
Definition: fasp.h:554
REAL * amli_coef
coefficients of the polynomial used by AMLI cycle
Definition: fasp.h:509
SHORT ILU_levels
number of levels use ILU smoother
Definition: fasp.h:560
SHORT coarse_solver
coarse solver type
Definition: fasp.h:500
SHORT cycle_type
type of AMG cycle
Definition: fasp.h:476
SHORT amli_degree
degree of the polynomial used by AMLI cycle
Definition: fasp.h:506
SHORT ILU_type
ILU type for smoothing.
Definition: fasp.h:563
INT SWZ_blksolver
type of Schwarz block solver
Definition: fasp.h:590
INT SWZ_type
type of Schwarz method
Definition: fasp.h:587
INT coarse_dof
max number of coarsest level DOF
Definition: fasp.h:473
REAL ILU_droptol
drop tolerance for ILUt
Definition: fasp.h:569
REAL tentative_smooth
relaxation parameter for smoothing the tentative prolongation
Definition: fasp.h:551
INT SWZ_levels
number of levels use Schwarz smoother
Definition: fasp.h:578
INT pair_number
number of pairwise matchings
Definition: fasp.h:542
SHORT max_levels
max number of levels of AMG
Definition: fasp.h:470
SHORT smooth_restriction
smooth the restriction for SA methods or not
Definition: fasp.h:557
Parameters for ILU.
Definition: fasp.h:404
INT ILU_lfil
level of fill-in for ILUk
Definition: fasp.h:413
REAL ILU_relax
add the sum of dropped elements to diagonal element in proportion relax
Definition: fasp.h:419
SHORT print_level
print level
Definition: fasp.h:407
SHORT ILU_type
ILU type for decomposition.
Definition: fasp.h:410
REAL ILU_droptol
drop tolerance for ILUt
Definition: fasp.h:416
INT job
work for MUMPS
Definition: fasp.h:615
dCSRmat A
pointer to the original coefficient matrix
Definition: fasp.h:731
Parameters for Schwarz method.
Definition: fasp.h:430
INT SWZ_mmsize
maximal size of blocks
Definition: fasp.h:442
INT SWZ_maxlvl
maximal level for constructing the blocks
Definition: fasp.h:439
INT SWZ_blksolver
type of Schwarz block solver
Definition: fasp.h:445
SHORT SWZ_type
type for Schwarz method
Definition: fasp.h:436
Sparse matrix of REAL type in CSR format.
Definition: fasp.h:151
INT col
column of matrix A, n
Definition: fasp.h:157
REAL * val
nonzero entries of A
Definition: fasp.h:169
INT row
row number of matrix A, m
Definition: fasp.h:154
INT * IA
integer array of row pointers, the size is m+1
Definition: fasp.h:163
INT nnz
number of nonzero entries
Definition: fasp.h:160
INT * JA
integer array of column indexes, the size is nnz
Definition: fasp.h:166
Vector with n entries of REAL type.
Definition: fasp.h:354
REAL * val
actual vector entries
Definition: fasp.h:360
Vector with n entries of INT type.
Definition: fasp.h:368