25#include "fasp_functs.h"
31#include "PreAMGUtil.inl"
88 printf(
"### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
92 printf(
"### DEBUG: Step 1. Find strong connections ......\n");
99 strong_couplings(A, S, param);
102 printf(
"### DEBUG: Step 2. C/F splitting ......\n");
106 switch (coarse_type) {
109 col = cfsplitting_clsp(A, S, vertices);
113 col = cfsplitting_agg(A, S, vertices, agg_path);
124 ordering1(S, &order);
125 col = cfsplitting_mis(S, vertices, &order);
131 col = cfsplitting_cls(A, S, vertices);
135 printf(
"### DEBUG: col = %d\n", col);
141 printf(
"### DEBUG: Step 3. Find support of C points ......\n");
144 switch (interp_type) {
148 col = clean_ff_couplings(S, vertices, row, col);
149 form_P_pattern_dir(P, S, vertices, row, col);
154 form_P_pattern_std(P, S, vertices, row, col);
162 form_P_pattern_rdc(P, A, theta, vertices, row, col);
168 for (i = 0; i < row; ++i)
169 if (theta[i] < param->
theta) param->
theta = theta[i];
170 printf(
"### DEBUG: theta = %e\n", param->
theta);
173 double eps = (2 - 2 * param->
theta) / (2 * param->
theta - 1);
176 double conv_factor = (eps / (1 + eps)) *
177 (1 + pow(eps, 2 * nu - 1) / pow(2 + eps, 2 * nu));
178 conv_factor = sqrt(conv_factor);
179 printf(
"### DEBUG: Upper bound for conv_factor = %e\n", conv_factor);
180 if (param->
theta <= 0.5) {
181 REAL reset_value = 0.5 + 1e-5;
182 printf(
"### WARNING: theta = %e <= 0.5, use %e instead \n",
183 param->
theta, reset_value);
184 param->
theta = reset_value;
186 if (param->
theta >= 0.0) {
189 REAL eps = (2 - 2 * theta) / (2 * theta - 1);
190 REAL sigma = 2 / (2 + eps);
191 REAL weight = sigma / (2 - 1 / theta);
192 printf(
"### DEBUG: theta = %e, eps = %e, sigma = %e\n", theta, eps,
198 printf(
"### DEBUG: Weight for JACOBI_F = %e\n", weight);
209 printf(
"### DEBUG: [--End--] %s ...\n", __FUNCTION__);
241 const INT row = A->
row, col = A->
col, row1 = row + 1;
248 INT i, j, begin_row, end_row;
249 REAL row_scl, row_sum;
256 nthreads = fasp_get_num_threads();
278 INT mybegin, myend, myid;
280#pragma omp parallel for private(myid, mybegin, myend, i, row_scl, row_sum, begin_row, \
283 for (myid = 0; myid < nthreads; myid++) {
285 for (i = mybegin; i < myend; i++) {
288 row_scl = row_sum = 0.0;
291 for (j = begin_row; j < end_row; j++) {
292 row_scl =
MIN(row_scl, aj[j]);
297 for (j = begin_row; j < end_row; j++) {
305 if (
ABS(row_sum) > max_row_sum *
ABS(diag.
val[i])) {
306 for (j = begin_row; j < end_row; j++) S->
JA[j] = -1;
308 for (j = begin_row; j < end_row; j++) {
312 if (A->
val[j] >= epsilon_str * row_scl) S->
JA[j] = -1;
323 for (i = 0; i < row; ++i) {
326 row_scl = row_sum = 0.0;
330 for (j = begin_row; j < end_row; j++) {
335 row_sum +=
ABS(aj[j]);
340 if (ja[j] != i) row_scl =
MAX(row_scl,
ABS(aj[j]));
344 row_scl *= epsilon_str;
347 for (j = begin_row; j < end_row; j++) {
360 if (row_sum < (2 - max_row_sum) *
ABS(diag.
val[i])) {
362 for (j = begin_row; j < end_row; j++) S->
JA[j] = -1;
366 switch (coarse_type) {
369 for (j = begin_row; j < end_row; j++) {
370 if (
ABS(A->
val[j]) <= row_scl) S->
JA[j] = -1;
375 for (j = begin_row; j < end_row; j++) {
376 if (-A->
val[j] <= row_scl) S->
JA[j] = -1;
409 INT index, i, j, begin_row, end_row;
412 for (index = i = 0; i < row; ++i) {
418 for (j = begin_row; j < end_row; j++) {
419 if (S->
JA[j] > -1) S->
JA[index++] = S->
JA[j];
423 S->
nnz = S->
IA[row] = index;
447 INT * ia = A->
IA, *vec = vertices->
val;
449 REAL row_scl, max_entry;
450 INT i, j, ji, max_index;
452 for (i = 0; i < row; ++i) {
454 if (vec[i] !=
FGPT)
continue;
457 for (ji = ia[i]; ji < ia[i + 1]; ++ji) {
459 if (j == i)
continue;
467 for (ji = ia[i]; ji < ia[i + 1]; ++ji) {
469 if (j == i)
continue;
470 if (vec[j] !=
FGPT)
continue;
471 if (A->
val[ji] > row_scl) {
473 if (A->
val[ji] > max_entry) {
474 max_entry = A->
val[ji];
481 if (max_index != -1) vec[max_index] =
CGPT;
513 INT maxmeas, maxnode, num_left = 0;
514 INT measure, newmeas;
516 INT myid, mybegin, myend;
519 INT *lists = work, *where = lists + row, *lambda = where + row;
523 INT jkeep = 0, cnt, index;
524 INT row_end_S, ji, row_end_S_nabor, jj;
525 INT* graph_array = lambda;
530 LinkList LoL_head = NULL, LoL_tail = NULL, list_ptr = NULL;
535 printf(
"### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
541 nthreads = fasp_get_num_threads();
549 if (col < 0)
goto FINISHED;
557#pragma omp parallel for private(myid, mybegin, myend, i)
559 for (myid = 0; myid < nthreads; myid++) {
561 for (i = mybegin; i < myend; i++) lambda[i] = ST.
IA[i + 1] - ST.
IA[i];
564 for (i = 0; i < row; ++i) lambda[i] = ST.
IA[i + 1] - ST.
IA[i];
572#pragma omp parallel for reduction(+ : num_left) private(myid, mybegin, myend, i)
574 for (myid = 0; myid < nthreads; myid++) {
576 for (i = mybegin; i < myend; i++) {
578 if (S->
IA[i + 1] == S->
IA[i])
580 if ((ia[i + 1] - ia[i]) <= 1)
596 for (i = 0; i < row; ++i) {
599 if (S->
IA[i + 1] == S->
IA[i])
601 if ((ia[i + 1] - ia[i]) <= 1)
614 for (i = 0; i < row; ++i) {
616 if (vec[i] ==
ISPT)
continue;
621 enter_list(&LoL_head, &LoL_tail, lambda[i], i, lists, where);
624 if (measure < 0) printf(
"### WARNING: Negative lambda[%d]!\n", i);
631 for (k = S->
IA[i]; k < S->IA[i + 1]; ++k) {
633 if (vec[j] ==
ISPT)
continue;
637 remove_node(&LoL_head, &LoL_tail, newmeas, j, lists, where);
639 newmeas = ++(lambda[j]);
640 enter_list(&LoL_head, &LoL_tail, newmeas, j, lists, where);
642 newmeas = ++(lambda[j]);
651 while (num_left > 0) {
654 maxnode = LoL_head->head;
655 maxmeas = lambda[maxnode];
656 if (maxmeas == 0) printf(
"### WARNING: Head of the list has measure 0!\n");
661 remove_node(&LoL_head, &LoL_tail, maxmeas, maxnode, lists, where);
665 for (i = ST.
IA[maxnode]; i < ST.
IA[maxnode + 1]; ++i) {
669 if (vec[j] !=
UNPT)
continue;
672 remove_node(&LoL_head, &LoL_tail, lambda[j], j, lists, where);
676 for (l = S->
IA[j]; l < S->IA[j + 1]; l++) {
678 if (vec[k] ==
UNPT) {
679 remove_node(&LoL_head, &LoL_tail, lambda[k], k, lists, where);
680 newmeas = ++(lambda[k]);
681 enter_list(&LoL_head, &LoL_tail, newmeas, k, lists, where);
688 for (i = S->
IA[maxnode]; i < S->IA[maxnode + 1]; ++i) {
692 if (vec[j] !=
UNPT)
continue;
695 remove_node(&LoL_head, &LoL_tail, measure, j, lists, where);
696 lambda[j] = --measure;
699 enter_list(&LoL_head, &LoL_tail, measure, j, lists, where);
705 for (l = S->
IA[j]; l < S->IA[j + 1]; l++) {
707 if (vec[k] ==
UNPT) {
708 remove_node(&LoL_head, &LoL_tail, lambda[k], k, lists, where);
709 newmeas = ++(lambda[k]);
710 enter_list(&LoL_head, &LoL_tail, newmeas, k, lists, where);
723 for (i = 0; i < row; i++) {
724 if (vec[i] ==
FGPT) {
725 row_end_S = S->
IA[i + 1];
726 for (ji = S->
IA[i]; ji < row_end_S; ji++) {
728 if (vec[j] ==
CGPT) {
733 for (ji = S->
IA[i]; ji < row_end_S; ji++) {
735 if (vec[j] ==
FGPT) {
737 row_end_S_nabor = S->
IA[j + 1];
738 for (jj = S->
IA[j]; jj < row_end_S_nabor; jj++) {
740 if (graph_array[index] == i) {
769 LoL_head->prev_node = NULL;
770 LoL_head->next_node = NULL;
771 LoL_head = list_ptr->next_node;
781 printf(
"### DEBUG: [--End--] %s ...\n", __FUNCTION__);
812 INT maxmeas, maxnode, num_left = 0;
813 INT measure, newmeas;
815 INT myid, mybegin, myend;
817 INT *ia = A->
IA, *vec = vertices->
val;
819 INT *lists = work, *where = lists + row, *lambda = where + row;
821 LinkList LoL_head = NULL, LoL_tail = NULL, list_ptr = NULL;
826 printf(
"### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
832 nthreads = fasp_get_num_threads();
846 if (compress_S(S) < 0)
goto FINISHED;
854#pragma omp parallel for private(myid, mybegin, myend, i)
856 for (myid = 0; myid < nthreads; myid++) {
858 for (i = mybegin; i < myend; i++) lambda[i] = ST.
IA[i + 1] - ST.
IA[i];
861 for (i = 0; i < row; ++i) lambda[i] = ST.
IA[i + 1] - ST.
IA[i];
869#pragma omp parallel for reduction(+ : num_left) private(myid, mybegin, myend, i)
871 for (myid = 0; myid < nthreads; myid++) {
873 for (i = mybegin; i < myend; i++) {
874 if ((ia[i + 1] - ia[i]) <= 1) {
886 for (i = 0; i < row; ++i) {
887 if ((ia[i + 1] - ia[i]) <= 1) {
898 for (i = 0; i < row; ++i) {
900 if (vec[i] ==
ISPT)
continue;
905 enter_list(&LoL_head, &LoL_tail, lambda[i], i, lists, where);
908 if (measure < 0) printf(
"### WARNING: Negative lambda[%d]!\n", i);
915 for (k = S->
IA[i]; k < S->IA[i + 1]; ++k) {
918 if (vec[j] ==
ISPT)
continue;
923 remove_node(&LoL_head, &LoL_tail, newmeas, j, lists, where);
925 newmeas = ++(lambda[j]);
926 enter_list(&LoL_head, &LoL_tail, newmeas, j, lists, where);
928 newmeas = ++(lambda[j]);
938 while (num_left > 0) {
941 maxnode = LoL_head->head;
942 maxmeas = lambda[maxnode];
943 if (maxmeas == 0) printf(
"### WARNING: Head of the list has measure 0!\n");
948 remove_node(&LoL_head, &LoL_tail, maxmeas, maxnode, lists, where);
952 for (i = ST.
IA[maxnode]; i < ST.
IA[maxnode + 1]; ++i) {
956 if (vec[j] !=
UNPT)
continue;
959 remove_node(&LoL_head, &LoL_tail, lambda[j], j, lists, where);
963 for (l = S->
IA[j]; l < S->IA[j + 1]; l++) {
965 if (vec[k] ==
UNPT) {
966 remove_node(&LoL_head, &LoL_tail, lambda[k], k, lists, where);
967 newmeas = ++(lambda[k]);
968 enter_list(&LoL_head, &LoL_tail, newmeas, k, lists, where);
975 for (i = S->
IA[maxnode]; i < S->IA[maxnode + 1]; ++i) {
979 if (vec[j] !=
UNPT)
continue;
982 remove_node(&LoL_head, &LoL_tail, measure, j, lists, where);
983 lambda[j] = --measure;
986 enter_list(&LoL_head, &LoL_tail, measure, j, lists, where);
992 for (l = S->
IA[j]; l < S->IA[j + 1]; l++) {
994 if (vec[k] ==
UNPT) {
995 remove_node(&LoL_head, &LoL_tail, lambda[k], k, lists, where);
996 newmeas = ++(lambda[k]);
997 enter_list(&LoL_head, &LoL_tail, newmeas, k, lists, where);
1009 list_ptr = LoL_head;
1010 LoL_head->prev_node = NULL;
1011 LoL_head->next_node = NULL;
1012 LoL_head = list_ptr->next_node;
1021 rem_positive_ff(A, &Stemp, vertices);
1023 if (compress_S(&Stemp) < 0)
goto FINISHED;
1039 printf(
"### DEBUG: [--End--] %s ...\n", __FUNCTION__);
1065static void strong_couplings_agg1(
dCSRmat* A,
1076 INT num_c, count, ci, cj, ck, fj, cck;
1077 INT *cp_index, *cp_rindex, *visited;
1078 INT* vec = vertices->
val;
1081 for (num_c = i = 0; i < row; i++) {
1082 if (vec[i] ==
CGPT) num_c++;
1087 cp_rindex = CGPT_rindex->
val;
1091 cp_index = CGPT_index->
val;
1092 for (j = i = 0; i < row; i++) {
1093 if (vec[i] ==
CGPT) {
1101 Sh->
row = Sh->
col = num_c;
1102 Sh->
val = Sh->
JA = NULL;
1115 for (ci = 0; ci < Sh->
row; ci++) {
1123 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1127 if (vec[fj] ==
CGPT && fj != i) {
1129 if (visited[cj] != ci) {
1136 else if (vec[fj] ==
FGPT) {
1139 for (k = S->
IA[fj]; k < S->IA[fj + 1]; k++) {
1141 if (vec[ck] ==
CGPT && ck != i) {
1142 if (cp_rindex[ck] >= num_c) {
1143 printf(
"### ERROR: ck=%d, num_c=%d, out of bound!\n", ck,
1147 cck = cp_rindex[ck];
1149 if (visited[cck] != ci) {
1160 Sh->
IA[ci + 1] = Sh->
IA[ci] + count;
1173 for (ci = 0; ci < Sh->
row; ci++) {
1179 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1183 if (vec[fj] ==
CGPT && fj != i) {
1185 if (visited[cj] != ci) {
1190 }
else if (vec[fj] ==
FGPT) {
1192 for (k = S->
IA[fj]; k < S->IA[fj + 1]; k++) {
1194 if (vec[ck] ==
CGPT && ck != i) {
1195 cck = cp_rindex[ck];
1196 if (visited[cck] != ci) {
1198 Sh->
JA[count] = cck;
1207 if (count != Sh->
IA[ci + 1]) {
1208 printf(
"### WARNING: Inconsistent numbers of nonzeros!\n ");
1243static void strong_couplings_agg2(
dCSRmat* A,
1254 INT num_c, count, ci, cj, ck, fj, cck;
1255 INT *cp_index, *cp_rindex, *visited;
1256 INT* vec = vertices->
val;
1259 for (num_c = i = 0; i < row; i++) {
1260 if (vec[i] ==
CGPT) num_c++;
1265 cp_rindex = CGPT_rindex->
val;
1269 cp_index = CGPT_index->
val;
1270 for (j = i = 0; i < row; i++) {
1271 if (vec[i] ==
CGPT) {
1279 Sh->
row = Sh->
col = num_c;
1280 Sh->
val = Sh->
JA = NULL;
1285 memset(visited, 0,
sizeof(
INT) * num_c);
1293 for (ci = 0; ci < Sh->
row; ci++) {
1301 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1305 if (vec[fj] ==
CGPT && fj != i) {
1307 if (visited[cj] != ci + 1) {
1308 visited[cj] = ci + 1;
1313 else if (vec[fj] ==
FGPT) {
1316 for (k = S->
IA[fj]; k < S->IA[fj + 1]; k++) {
1320 if (vec[ck] ==
CGPT && ck != i) {
1321 if (cp_rindex[ck] >= num_c) {
1322 printf(
"### ERROR: ck=%d, num_c=%d, out of bound!\n", ck,
1326 cck = cp_rindex[ck];
1328 if (visited[cck] == ci + 1) {
1330 }
else if (visited[cck] == -ci - 1) {
1331 visited[cck] = ci + 1;
1334 visited[cck] = -ci - 1;
1345 Sh->
IA[ci + 1] = Sh->
IA[ci] + count;
1353 memset(visited, 0,
sizeof(
INT) * num_c);
1358 for (ci = 0; ci < Sh->
row; ci++) {
1364 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1368 if (vec[fj] ==
CGPT && fj != i) {
1370 if (visited[cj] != ci + 1) {
1371 visited[cj] = ci + 1;
1377 else if (vec[fj] ==
FGPT) {
1380 for (k = S->
IA[fj]; k < S->IA[fj + 1]; k++) {
1384 if (vec[ck] ==
CGPT && ck != i) {
1385 cck = cp_rindex[ck];
1386 if (visited[cck] == ci + 1) {
1388 }
else if (visited[cck] == -ci - 1) {
1389 visited[cck] = ci + 1;
1390 Sh->
JA[count] = cck;
1393 visited[cck] = -ci - 1;
1403 if (count != Sh->
IA[ci + 1]) {
1404 printf(
"### WARNING: Inconsistent numbers of nonzeros!\n ");
1441 INT * vec = vertices->
val, *cp_index;
1442 INT maxmeas, maxnode, num_left = 0;
1443 INT measure, newmeas;
1444 INT i, j, k, l, m, ci, cj, ck, cl, num_c;
1448 INT *lists = work, *where = lists + row, *lambda = where + row;
1450 ivector CGPT_index, CGPT_rindex;
1451 LinkList LoL_head = NULL, LoL_tail = NULL, list_ptr = NULL;
1459 printf(
"### DEBUG: [-Begin-] %s ...\n", __FUNCTION__);
1466 num_c = cfsplitting_cls(A, S, vertices);
1474 if (aggressive_path < 2)
1475 strong_couplings_agg1(A, S, &Sh, vertices, &CGPT_index, &CGPT_rindex);
1477 strong_couplings_agg2(A, S, &Sh, vertices, &CGPT_index, &CGPT_rindex);
1481 CGPT_index.
row = num_c;
1482 CGPT_rindex.
row = row;
1483 cp_index = CGPT_index.
val;
1487#pragma omp parallel for if (num_c > OPENMP_HOLDS)
1489 for (ci = 0; ci < num_c; ++ci) lambda[ci] = ShT.
IA[ci + 1] - ShT.
IA[ci];
1492 for (ci = 0; ci < num_c; ++ci) {
1495 measure = lambda[ci];
1497 if (vec[i] ==
ISPT)
continue;
1500 enter_list(&LoL_head, &LoL_tail, lambda[ci], ci, lists, where);
1503 if (measure < 0) printf(
"### WARNING: Negative lambda[%d]!\n", i);
1508 for (ck = Sh.
IA[ci]; ck < Sh.
IA[ci + 1]; ++ck) {
1513 if (vec[j] ==
ISPT)
continue;
1516 newmeas = lambda[cj];
1518 remove_node(&LoL_head, &LoL_tail, newmeas, cj, lists, where);
1521 newmeas = ++(lambda[cj]);
1522 enter_list(&LoL_head, &LoL_tail, newmeas, cj, lists, where);
1525 newmeas = ++(lambda[cj]);
1535 while (num_left > 0) {
1538 maxnode = LoL_head->head;
1539 maxmeas = lambda[maxnode];
1540 if (maxmeas == 0) printf(
"### WARNING: Head of the list has measure 0!\n");
1543 vec[cp_index[maxnode]] = 3;
1545 remove_node(&LoL_head, &LoL_tail, maxmeas, maxnode, lists, where);
1546 lambda[maxnode] = 0;
1550 for (ci = ShT.
IA[maxnode]; ci < ShT.
IA[maxnode + 1]; ++ci) {
1555 if (vec[j] !=
CGPT)
continue;
1558 remove_node(&LoL_head, &LoL_tail, lambda[cj], cj, lists, where);
1562 for (cl = Sh.
IA[cj]; cl < Sh.
IA[cj + 1]; cl++) {
1565 if (vec[k] ==
CGPT) {
1566 remove_node(&LoL_head, &LoL_tail, lambda[ck], ck, lists, where);
1567 newmeas = ++(lambda[ck]);
1568 enter_list(&LoL_head, &LoL_tail, newmeas, ck, lists, where);
1575 for (ci = Sh.
IA[maxnode]; ci < Sh.
IA[maxnode + 1]; ++ci) {
1580 if (vec[j] !=
CGPT)
continue;
1582 measure = lambda[cj];
1583 remove_node(&LoL_head, &LoL_tail, measure, cj, lists, where);
1584 lambda[cj] = --measure;
1587 enter_list(&LoL_head, &LoL_tail, measure, cj, lists, where);
1591 for (cl = Sh.
IA[cj]; cl < Sh.
IA[cj + 1]; cl++) {
1594 if (vec[k] ==
CGPT) {
1595 remove_node(&LoL_head, &LoL_tail, lambda[ck], ck, lists, where);
1596 newmeas = ++(lambda[ck]);
1597 enter_list(&LoL_head, &LoL_tail, newmeas, ck, lists, where);
1609#pragma omp parallel for if (row > OPENMP_HOLDS)
1611 for (i = 0; i < row; i++) {
1612 if (vec[i] ==
CGPT || vec[i] == 4) vec[i] =
FGPT;
1616#pragma omp parallel for if (row > OPENMP_HOLDS)
1618 for (i = 0; i < row; i++) {
1619 if (vec[i] == 3) vec[i] =
CGPT;
1628 for (i = 0; i < row; i++) {
1630 if (vec[i] !=
FGPT)
continue;
1634 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1636 if (IS_CNEIGH)
break;
1640 if (vec[k] ==
CGPT) {
1642 }
else if (vec[k] ==
FGPT) {
1643 for (l = S->
IA[k]; l < S->IA[k + 1]; l++) {
1645 if (vec[m] ==
CGPT) {
1663 list_ptr = LoL_head;
1664 LoL_head->prev_node = NULL;
1665 LoL_head->next_node = NULL;
1666 LoL_head = list_ptr->next_node;
1680 printf(
"### DEBUG: [--End--] %s ...\n", __FUNCTION__);
1712 INT* vec = vertices->
val;
1715 INT ci_tilde = -1, ci_tilde_mark = -1;
1716 INT ji, jj, i, j, index;
1720 for (i = 0; i < row; ++i) {
1722 if (vec[i] !=
FGPT)
continue;
1724 for (ji = S->
IA[i]; ji < S->IA[i + 1]; ++ji) {
1732 if (ci_tilde_mark != i) ci_tilde = -1;
1734 for (ji = S->
IA[i]; ji < S->IA[i + 1]; ++ji) {
1738 if (vec[j] !=
FGPT)
continue;
1742 for (jj = S->
IA[j]; jj < S->IA[j + 1]; ++jj) {
1744 if (cindex[index] == i) {
1755 if (ci_tilde > -1) {
1756 vec[ci_tilde] =
FGPT;
1760 C_i_nonempty =
FALSE;
1767 C_i_nonempty =
TRUE;
1783REAL rabs(
REAL x) {
return (x > 0) ? x : -x; }
1796static void form_P_pattern_rdc(
1800 INT* vec = vertices->
val;
1801 INT i, j, k, index = 0;
1811 for (i = 0; i < row; ++i) {
1812 if (vec[i] ==
CGPT) {
1813 P->
IA[i + 1] = P->
IA[i] + 1;
1814 theta[i] = 1000000.0;
1816 P->
IA[i + 1] = P->
IA[i];
1819 for (k = A->
IA[i]; k < A->IA[i + 1]; ++k) {
1824 sum += rabs(A->
val[k]);
1826 if (j == i) diagptr = k;
1829 theta[i] = rabs(A->
val[diagptr]) / sum;
1831 printf(
"### ERROR: Diagonal element is zero! [%s:%d]\n", __FUNCTION__,
1833 theta[i] = 1000000.0;
1835 if (theta[i] < 0.5) {
1836 printf(
"WARNING: theta[%d] = %f < 0.5! not diagonal dominant!\n", i,
1842 double sum_row = 0.0;
1843 for (ii = A->
IA[i]; ii < A->IA[i + 1]; ++ii) {
1845 sum_row += A->
val[ii];
1848 printf(
"(no abs op)sum_row = %f\n", sum_row);
1855 P->
nnz = P->
IA[row];
1857 for (i = 0; i < row; ++i) {
1858 if (vec[i] ==
CGPT) {
1862 for (k = A->
IA[i]; k < A->IA[i + 1]; ++k) {
1864 if (vec[j] ==
CGPT) P->
JA[index++] = j;
1896 INT* vec = vertices->
val;
1903 nthreads = fasp_get_num_threads();
1915 INT mybegin, myend, myid;
1917#pragma omp parallel for private(myid, mybegin, myend, i, j, k)
1919 for (myid = 0; myid < nthreads; myid++) {
1921 for (i = mybegin; i < myend; ++i) {
1924 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1926 if (vec[k] ==
CGPT) P->
IA[i + 1]++;
1945 for (i = 0; i < row; ++i) {
1948 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1950 if (vec[k] ==
CGPT) P->
IA[i + 1]++;
1967 for (i = 0; i < P->
row; ++i) P->
IA[i + 1] += P->
IA[i];
1974 for (index = i = 0; i < row; ++i) {
1975 if (vec[i] ==
FGPT) {
1976 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
1978 if (vec[k] ==
CGPT) P->
JA[index++] = k;
1981 else if (vec[i] ==
CGPT) {
2009 INT i, j, k, l, h, index;
2010 INT* vec = vertices->
val;
2022 for (i = 0; i < row; ++i) {
2024 if (vec[i] ==
FGPT) {
2025 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
2030 if ((vec[k] ==
CGPT) && (visited[k] != i)) {
2036 else if ((vec[k] ==
FGPT) && (k != i)) {
2037 for (l = S->
IA[k]; l < S->IA[k + 1]; l++) {
2039 if ((vec[h] ==
CGPT) && (visited[h] != i)) {
2049 else if (vec[i] ==
CGPT) {
2060 for (i = 0; i < P->
row; ++i) P->
IA[i + 1] += P->
IA[i];
2069 for (i = 0; i < row; ++i) {
2071 if (vec[i] ==
FGPT) {
2075 for (j = S->
IA[i]; j < S->IA[i + 1]; j++) {
2080 if ((vec[k] ==
CGPT) && (visited[k] != i)) {
2082 P->
JA[P->
IA[i] + index] = k;
2087 else if ((vec[k] ==
FGPT) && (k != i)) {
2088 for (l = S->
IA[k]; l < S->IA[k + 1]; l++) {
2090 if ((vec[h] ==
CGPT) && (visited[h] != i)) {
2092 P->
JA[P->
IA[i] + index] = h;
2103 else if (vec[i] ==
CGPT) {
2104 P->
JA[P->
IA[i]] = i;
2133 INT* vec = vertices->
val;
2138 INT row_begin, row_end;
2142 for (i = 0; i < n; i++) {
2144 if (vec[ind] ==
UNPT) {
2146 row_begin = IS[ind];
2147 row_end = IS[ind + 1];
2148 for (j = row_begin; j < row_end; j++) {
2149 if (vec[JS[j]] ==
CGPT) {
2154 if (vec[ind] ==
CGPT) {
2156 for (j = row_begin; j < row_end; j++) {
2181 const INT n = order->
row;
2184 INT maxind, maxdeg, degree;
2187 for (i = 0; i < n; i++) ord[i] = i;
2189 for (maxind = maxdeg = i = 0; i < n; i++) {
2190 degree = IS[i + 1] - IS[i];
2191 if (degree > maxdeg) {
void fasp_iarray_set(const INT n, INT *x, const INT val)
Set initial value for an array to be x=val.
void fasp_iarray_cp(const INT n, const INT *x, INT *y)
Copy an array to the other y=x.
void fasp_mem_free(void *mem)
Free up previous allocated memory body and set pointer to NULL.
void * fasp_mem_calloc(const unsigned int size, const unsigned int type)
Allocate, initiate, and check memory.
void fasp_chkerr(const SHORT status, const char *fctname)
Check error status and print out error messages before quit.
void fasp_get_start_end(const INT procid, const INT nprocs, const INT n, INT *start, INT *end)
Assign Load to each thread.
void fasp_dvec_free(dvector *u)
Free vector data space of REAL type.
void fasp_ivec_free(ivector *u)
Free vector data space of INT type.
void fasp_ivec_alloc(const INT m, ivector *u)
Create vector data space of INT type.
ivector fasp_ivec_create(const INT m)
Create vector data space of INT type.
void fasp_ivec_set(INT n, ivector *u, const INT m)
Set ivector value to be m.
void fasp_icsr_trans(const iCSRmat *A, iCSRmat *AT)
Find transpose of iCSRmat matrix A.
void fasp_icsr_free(iCSRmat *A)
Free CSR sparse matrix data memory space.
void fasp_dcsr_getdiag(INT n, const dCSRmat *A, dvector *diag)
Get first n diagonal entries of a CSR matrix A.
INT fasp_amg_coarsening_cr(const INT i_0, const INT i_n, dCSRmat *A, ivector *vertices, AMG_param *param)
CR coarsening.
SHORT fasp_amg_coarsening_rs(dCSRmat *A, ivector *vertices, dCSRmat *P, iCSRmat *S, AMG_param *param)
Standard and aggressive coarsening schemes.
Main header file for the FASP project.
#define SHORT
FASP integer and floating point numbers.
#define MAX(a, b)
Definition of max, min, abs.
#define ERROR_AMG_INTERP_TYPE
#define FASP_SUCCESS
Definition of return status and error messages.
#define INTERP_DIR
Definition of interpolation types.
#define TRUE
Definition of logic type.
#define ERROR_AMG_COARSEING
#define SMOOTHER_JACOBIF
Definition of standard smoother types.
Parameters for AMG methods.
REAL strong_threshold
strong connection threshold for coarsening
INT aggressive_path
number of paths use to determine strongly coupled C points
SHORT interpolation_type
interpolation type
SHORT coarsening_type
coarsening type
REAL theta
theta for reduction-based amg
REAL relaxation
relaxation parameter for Jacobi and SOR smoother
SHORT smoother
smoother type
SHORT postsmooth_iter
number of postsmoothers
SHORT presmooth_iter
number of presmoothers
REAL max_row_sum
maximal row sum parameter
Sparse matrix of REAL type in CSR format.
INT col
column of matrix A, n
REAL * val
nonzero entries of A
INT row
row number of matrix A, m
INT * IA
integer array of row pointers, the size is m+1
INT nnz
number of nonzero entries
INT * JA
integer array of column indexes, the size is nnz
Vector with n entries of REAL type.
REAL * val
actual vector entries
Sparse matrix of INT type in CSR format.
INT col
column of matrix A, n
INT row
row number of matrix A, m
INT * IA
integer array of row pointers, the size is m+1
INT nnz
number of nonzero entries
INT * JA
integer array of column indexes, the size is nnz
INT * val
nonzero entries of A
Vector with n entries of INT type.
INT * val
actual vector entries