static void do_test(MAP *rmap, MAP *cmap) { MAT *A; VEC *x, *y; INT i, j, m0, n0; INT *cols = phgAlloc(cmap->nglobal * sizeof(*cols)); FLOAT *data = phgAlloc(cmap->nglobal * sizeof(*data)); A = phgMapCreateMat(rmap, cmap); m0 = A->rmap->partition[A->rmap->rank]; n0 = A->cmap->partition[A->cmap->rank]; /* Matrix entries: A(I,J) = 1 + (I-1) + (J-1) */ for (i = m0; i < m0 + A->rmap->nlocal; i++) { #if 0 /* Test MatAddEntry */ for (j = 0; j < A->cmap->nglobal; j++) phgMatAddGlobalEntry(A, i, j, 1.0 + i + j); #else /* Test MatAddEntries */ for (j = 0; j < A->cmap->nglobal; j++) { cols[j] = j; data[j] = 1.0 + i + j; } phgMatAddGlobalEntries(A, 1, &i, A->cmap->nglobal, cols, data); #endif } phgFree(cols); phgFree(data); phgMatAssemble(A); phgInfo(-1, "y = A * x\n"); x = phgMapCreateVec(A->cmap, 1); for (i = 0; i < x->map->nlocal; i++) x->data[i] = 1.0 + i + n0; phgVecAssemble(x); y = phgMatVec(MAT_OP_N, 1.0, A, x, 0.0, NULL); for (i = 0; i < y->map->nlocal; i++) phgInfo(-1, " y->data[%d] = %lg\n", i + m0, (double)y->data[i]); phgVecDestroy(&x); phgVecDestroy(&y); phgInfo(-1, "y = A' * x\n"); x = phgMapCreateVec(A->rmap, 1); for (i = 0; i < x->map->nlocal; i++) x->data[i] = 1.0 + i + m0; phgVecAssemble(x); y = phgMatVec(MAT_OP_T, 1.0, A, x, 0.0, NULL); for (i = 0; i < y->map->nlocal; i++) phgInfo(-1, " y->data[%d] = %lg\n", i + n0, (double)y->data[i]); phgVecDestroy(&x); phgVecDestroy(&y); phgMatDestroy(&A); }
int main(int argc, char *argv[]) { GRID *g; DOF *u_h; MAT *A, *A0, *B; MAP *map; INT i; size_t nnz, mem, mem_peak; VEC *x, *y0, *y1, *y2; double t0, t1, dnz, dnz1, mflops, mop; char *fn = "../test/cube.dat"; FLOAT mem_max = 300; INT refine = 0; phgOptionsRegisterFilename("-mesh_file", "Mesh file", (char **)&fn); phgOptionsRegisterInt("-loop_count", "Loop count", &loop_count); phgOptionsRegisterInt("-refine", "Refinement level", &refine); phgOptionsRegisterFloat("-mem_max", "Maximum memory", &mem_max); phgInit(&argc, &argv); g = phgNewGrid(-1); if (!phgImport(g, fn, FALSE)) phgError(1, "can't read file \"%s\".\n", fn); phgRefineAllElements(g, refine); u_h = phgDofNew(g, DOF_DEFAULT, 1, "u_h", DofNoAction); while (TRUE) { phgPrintf("\n"); if (phgBalanceGrid(g, 1.2, 1, NULL, 0.)) phgPrintf("Repartition mesh, %d submeshes, load imbalance: %lg\n", g->nprocs, (double)g->lif); map = phgMapCreate(u_h, NULL); A = phgMapCreateMat(map, map); A->handle_bdry_eqns = TRUE; build_matrix(A, u_h); phgMatAssemble(A); /* Note: A is unsymmetric (A' != A) if boundary entries not removed */ phgMatRemoveBoundaryEntries(A); #if 0 /* test block matrix operation */ A0 = phgMatCreateBlockMatrix(g->comm, 1, 1, &A, NULL); #else A0 = A; #endif phgPrintf("%d DOF, %d elems, %d submeshes, matrix size: %d, LIF: %lg\n", DofGetDataCountGlobal(u_h), g->nleaf_global, g->nprocs, A->rmap->nglobal, (double)g->lif); /* test PHG mat-vec multiply */ x = phgMapCreateVec(A->cmap, 1); y1 = phgMapCreateVec(A->rmap, 1); phgVecRandomize(x, 123); phgMatVec(MAT_OP_N, 1.0, A0, x, 0.0, &y1); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { phgMatVec(MAT_OP_N, 1.0, A0, x, 0.0, &y1); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); y0 = phgVecCopy(y1, NULL); nnz = A->nnz_d + A->nnz_o; #if USE_MPI dnz1 = nnz; MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm); #else dnz = nnz; #endif mop = loop_count * (dnz + dnz - A->rmap->nlocal) * 1e-6; phgPrintf("\n"); t1 -= t0; phgPrintf(" PHG: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF)\n", t1, dnz, mop / (t1 == 0 ? 1. : t1), mflops); /* test trans(A)*x */ phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { phgMatVec(MAT_OP_T, 1.0, A0, x, 0.0, &y1); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); t1 -= t0; phgPrintf(" A'*x: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), " "err: %le\n", t1, dnz, mop / (t1 == 0 ? 1. : t1), mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL)); /* time A * trans(A) */ phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); B = phgMatMat(MAT_OP_N, MAT_OP_N, 1.0, A, A, 0.0, NULL); t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); nnz = B->nnz_d + B->nnz_o; #if USE_MPI dnz1 = nnz; MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm); #else dnz = nnz; #endif /* compare B*x <--> A*A*x */ y2 = phgMatVec(MAT_OP_N, 1.0, B, x, 0.0, NULL); phgMatVec(MAT_OP_N, 1.0, A0, y0, 0.0, &y1); phgMatDestroy(&B); t1 -= t0; phgPrintf(" A*A: time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n", t1, dnz, mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL)); #if USE_PETSC { Mat ma, mb; MatInfo info; Vec va, vb, vc; PetscScalar *vec; ma = phgPetscCreateMatAIJ(A); MatGetVecs(ma, PETSC_NULL, &va); VecDuplicate(va, &vb); VecGetArray(va, &vec); memcpy(vec, x->data, x->map->nlocal * sizeof(*vec)); VecRestoreArray(va, &vec); MatMult(ma, va, vb); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { MatMult(ma, va, vb); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); VecGetArray(vb, &vec); memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec)); VecRestoreArray(vb, &vec); MatGetInfo(ma, MAT_GLOBAL_SUM, &info); /*phgPrintf(" --------------------------------------------" "-------------------------\n");*/ phgPrintf("\n"); t1 -= t0; dnz = info.nz_used; phgPrintf(" PETSc: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), " "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL)); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { MatMultTranspose(ma, va, vb); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); VecGetArray(vb, &vec); memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec)); VecRestoreArray(vb, &vec); t1 -= t0; phgPrintf(" A'*x: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), " "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL)); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); MatMatMult(ma, ma, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &mb); t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); t1 -= t0; MatGetInfo(mb, MAT_GLOBAL_SUM, &info); dnz = info.nz_used; VecDuplicate(va, &vc); /* compare B*x <--> A*A*x */ MatMult(ma, vb, vc); MatMult(mb, va, vb); VecGetArray(vb, &vec); memcpy(y1->data, vec, x->map->nlocal * sizeof(*vec)); VecRestoreArray(vb, &vec); VecGetArray(vc, &vec); memcpy(y2->data, vec, x->map->nlocal * sizeof(*vec)); VecRestoreArray(vc, &vec); phgPrintf(" A*A: time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n", t1, dnz, mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL)); phgPetscMatDestroy(&mb); phgPetscMatDestroy(&ma); phgPetscVecDestroy(&va); phgPetscVecDestroy(&vb); phgPetscVecDestroy(&vc); } #endif /* USE_PETSC */ #if USE_HYPRE { HYPRE_IJMatrix ma; HYPRE_IJVector va, vb, vc; HYPRE_ParCSRMatrix par_ma; hypre_ParCSRMatrix *par_mb; HYPRE_ParVector par_va, par_vb, par_vc; HYPRE_Int offset, *ni, start, end; assert(sizeof(INT)==sizeof(int) && sizeof(FLOAT)==sizeof(double)); setup_hypre_mat(A, &ma); ni = phgAlloc(2 * A->rmap->nlocal * sizeof(*ni)); offset = A->cmap->partition[A->cmap->rank]; for (i = 0; i < A->rmap->nlocal; i++) ni[i] = i + offset; HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1, &va); HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1, &vb); HYPRE_IJVectorCreate(g->comm, offset, offset + A->rmap->nlocal - 1, &vc); HYPRE_IJVectorSetObjectType(va, HYPRE_PARCSR); HYPRE_IJVectorSetObjectType(vb, HYPRE_PARCSR); HYPRE_IJVectorSetObjectType(vc, HYPRE_PARCSR); HYPRE_IJVectorSetMaxOffProcElmts(va, 0); HYPRE_IJVectorSetMaxOffProcElmts(vb, 0); HYPRE_IJVectorSetMaxOffProcElmts(vc, 0); HYPRE_IJVectorInitialize(va); HYPRE_IJVectorInitialize(vb); HYPRE_IJVectorInitialize(vc); HYPRE_IJMatrixGetObject(ma, (void **)(void *)&par_ma); HYPRE_IJVectorGetObject(va, (void **)(void *)&par_va); HYPRE_IJVectorGetObject(vb, (void **)(void *)&par_vb); HYPRE_IJVectorGetObject(vc, (void **)(void *)&par_vc); HYPRE_IJVectorSetValues(va, A->cmap->nlocal, ni, (double *)x->data); HYPRE_IJVectorAssemble(va); HYPRE_IJVectorAssemble(vb); HYPRE_IJVectorAssemble(vc); HYPRE_IJMatrixGetRowCounts(ma, A->cmap->nlocal, ni, ni + A->rmap->nlocal); for (i = 0, nnz = 0; i < A->rmap->nlocal; i++) nnz += ni[A->rmap->nlocal + i]; #if USE_MPI dnz1 = nnz; MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm); #else dnz = nnz; #endif HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_va, 0.0, par_vb); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_va, 0.0, par_vb); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data); /*phgPrintf(" --------------------------------------------" "-------------------------\n");*/ phgPrintf("\n"); t1 -= t0; phgPrintf(" HYPRE: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), " "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL)); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); for (i = 0; i < loop_count; i++) { HYPRE_ParCSRMatrixMatvecT(1.0, par_ma, par_va, 0.0, par_vb); } t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data); t1 -= t0; phgPrintf(" A'*x: time %0.4lf, nnz %0.16lg, %0.2lfMF (%0.2lfMF), " "err: %le\n", t1, dnz, mop / (t1==0 ? 1.:t1), mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y0, 1.0, &y1), 0, NULL)); phgPerfGetMflops(g, NULL, NULL); /* reset flops counter */ t0 = phgGetTime(NULL); /* Note: 'HYPRE_ParCSRMatrix' is currently typedef'ed to * 'hypre_ParCSRMatrix *' */ par_mb = hypre_ParMatmul((hypre_ParCSRMatrix *)par_ma, (hypre_ParCSRMatrix *)par_ma); t1 = phgGetTime(NULL); mflops = phgPerfGetMflops(g, NULL, NULL); start = hypre_ParCSRMatrixFirstRowIndex(par_mb); end = hypre_ParCSRMatrixLastRowIndex(par_mb) + 1; for (i = start, nnz = 0; i < end; i++) { HYPRE_Int ncols; hypre_ParCSRMatrixGetRow(par_mb, i, &ncols, NULL, NULL); hypre_ParCSRMatrixRestoreRow(par_mb, i, &ncols, NULL, NULL); nnz += ncols; } #if USE_MPI dnz1 = nnz; MPI_Reduce(&dnz1, &dnz, 1, MPI_DOUBLE, MPI_SUM, 0, g->comm); #else dnz = nnz; #endif /* compare B*x <--> A*A*x */ HYPRE_ParCSRMatrixMatvec(1.0, par_ma, par_vb, 0.0, par_vc); HYPRE_ParCSRMatrixMatvec(1.0, (void *)par_mb, par_va, 0.0, par_vb); HYPRE_IJVectorGetValues(vb, A->rmap->nlocal, ni, (double*)y1->data); HYPRE_IJVectorGetValues(vc, A->rmap->nlocal, ni, (double*)y2->data); hypre_ParCSRMatrixDestroy((par_mb)); t1 -= t0; phgPrintf(" A*A: time %0.4lf, nnz %0.16lg, %0.2lfMF, err: %le\n", t1, dnz, mflops, (double)phgVecNorm2(phgVecAXPBY(-1.0, y1, 1.0, &y2), 0, NULL)); phgFree(ni); HYPRE_IJMatrixDestroy(ma); HYPRE_IJVectorDestroy(va); HYPRE_IJVectorDestroy(vb); HYPRE_IJVectorDestroy(vc); } #endif /* USE_HYPRE */ if (A0 != A) phgMatDestroy(&A0); #if 0 if (A->rmap->nglobal > 1000) { VEC *v = phgMapCreateVec(A->rmap, 3); for (i = 0; i < v->map->nlocal; i++) { v->data[i + 0 * v->map->nlocal] = 1 * (i + v->map->partition[g->rank]); v->data[i + 1 * v->map->nlocal] = 2 * (i + v->map->partition[g->rank]); v->data[i + 2 * v->map->nlocal] = 3 * (i + v->map->partition[g->rank]); } phgMatDumpMATLAB(A, "A", "A.m"); phgVecDumpMATLAB(v, "v", "v.m"); phgFinalize(); exit(0); } #endif phgMatDestroy(&A); phgVecDestroy(&x); phgVecDestroy(&y0); phgVecDestroy(&y1); phgVecDestroy(&y2); phgMapDestroy(&map); mem = phgMemoryUsage(g, &mem_peak); dnz = mem / (1024.0 * 1024.0); dnz1 = mem_peak / (1024.0 * 1024.0); /*phgPrintf(" --------------------------------------------" "-------------------------\n");*/ phgPrintf("\n"); phgPrintf(" Memory: current %0.4lgMB, peak %0.4lgMB\n", dnz, dnz1); #if 0 { static int loop_count = 0; if (++loop_count == 4) break; } #endif if (mem_peak > 1024 * (size_t)1024 * mem_max) break; phgRefineAllElements(g, 1); } phgDofFree(&u_h); phgFreeGrid(&g); phgFinalize(); return 0; }
void phgNSInitPc(NSSolver *ns) { GRID *g = ns->g; MAP *Pmap = ns->Pmap, *Pbcmap; BOOLEAN use_Fu = _nsp->use_Fu; int verb; /* pcd boundary type test */ _pcd->dof_inflow = phgDofNew(g, _nsp->ptype, 1, "dof inflow", DofNoAction); _pcd->dof_outflow = phgDofNew(g, _nsp->ptype, 1, "dof outflow", DofNoAction); _pcd->dof_nobdry = phgDofNew(g, _nsp->ptype, 1, "dof nobdry", DofNoAction); phgDofSetDirichletBoundaryMask(_pcd->dof_inflow, INFLOW); phgDofSetDirichletBoundaryMask(_pcd->dof_outflow, OUTFLOW); phgDofSetDirichletBoundaryMask(_pcd->dof_nobdry, 0); _pcd->map_inflow = phgMapCreate(_pcd->dof_inflow, NULL); _pcd->map_outflow = phgMapCreate(_pcd->dof_outflow, NULL); _pcd->map_nobdry = phgMapCreate(_pcd->dof_nobdry, NULL); _pcd->Pbcmap = phgMapCreate(_pcd->pbc, NULL); Pbcmap = _pcd->Pbcmap; Unused(Pmap); #warning PCD B.C.: step 1. build mat using map... /* * PCD boundary setup: should be consistent with code above */ if (_nsp->pin_node) { _pcd->matFp = phgMapCreateMat(Pbcmap, Pbcmap); _pcd->matAp = phgMapCreateMat(Pbcmap, Pbcmap); _pcd->matQp = phgMapCreateMat(Pbcmap, Pbcmap); } else { //_pcd->matAp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow); //_pcd->matFp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow); _pcd->matFp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow); _pcd->matAp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow); //_pcd->matQp = phgMapCreateMat(_pcd->map_outflow, _pcd->map_outflow); //_pcd->matQp = phgMapCreateMat(_pcd->map_inflow, _pcd->map_inflow); //_pcd->matFp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry); //_pcd->matAp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry); //_pcd->matFp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry); _pcd->matQp = phgMapCreateMat(_pcd->map_nobdry, _pcd->map_nobdry); } /* stokes problem: get SYMETRIC mat when assemble. * Handle_bdry_eqns means mat is composed with row of boundary row * and non-bdry row, and eliminating mat columes of dirichlet dof. */ if (_nsp->use_symetric) { _pcd->matFp->handle_bdry_eqns = TRUE; _pcd->matAp->handle_bdry_eqns = TRUE; _pcd->matQp->handle_bdry_eqns = TRUE; } /* genearl NS: no need to eliminate mat columes of dirichlet dof */ else { _pcd->matFp->handle_bdry_eqns = FALSE; _pcd->matAp->handle_bdry_eqns = FALSE; _pcd->matQp->handle_bdry_eqns = FALSE; } _pcd->rhsScale = phgMapCreateVec(_pcd->matQp->rmap, 1); phgVecDisassemble(_pcd->rhsScale); ns->pc = phgMat2Solver(SOLVER_PreOnly, ns->solver_u->mat); if (_nsp->use_PCD) phgSolverSetPC(ns->solver_u, ns->pc, pc_proc); /* solver F */ phgOptionsPush(); phgOptionsSetOptions("-solver hypre " "-hypre_solver pcg " "-hypre_pc boomeramg " "-solver_maxit 10 " "-solver_rtol 1e-4"); phgOptionsSetOptions(_nsp->F_opts); /* use matF in the preconditioning matrix */ _pcd->solver_F = phgMat2Solver(SOLVER_DEFAULT, ns->matF); _pcd->solver_F->verb = SUB_SOLVER_VERB; /* Set user options. */ _pcd->pc_F = NULL; #if USE_MG if (ns_params->use_mg_F) { MAT *matF = ns->matF; assert(ns_params->use_PCD && !ns_params->use_Fu); _pcd->pc_F = phgMat2Solver(SOLVER_PreOnly, matF); phgOptionsSetOptions("-solver petsc "); matF->mv_data = phgAlloc(sizeof(*matF->mv_data)); matF->mv_data[0] = (void *) ns->mg; phgSolverSetPC(_pcd->solver_F, _pcd->pc_F, mg_pc_proc); } #endif /* USE_MG */ _pcd->solver_F->warn_maxit = FALSE; phgOptionsPop(); /* solver Ap */ phgOptionsPush(); phgOptionsSetOptions("-solver hypre " "-hypre_solver gmres " "-hypre_pc boomeramg " "-solver_maxit 10 " "-solver_rtol 1e-3"); phgOptionsSetOptions(_nsp->Ap_opts); _pcd->solver_Ap = phgMat2Solver(SOLVER_DEFAULT, _pcd->matAp); _pcd->solver_Ap->warn_maxit = FALSE; _pcd->solver_Ap->verb = SUB_SOLVER_VERB; phgOptionsPop(); _pcd->pc_Ap = NULL; #if USE_MG if (ns_params->use_mg_Ap) { MAT *matAp = _pcd->matAp; assert(ns_params->use_PCD); _pcd->pc_Ap = phgMat2Solver(SOLVER_PreOnly, matAp); phgOptionsSetOptions("-solver petsc "); matAp->mv_data = phgAlloc(sizeof(*matAp->mv_data)); matAp->mv_data[0] = (void *) ns->mg; phgSolverSetPC(_pcd->solver_Ap, _pcd->pc_Ap, mg_pc_proc); } #endif /* USE_MG */ /* solver Qp */ phgOptionsPush(); phgOptionsSetOptions("-solver hypre " "-hypre_solver pcg " "-hypre_pc boomeramg " "-solver_maxit 10 " "-solver_rtol 1e-3"); phgOptionsSetOptions(_nsp->Qp_opts); _pcd->solver_Qp = phgMat2Solver(SOLVER_DEFAULT, _pcd->matQp); _pcd->solver_Qp->warn_maxit = FALSE; _pcd->solver_Qp->verb = SUB_SOLVER_VERB; phgOptionsPop(); _pcd->pc_Qp = NULL; #if USE_MG if (ns_params->use_mg_Qp) { MAT *matQp = _pcd->matQp; assert(ns_params->use_PCD); _pcd->pc_Qp = phgMat2Solver(SOLVER_PreOnly, matQp); phgOptionsSetOptions("-solver petsc "); matQp->mv_data = phgAlloc(sizeof(*matQp->mv_data)); matQp->mv_data[0] = (void *) ns->mg; phgSolverSetPC(_pcd->solver_Qp, _pcd->pc_Qp, mg_pc_proc); } #endif /* USE_MG */ /* Fu for solve F^{-1} */ if (use_Fu) { /* _nsp->implicit_centrip && */ DOF *u1; MAP *u1map; MAT *matFu; u1 = _pcd->u1 = phgDofNew(g, _nsp->utype, 1, "velocity component u", DofNoAction); phgDofSetDirichletBoundaryMask(u1, SETFLOW); u1map = _pcd->u1map = phgMapCreate(_pcd->u1, NULL); matFu = _pcd->matFu = phgMapCreateMat(u1map, u1map); if (_nsp->use_symetric) matFu->handle_bdry_eqns = TRUE; /* solver Fu */ phgOptionsPush(); phgOptionsSetOptions("-solver hypre " "-hypre_solver pcg " "-hypre_pc boomeramg " "-solver_maxit 10 " "-solver_rtol 1e-4"); phgOptionsSetOptions(_nsp->Fu_opts); _pcd->solver_Fu = phgMat2Solver(SOLVER_DEFAULT, _pcd->matFu); _pcd->solver_Fu->warn_maxit = FALSE; _pcd->solver_Fu->verb = SUB_SOLVER_VERB; phgOptionsPop(); } return; }