HYPRE_Int hypre_AMGNodalSchwarzSmoother( hypre_CSRMatrix *A, HYPRE_Int *dof_func, HYPRE_Int num_functions, HYPRE_Int option, HYPRE_Int **i_domain_dof_pointer, HYPRE_Int **j_domain_dof_pointer, HYPRE_Real **domain_matrixinverse_pointer, HYPRE_Int *num_domains_pointer) { /* option = 0: nodal symGS; 1: next to nodal symGS (overlapping Schwarz) */ HYPRE_Int *i_domain_dof, *j_domain_dof; HYPRE_Real *domain_matrixinverse; HYPRE_Int num_domains; HYPRE_Int *i_dof_node, *j_dof_node; HYPRE_Int *i_node_dof, *j_node_dof; HYPRE_Int *i_node_dof_dof, *j_node_dof_dof; HYPRE_Int *i_node_node, *j_node_node; HYPRE_Int num_nodes; HYPRE_Int *i_dof_dof = hypre_CSRMatrixI(A); HYPRE_Int *j_dof_dof = hypre_CSRMatrixJ(A); HYPRE_Real *a_dof_dof = hypre_CSRMatrixData(A); HYPRE_Int num_dofs = hypre_CSRMatrixNumRows(A); HYPRE_Int ierr = 0; HYPRE_Int i,j,k, l_loc, i_loc, j_loc; HYPRE_Int i_dof, j_dof; HYPRE_Int *i_local_to_global; HYPRE_Int *i_global_to_local; HYPRE_Int *i_int; HYPRE_Int *i_int_to_local; HYPRE_Int int_dof_counter, local_dof_counter, max_local_dof_counter=0; HYPRE_Int domain_dof_counter = 0, domain_matrixinverse_counter = 0; HYPRE_Real *AE, *XE; /* PCG arrays: --------------------------------------------------- HYPRE_Real *x, *rhs, *v, *w, *d, *aux; HYPRE_Int max_iter; ------------------------------------------------------------------ */ /* build dof_node graph: ----------------------------------------- */ num_nodes = num_dofs / num_functions; hypre_printf("\nnum_nodes: %d, num_dofs: %d = %d x %d\n", num_nodes, num_dofs, num_nodes, num_functions); i_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs+1); j_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs); for (i=0; i < num_dofs+1; i++) i_dof_node[i] = i; for (j = 0; j < num_nodes; j++) for (k = 0; k < num_functions; k++) j_dof_node[j*num_functions+k] = j; /* build node_dof graph: ----------------------------------------- */ ierr = transpose_matrix_create(&i_node_dof, &j_node_dof, i_dof_node, j_dof_node, num_dofs, num_nodes); /* build node_node graph: ----------------------------------------- */ ierr = matrix_matrix_product(&i_node_dof_dof, &j_node_dof_dof, i_node_dof, j_node_dof, i_dof_dof, j_dof_dof, num_nodes, num_dofs, num_dofs); ierr = matrix_matrix_product(&i_node_node, &j_node_node, i_node_dof_dof, j_node_dof_dof, i_dof_node, j_dof_node, num_nodes, num_dofs, num_nodes); hypre_TFree(i_node_dof_dof); hypre_TFree(j_node_dof_dof); /* compute for each node the local information: -------------------- */ i_global_to_local = i_dof_node; for (i_dof =0; i_dof < num_dofs; i_dof++) i_global_to_local[i_dof] = -1; domain_matrixinverse_counter = 0; domain_dof_counter = 0; for (i=0; i < num_nodes; i++) { local_dof_counter = 0; for (j=i_node_node[i]; j < i_node_node[i+1]; j++) for (k=i_node_dof[j_node_node[j]]; k<i_node_dof[j_node_node[j]+1]; k++) { j_dof = j_node_dof[k]; if (i_global_to_local[j_dof] < 0) { i_global_to_local[j_dof] = local_dof_counter; local_dof_counter++; } } domain_matrixinverse_counter += local_dof_counter*local_dof_counter; domain_dof_counter += local_dof_counter; if (local_dof_counter > max_local_dof_counter) max_local_dof_counter = local_dof_counter; for (j=i_node_node[i]; j < i_node_node[i+1]; j++) for (k=i_node_dof[j_node_node[j]]; k<i_node_dof[j_node_node[j]+1]; k++) { j_dof = j_node_dof[k]; i_global_to_local[j_dof] = -1; } } num_domains = num_nodes; i_domain_dof = hypre_CTAlloc(HYPRE_Int, num_domains+1); if (option == 1) j_domain_dof = hypre_CTAlloc(HYPRE_Int, domain_dof_counter); else j_domain_dof = hypre_CTAlloc(HYPRE_Int, num_dofs); if (option == 1) domain_matrixinverse = hypre_CTAlloc(HYPRE_Real, domain_matrixinverse_counter); else domain_matrixinverse = hypre_CTAlloc(HYPRE_Real, num_dofs * num_functions); i_local_to_global = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter); AE = hypre_CTAlloc(HYPRE_Real, max_local_dof_counter * max_local_dof_counter); XE = hypre_CTAlloc(HYPRE_Real, max_local_dof_counter * max_local_dof_counter); i_int_to_local = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter); i_int = hypre_CTAlloc(HYPRE_Int, max_local_dof_counter); for (l_loc=0; l_loc < max_local_dof_counter; l_loc++) i_int[l_loc] = -1; domain_dof_counter = 0; domain_matrixinverse_counter = 0; for (i=0; i < num_nodes; i++) { i_domain_dof[i] = domain_dof_counter; local_dof_counter = 0; for (j=i_node_node[i]; j < i_node_node[i+1]; j++) for (k=i_node_dof[j_node_node[j]]; k<i_node_dof[j_node_node[j]+1]; k++) { j_dof = j_node_dof[k]; if (i_global_to_local[j_dof] < 0) { i_global_to_local[j_dof] = local_dof_counter; i_local_to_global[local_dof_counter] = j_dof; local_dof_counter++; } } for (j=i_node_dof[i]; j < i_node_dof[i+1]; j++) for (k=i_dof_dof[j_node_dof[j]]; k < i_dof_dof[j_node_dof[j]+1]; k++) if (i_global_to_local[j_dof_dof[k]] < 0) hypre_printf("WRONG local indexing: ====================== \n"); int_dof_counter = 0; for (k=i_node_dof[i]; k < i_node_dof[i+1]; k++) { i_dof = j_node_dof[k]; i_loc = i_global_to_local[i_dof]; i_int[i_loc] = int_dof_counter; i_int_to_local[int_dof_counter] = i_loc; int_dof_counter++; } /* get local matrix AE: ======================================== */ if (option == 1) { for (i_loc=0; i_loc < local_dof_counter; i_loc++) for (j_loc=0; j_loc < local_dof_counter; j_loc++) AE[i_loc + j_loc * local_dof_counter] = 0.e0; for (i_loc=0; i_loc < local_dof_counter; i_loc++) { i_dof = i_local_to_global[i_loc]; for (j=i_dof_dof[i_dof]; j < i_dof_dof[i_dof+1]; j++) { j_loc = i_global_to_local[j_dof_dof[j]]; if (j_loc >=0) AE[i_loc + j_loc * local_dof_counter] = a_dof_dof[j]; } } /* get block for Schwarz smoother: ============================= */ ierr = matinv(XE, AE, local_dof_counter); /* hypre_printf("ierr_AE_inv: %d\n", ierr); */ } if (option == 1) for (i_loc=0; i_loc < local_dof_counter; i_loc++) j_domain_dof[domain_dof_counter+i_loc] = i_local_to_global[i_loc]; if (option == 1) for (i_loc=0; i_loc < local_dof_counter; i_loc++) for (j_loc=0; j_loc < local_dof_counter; j_loc++) domain_matrixinverse[domain_matrixinverse_counter + i_loc + j_loc * local_dof_counter] = XE[i_loc + j_loc * local_dof_counter]; if (option == 0) { for (i_loc=0; i_loc < int_dof_counter; i_loc++) for (j_loc=0; j_loc < int_dof_counter; j_loc++) AE[i_loc + j_loc * int_dof_counter] = 0.e0; for (l_loc=0; l_loc < int_dof_counter; l_loc++) { i_loc = i_int_to_local[l_loc]; i_dof = i_local_to_global[i_loc]; for (j=i_dof_dof[i_dof]; j < i_dof_dof[i_dof+1]; j++) { j_loc = i_global_to_local[j_dof_dof[j]]; if (j_loc >=0) if (i_int[j_loc] >=0) AE[i_loc + i_int[j_loc] * int_dof_counter] = a_dof_dof[j]; } } ierr = matinv(XE, AE, int_dof_counter); for (i_loc=0; i_loc < int_dof_counter; i_loc++) { j_domain_dof[domain_dof_counter + i_loc] = i_local_to_global[i_int_to_local[i_loc]]; for (j_loc=0; j_loc < int_dof_counter; j_loc++) domain_matrixinverse[domain_matrixinverse_counter + i_loc + j_loc * int_dof_counter] = XE[i_loc + j_loc * int_dof_counter]; } domain_dof_counter+=int_dof_counter; domain_matrixinverse_counter+=int_dof_counter*int_dof_counter; } else { domain_dof_counter+=local_dof_counter; domain_matrixinverse_counter+=local_dof_counter*local_dof_counter; } for (l_loc=0; l_loc < local_dof_counter; l_loc++) { i_int[l_loc] = -1; i_global_to_local[i_local_to_global[l_loc]] = -1; } } i_domain_dof[num_nodes] = domain_dof_counter; hypre_TFree(i_dof_node); hypre_TFree(j_dof_node); hypre_TFree(i_node_dof); hypre_TFree(j_node_dof); hypre_TFree(i_node_node); hypre_TFree(j_node_node); hypre_TFree(i_int); hypre_TFree(i_int_to_local); hypre_TFree(i_local_to_global); hypre_TFree(AE); hypre_TFree(XE); *i_domain_dof_pointer = i_domain_dof; *j_domain_dof_pointer = j_domain_dof; *num_domains_pointer = num_domains; *domain_matrixinverse_pointer = domain_matrixinverse; /* hypre_printf("exit *Schwarz*: ===============================\n\n"); */ /* ----------------------------------------------------------------- x = hypre_CTAlloc(HYPRE_Real, num_dofs); rhs = hypre_CTAlloc(HYPRE_Real, num_dofs); v = hypre_CTAlloc(HYPRE_Real, num_dofs); w = hypre_CTAlloc(HYPRE_Real, num_dofs); d = hypre_CTAlloc(HYPRE_Real, num_dofs); aux = hypre_CTAlloc(HYPRE_Real, num_dofs); for (i=0; i < num_dofs; i++) x[i] = 0.e0; for (i=0; i < num_dofs; i++) rhs[i] = rand(); max_iter = 1000; hypre_printf("\nenter SchwarzPCG: =======================================\n"); ierr = hypre_Schwarzpcg(x, rhs, a_dof_dof, i_dof_dof, j_dof_dof, i_domain_dof, j_domain_dof, domain_matrixinverse, num_domains, v, w, d, aux, max_iter, num_dofs); hypre_printf("\n\n=======================================================\n"); hypre_printf(" END test PCG solve: \n"); hypre_printf("===========================================================\n"); hypre_TFree(x); hypre_TFree(rhs); hypre_TFree(aux); hypre_TFree(v); hypre_TFree(w); hypre_TFree(d); ----------------------------------------------------------------------- */ return ierr; }
HYPRE_Int hypre_AMGNodalSchwarzSmoother( hypre_CSRMatrix *A, HYPRE_Int *dof_func, HYPRE_Int num_functions, HYPRE_Int option, HYPRE_Int **i_domain_dof_pointer, HYPRE_Int **j_domain_dof_pointer, double **domain_matrixinverse_pointer, HYPRE_Int *num_domains_pointer) { /* option = 0: nodal symGS; 1: next to nodal symGS (overlapping Schwarz) */ HYPRE_Int *i_domain_dof, *j_domain_dof; double *domain_matrixinverse; HYPRE_Int num_domains; HYPRE_Int *i_dof_node, *j_dof_node; HYPRE_Int *i_node_dof, *j_node_dof; HYPRE_Int *i_node_dof_dof, *j_node_dof_dof; HYPRE_Int *i_node_node, *j_node_node; HYPRE_Int num_nodes; HYPRE_Int *i_dof_dof = hypre_CSRMatrixI(A); HYPRE_Int *j_dof_dof = hypre_CSRMatrixJ(A); double *a_dof_dof = hypre_CSRMatrixData(A); HYPRE_Int num_dofs = hypre_CSRMatrixNumRows(A); HYPRE_Int ierr = 0; HYPRE_Int i,j,k, l_loc, i_loc, j_loc; HYPRE_Int i_dof, j_dof; HYPRE_Int *i_local_to_global; HYPRE_Int *i_global_to_local; HYPRE_Int *i_int; HYPRE_Int *i_int_to_local; HYPRE_Int int_dof_counter, local_dof_counter, max_local_dof_counter=0; HYPRE_Int domain_dof_counter = 0, domain_matrixinverse_counter = 0; double *AE, *XE; /* PCG arrays: --------------------------------------------------- double *x, *rhs, *v, *w, *d, *aux; HYPRE_Int max_iter; ------------------------------------------------------------------ */ /* build dof_node graph: ----------------------------------------- */ num_nodes = num_dofs / num_functions; hypre_printf("\nnum_nodes: %d, num_dofs: %d = %d x %d\n", num_nodes, num_dofs, num_nodes, num_functions); i_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs+1); j_dof_node = hypre_CTAlloc(HYPRE_Int, num_dofs); for (i=0; i < num_dofs+1; i++) i_dof_node[i] = i; for (j = 0; j < num_nodes; j++) for (k = 0; k < num_functions; k++) j_dof_node[j*num_functions+k] = j; /* build node_dof graph: ----------------------------------------- */ ierr = transpose_matrix_create(&i_node_dof, &j_node_dof, i_dof_node, j_dof_node, num_dofs, num_nodes); /* build node_node graph: ----------------------------------------- */ ierr = matrix_matrix_product(&i_node_dof_dof, &j_node_dof_dof, i_node_dof, j_node_dof, i_dof_dof, j_dof_dof, num_nodes, num_dofs, num_dofs); ierr = matrix_matrix_product(&i_node_node, &j_node_node, i_node_dof_dof, j_node_dof_dof, i_dof_node, j_dof_node, num_nodes, num_dofs, num_nodes); hypre_TFree(i_node_dof_dof); hypre_TFree(j_node_dof_dof); /* compute for each node the local information: -------------------- */ i_global_to_local = i_dof_node; for (i_dof =0; i_dof < num_dofs; i_dof++) i_global_to_local[i_dof] = -1; domain_matrixinverse_counter = 0; domain_dof_counter = 0; for (i=0; i < num_nodes; i++) { local_dof_counter = 0; for (j=i_node_node[i]; j < i_node_node[i+1]; j++) for (k=i_node_dof[j_node_node[j]]; k<i_node_dof[j_node_node[j]+1]; k++) { j_dof = j_node_dof[k]; if (i_global_to_local[j_dof] < 0) { i_global_to_local[j_dof] = local_dof_counter; local_dof_counter++; } } domain_matrixinverse_counter += local_dof_counter*local_dof_counter; domain_dof_counter += local_dof_counter; if (local_dof_counter > max_local_dof_counter) max_local_dof_counter = local_dof_counter; for (j=i_node_node[i]; j < i_node_node[i+1]; j++) for (k=i_node_dof[j_node_node[j]]; k<i_node_dof[j_node_node[j]+1]; k++) { j_dof = j_node_dof[k]; i_global_to_local[j_dof] = -1; } } num_domains = num_nodes; i_domain_dof = hypre_CTAlloc(HYPRE_Int, num_domains+1); if (option == 1) j_domain_dof = hypre_CTAlloc(HYPRE_Int, domain_dof_counter); else j_domain_dof = hypre_CTAlloc(HYPRE_Int, num_dofs); if (option == 1) domain_matrixinverse = hypre_CTAlloc(double, domain_matrixinverse_counter); else