HYPRE_Int hypre_BlockTridiagSetup(void *data, hypre_ParCSRMatrix *A, hypre_ParVector *b, hypre_ParVector *x) { HYPRE_Int i, j, *index_set1, print_level, nsweeps, relax_type; HYPRE_Int nrows, nrows1, nrows2, start1, start2, *index_set2; HYPRE_Int count, ierr; double threshold; hypre_ParCSRMatrix **submatrices; HYPRE_Solver precon1; HYPRE_Solver precon2; HYPRE_IJVector ij_u1, ij_u2, ij_f1, ij_f2; hypre_ParVector *vector; MPI_Comm comm; hypre_BlockTridiagData *b_data = (hypre_BlockTridiagData *) data; HYPRE_ParCSRMatrixGetComm((HYPRE_ParCSRMatrix) A, &comm); index_set1 = b_data->index_set1; nrows1 = index_set1[0]; nrows = hypre_ParCSRMatrixNumRows(A); nrows2 = nrows - nrows1; b_data->index_set2 = hypre_CTAlloc(HYPRE_Int, nrows2+1); index_set2 = b_data->index_set2; index_set2[0] = nrows2; count = 1; for (i = 0; i < index_set1[1]; i++) index_set2[count++] = i; for (i = 1; i < nrows1; i++) for (j = index_set1[i]+1; j < index_set1[i+1]; j++) index_set2[count++] = j; for (i = index_set1[nrows1]+1; i < nrows; i++) index_set2[count++] = i; submatrices = hypre_CTAlloc(hypre_ParCSRMatrix *, 4); hypre_ParCSRMatrixExtractSubmatrices(A, index_set1, &submatrices); nrows1 = hypre_ParCSRMatrixNumRows(submatrices[0]); nrows2 = hypre_ParCSRMatrixNumRows(submatrices[3]); start1 = hypre_ParCSRMatrixFirstRowIndex(submatrices[0]); start2 = hypre_ParCSRMatrixFirstRowIndex(submatrices[3]); HYPRE_IJVectorCreate(comm, start1, start1+nrows1-1, &ij_u1); HYPRE_IJVectorSetObjectType(ij_u1, HYPRE_PARCSR); ierr = HYPRE_IJVectorInitialize(ij_u1); ierr += HYPRE_IJVectorAssemble(ij_u1); hypre_assert(!ierr); HYPRE_IJVectorCreate(comm, start1, start1+nrows1-1, &ij_f1); HYPRE_IJVectorSetObjectType(ij_f1, HYPRE_PARCSR); ierr = HYPRE_IJVectorInitialize(ij_f1); ierr += HYPRE_IJVectorAssemble(ij_f1); hypre_assert(!ierr); HYPRE_IJVectorCreate(comm, start2, start2+nrows2-1, &ij_u2); HYPRE_IJVectorSetObjectType(ij_u2, HYPRE_PARCSR); ierr = HYPRE_IJVectorInitialize(ij_u2); ierr += HYPRE_IJVectorAssemble(ij_u2); hypre_assert(!ierr); HYPRE_IJVectorCreate(comm, start2, start2+nrows1-1, &ij_f2); HYPRE_IJVectorSetObjectType(ij_f2, HYPRE_PARCSR); ierr = HYPRE_IJVectorInitialize(ij_f2); ierr += HYPRE_IJVectorAssemble(ij_f2); hypre_assert(!ierr); HYPRE_IJVectorGetObject(ij_f1, (void **) &vector); b_data->F1 = vector; HYPRE_IJVectorGetObject(ij_u1, (void **) &vector); b_data->U1 = vector; HYPRE_IJVectorGetObject(ij_f2, (void **) &vector); b_data->F2 = vector; HYPRE_IJVectorGetObject(ij_u2, (void **) &vector); b_data->U2 = vector; print_level = b_data->print_level; threshold = b_data->threshold; nsweeps = b_data->num_sweeps; relax_type = b_data->relax_type; threshold = b_data->threshold; HYPRE_BoomerAMGCreate(&precon1); HYPRE_BoomerAMGSetMaxIter(precon1, 1); HYPRE_BoomerAMGSetCycleType(precon1, 1); HYPRE_BoomerAMGSetPrintLevel(precon1, print_level); HYPRE_BoomerAMGSetMaxLevels(precon1, 25); HYPRE_BoomerAMGSetMeasureType(precon1, 0); HYPRE_BoomerAMGSetCoarsenType(precon1, 0); HYPRE_BoomerAMGSetStrongThreshold(precon1, threshold); HYPRE_BoomerAMGSetNumFunctions(precon1, 1); HYPRE_BoomerAMGSetNumSweeps(precon1, nsweeps); HYPRE_BoomerAMGSetRelaxType(precon1, relax_type); hypre_BoomerAMGSetup(precon1, submatrices[0], b_data->U1, b_data->F1); HYPRE_BoomerAMGCreate(&precon2); HYPRE_BoomerAMGSetMaxIter(precon2, 1); HYPRE_BoomerAMGSetCycleType(precon2, 1); HYPRE_BoomerAMGSetPrintLevel(precon2, print_level); HYPRE_BoomerAMGSetMaxLevels(precon2, 25); HYPRE_BoomerAMGSetMeasureType(precon2, 0); HYPRE_BoomerAMGSetCoarsenType(precon2, 0); HYPRE_BoomerAMGSetMeasureType(precon2, 1); HYPRE_BoomerAMGSetStrongThreshold(precon2, threshold); HYPRE_BoomerAMGSetNumFunctions(precon2, 1); HYPRE_BoomerAMGSetNumSweeps(precon2, nsweeps); HYPRE_BoomerAMGSetRelaxType(precon2, relax_type); hypre_BoomerAMGSetup(precon2, submatrices[3], NULL, NULL); b_data->precon1 = precon1; b_data->precon2 = precon2; b_data->A11 = submatrices[0]; hypre_ParCSRMatrixDestroy(submatrices[1]); b_data->A21 = submatrices[2]; b_data->A22 = submatrices[3]; hypre_TFree(submatrices); return (0); }
HYPRE_Int hypre_AMESetup(void *esolver) { HYPRE_Int ne, *edge_bc; hypre_AMEData *ame_data = esolver; hypre_AMSData *ams_data = ame_data -> precond; if (ams_data -> beta_is_zero) { ame_data -> t1 = hypre_ParVectorInDomainOf(ams_data -> G); ame_data -> t2 = hypre_ParVectorInDomainOf(ams_data -> G); } else { ame_data -> t1 = ams_data -> r1; ame_data -> t2 = ams_data -> g1; } ame_data -> t3 = ams_data -> r0; /* Eliminate boundary conditions in G = [Gii, Gib; 0, Gbb], i.e., compute [Gii, 0; 0, 0] */ { HYPRE_Int i, j, k, nv; HYPRE_Int *offd_edge_bc; hypre_ParCSRMatrix *Gt; nv = hypre_ParCSRMatrixNumCols(ams_data -> G); ne = hypre_ParCSRMatrixNumRows(ams_data -> G); edge_bc = hypre_TAlloc(HYPRE_Int, ne); for (i = 0; i < ne; i++) edge_bc[i] = 0; /* Find boundary (eliminated) edges */ { hypre_CSRMatrix *Ad = hypre_ParCSRMatrixDiag(ams_data -> A); HYPRE_Int *AdI = hypre_CSRMatrixI(Ad); HYPRE_Int *AdJ = hypre_CSRMatrixJ(Ad); HYPRE_Real *AdA = hypre_CSRMatrixData(Ad); hypre_CSRMatrix *Ao = hypre_ParCSRMatrixOffd(ams_data -> A); HYPRE_Int *AoI = hypre_CSRMatrixI(Ao); HYPRE_Real *AoA = hypre_CSRMatrixData(Ao); HYPRE_Real l1_norm; /* A row (edge) is boundary if its off-diag l1 norm is less than eps */ HYPRE_Real eps = DBL_EPSILON * 1e+4; for (i = 0; i < ne; i++) { l1_norm = 0.0; for (j = AdI[i]; j < AdI[i+1]; j++) if (AdJ[j] != i) l1_norm += fabs(AdA[j]); if (AoI) for (j = AoI[i]; j < AoI[i+1]; j++) l1_norm += fabs(AoA[j]); if (l1_norm < eps) edge_bc[i] = 1; } } hypre_ParCSRMatrixTranspose(ams_data -> G, &Gt, 1); /* Use a Matvec communication to find which of the edges connected to local vertices are on the boundary */ { hypre_ParCSRCommHandle *comm_handle; hypre_ParCSRCommPkg *comm_pkg; HYPRE_Int num_sends, *int_buf_data; HYPRE_Int index, start; offd_edge_bc = hypre_CTAlloc(HYPRE_Int, hypre_CSRMatrixNumCols(hypre_ParCSRMatrixOffd(Gt))); hypre_MatvecCommPkgCreate(Gt); comm_pkg = hypre_ParCSRMatrixCommPkg(Gt); num_sends = hypre_ParCSRCommPkgNumSends(comm_pkg); int_buf_data = hypre_CTAlloc(HYPRE_Int, hypre_ParCSRCommPkgSendMapStart(comm_pkg, num_sends)); index = 0; for (i = 0; i < num_sends; i++) { start = hypre_ParCSRCommPkgSendMapStart(comm_pkg, i); for (j = start; j < hypre_ParCSRCommPkgSendMapStart(comm_pkg, i+1); j++) { k = hypre_ParCSRCommPkgSendMapElmt(comm_pkg,j); int_buf_data[index++] = edge_bc[k]; } } comm_handle = hypre_ParCSRCommHandleCreate(11, comm_pkg, int_buf_data, offd_edge_bc); hypre_ParCSRCommHandleDestroy(comm_handle); hypre_TFree(int_buf_data); } /* Eliminate boundary vertex entries in G^t */ { hypre_CSRMatrix *Gtd = hypre_ParCSRMatrixDiag(Gt); HYPRE_Int *GtdI = hypre_CSRMatrixI(Gtd); HYPRE_Int *GtdJ = hypre_CSRMatrixJ(Gtd); HYPRE_Real *GtdA = hypre_CSRMatrixData(Gtd); hypre_CSRMatrix *Gto = hypre_ParCSRMatrixOffd(Gt); HYPRE_Int *GtoI = hypre_CSRMatrixI(Gto); HYPRE_Int *GtoJ = hypre_CSRMatrixJ(Gto); HYPRE_Real *GtoA = hypre_CSRMatrixData(Gto); HYPRE_Int bdr; for (i = 0; i < nv; i++) { bdr = 0; /* A vertex is boundary if it belongs to a boundary edge */ for (j = GtdI[i]; j < GtdI[i+1]; j++) if (edge_bc[GtdJ[j]]) { bdr = 1; break; } if (!bdr && GtoI) for (j = GtoI[i]; j < GtoI[i+1]; j++) if (offd_edge_bc[GtoJ[j]]) { bdr = 1; break; } if (bdr) { for (j = GtdI[i]; j < GtdI[i+1]; j++) /* if (!edge_bc[GtdJ[j]]) */ GtdA[j] = 0.0; if (GtoI) for (j = GtoI[i]; j < GtoI[i+1]; j++) /* if (!offd_edge_bc[GtoJ[j]]) */ GtoA[j] = 0.0; } } } hypre_ParCSRMatrixTranspose(Gt, &ame_data -> G, 1); hypre_ParCSRMatrixDestroy(Gt); hypre_TFree(offd_edge_bc); } /* Compute G^t M G */ { if (!hypre_ParCSRMatrixCommPkg(ame_data -> G)) hypre_MatvecCommPkgCreate(ame_data -> G); if (!hypre_ParCSRMatrixCommPkg(ame_data -> M)) hypre_MatvecCommPkgCreate(ame_data -> M); hypre_BoomerAMGBuildCoarseOperator(ame_data -> G, ame_data -> M, ame_data -> G, &ame_data -> A_G); hypre_ParCSRMatrixFixZeroRows(ame_data -> A_G); } /* Create AMG preconditioner and PCG-AMG solver for G^tMG */ { HYPRE_BoomerAMGCreate(&ame_data -> B1_G); HYPRE_BoomerAMGSetCoarsenType(ame_data -> B1_G, ams_data -> B_G_coarsen_type); HYPRE_BoomerAMGSetAggNumLevels(ame_data -> B1_G, ams_data -> B_G_agg_levels); HYPRE_BoomerAMGSetRelaxType(ame_data -> B1_G, ams_data -> B_G_relax_type); HYPRE_BoomerAMGSetNumSweeps(ame_data -> B1_G, 1); HYPRE_BoomerAMGSetMaxLevels(ame_data -> B1_G, 25); HYPRE_BoomerAMGSetTol(ame_data -> B1_G, 0.0); HYPRE_BoomerAMGSetMaxIter(ame_data -> B1_G, 1); HYPRE_BoomerAMGSetStrongThreshold(ame_data -> B1_G, ams_data -> B_G_theta); /* don't use exact solve on the coarsest level (matrix may be singular) */ HYPRE_BoomerAMGSetCycleRelaxType(ame_data -> B1_G, ams_data -> B_G_relax_type, 3); HYPRE_ParCSRPCGCreate(hypre_ParCSRMatrixComm(ame_data->A_G), &ame_data -> B2_G); HYPRE_PCGSetPrintLevel(ame_data -> B2_G, 0); HYPRE_PCGSetTol(ame_data -> B2_G, 1e-12); HYPRE_PCGSetMaxIter(ame_data -> B2_G, 20); HYPRE_PCGSetPrecond(ame_data -> B2_G, (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve, (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup, ame_data -> B1_G); HYPRE_ParCSRPCGSetup(ame_data -> B2_G, (HYPRE_ParCSRMatrix)ame_data->A_G, (HYPRE_ParVector)ame_data->t1, (HYPRE_ParVector)ame_data->t2); } /* Setup LOBPCG */ { HYPRE_Int seed = 75; mv_InterfaceInterpreter* interpreter; mv_MultiVectorPtr eigenvectors; ame_data -> interpreter = hypre_CTAlloc(mv_InterfaceInterpreter,1); interpreter = (mv_InterfaceInterpreter*) ame_data -> interpreter; HYPRE_ParCSRSetupInterpreter(interpreter); ame_data -> eigenvalues = hypre_CTAlloc(HYPRE_Real, ame_data -> block_size); ame_data -> eigenvectors = mv_MultiVectorCreateFromSampleVector(interpreter, ame_data -> block_size, ame_data -> t3); eigenvectors = (mv_MultiVectorPtr) ame_data -> eigenvectors; mv_MultiVectorSetRandom (eigenvectors, seed); /* Make the initial vectors discretely divergence free */ { HYPRE_Int i, j; HYPRE_Real *data; mv_TempMultiVector* tmp = mv_MultiVectorGetData(eigenvectors); HYPRE_ParVector *v = (HYPRE_ParVector*)(tmp -> vector); hypre_ParVector *vi; for (i = 0; i < ame_data -> block_size; i++) { vi = (hypre_ParVector*) v[i]; data = hypre_VectorData(hypre_ParVectorLocalVector(vi)); for (j = 0; j < ne; j++) if (edge_bc[j]) data[j] = 0.0; hypre_AMEDiscrDivFreeComponent(esolver, vi); } } } hypre_TFree(edge_bc); return hypre_error_flag; }