PARAMS *phgParametersCreate() { PARAMS *params = (PARAMS *) phgAlloc(sizeof(*params)); /* default settings */ _p->fn = "cube.bdface.mesh"; _p->fn_bdry = "cube.bdry.dat"; _p->fix_edge = FALSE; _p->fix_bdry = FALSE; _p->pre_refines = 0; _p->tol = 1e-2; _p->n_move_substep = 1; _p->n_smooth_monitor = 1; _p->move_opts = NULL; _p->dof_opts = NULL; _p->verb = 0; _p->viz_move = FALSE; /* get user defined parameter from file*/ phgOptionsRegisterFilename("mesh_file", "Mesh file", (char **)&_p->fn); phgOptionsRegisterFilename("bdry_face_file", "Boundary face file", (char **)&_p->fn_bdry); phgOptionsRegisterInt("pre_refines", "Pre-refines", &_p->pre_refines); phgOptionsRegisterInt("mm_n_move_substep", "Moving Mesh: num of substep in one step", &_p->n_move_substep); phgOptionsRegisterInt("mm_n_smooth_monitor", "Moving Mesh: num of smoothing mointor", &_p->n_smooth_monitor); phgOptionsRegisterInt("mm_verbosity", "Moving Mesh: Verbosity", &_p->verb); phgOptionsRegisterFloat("mm_tol", "Moving Mesh: tolerence of error", &_p->tol); phgOptionsRegisterNoArg("mm_fix_edge", "Moving Mesh: fix edge boundary nodes", &_p->fix_edge); phgOptionsRegisterNoArg("mm_fix_bdry", "Moving Mesh: fix all boundary nodes", &_p->fix_bdry); phgOptionsRegisterNoArg("mm_viz_move", "Moving Mesh: visualize nodes move", &_p->viz_move); phgOptionsRegisterString("mm_move_opts", "Moving Mesh Solver of moving options", &_p->move_opts); phgOptionsRegisterString("mm_dof_opts", "Moving Mesh Solver of dof updating options", &_p->dof_opts); _p->fix_edge |= _p->fix_bdry; return params; }
int main(int argc, char *argv[]) { MAT *A, *B; VEC *U = NULL, *x; FLOAT *C; SOLVER *solver, *solver1 = NULL; INT i, j, k, n, *pvt, N = 1000, K = 2; char *main_opts = NULL, *sub_opts = NULL; phgOptionsRegisterInt("-n", "N value", &N); phgOptionsRegisterInt("-k", "K value", &K); phgOptionsRegisterString("-main_solver_opts", "Options for the main solver", &main_opts); phgOptionsRegisterString("-sub_solver_opts", "Options for the subsolver", &sub_opts); /* a direct solver is preferable for the sparse matrix */ phgOptionsPreset("-solver mumps"); phgInit(&argc, &argv); phgPrintf( "----------------------------------------------------------------------------\n" "This code solves (A+UU^t)x=b using the Sherman-Morrison-Woodbury formula.\n" "Note: may use the following to disable use of the Sherman-Morrison-Woodbury\n" "algorithm and change to the default solver instead:\n" " -preonly_pc_type solver -preonly_pc_opts \"-solver_maxit 2000\"\n" "----------------------------------------------------------------------------\n" ); phgPrintf("Generating the linear system: N = %"dFMT", K = %"dFMT"\n", N, K); /* A is a distributed NxN SPD tridiagonal matrix (A = [-1, 2, -1]) */ n = N / phgNProcs + (phgRank < (N % phgNProcs) ? 1 : 0); A = phgMatCreate(phgComm, n, N); phgPrintf(" Generating matrix A.\n"); for (i = 0; i < n; i++) { /* diagonal */ phgMatAddEntry(A, i, i, 2.0); /* diagonal - 1 */ if (i > 0) phgMatAddEntry(A, i, i - 1, -1.0); else if (phgRank > 0) phgMatAddLGEntry(A, i, A->rmap->partition[phgRank] - 1, -1.0); /* diagonal + 1 */ if (i < n - 1) phgMatAddEntry(A, i, i + 1, -1.0); else if (phgRank < phgNProcs - 1) phgMatAddLGEntry(A, i, A->rmap->partition[phgRank] + n, -1.0); } phgMatAssemble(A); /* U is a K-component vector */ U = phgMapCreateVec(A->rmap, K); phgVecRandomize(U, 123); /* solver1 is the solver for A */ phgOptionsPush(); phgOptionsSetOptions(sub_opts); solver1 = phgMat2Solver(SOLVER_DEFAULT, A); phgOptionsPop(); /* x is a scratch vector */ x = phgMapCreateVec(A->rmap, 1); /* C is a KxK dense matrix, pvt is an integer array, they store the LU * factorization of (I + U^t*inv(A)*U) */ phgPrintf(" Generating the dense matrix I+U^t*inv(A)*U.\n"); C = phgCalloc(K * K, sizeof(*C)); pvt = phgAlloc(K * sizeof(*pvt)); for (i = 0; i < K; i++) { for (j = 0; j < n; j++) { solver1->rhs->data[j] = U->data[i * n + j]; x->data[j] = 0.0; } solver1->rhs->assembled = TRUE; phgSolverVecSolve(solver1, FALSE, x); for (j = 0; j < K; j++) for (k = 0; k < n; k++) C[i * K + j] += U->data[j * n + k] * x->data[k]; } #if USE_MPI if (U->map->nprocs > 1) { FLOAT *tmp = phgAlloc(K * K * sizeof(*tmp)); MPI_Allreduce(C, tmp, K * K, PHG_MPI_FLOAT, MPI_SUM, U->map->comm); phgFree(C); C = tmp; } #endif /* USE_MPI */ for (i = 0; i < K; i++) C[i * K + i] += 1.0; phgPrintf(" Factorizing the dense matrix I+U^t*inv(A)*U.\n"); phgSolverDenseLU(K, C, pvt); /* B is a matrix-free matrix representing A + U*U^t, B->mv_data is used * to pass A, U, solver1, C and pvt to callback functions */ B = phgMapCreateMatrixFreeMat(A->rmap, A->cmap, funcB, /* arguments carried over to CB functions */ A, U, solver1, C, pvt, NULL); /* solver is a PreOnly solver for B whose pc_proc is set to sherman(). * * Note: can also use pcg, gmres, or petsc for this solver, in this case * the solution obtained with the Sherman-Morisson formula is iteratively * refined. */ phgOptionsPush(); phgOptionsSetOptions("-solver preonly"); phgOptionsSetOptions(main_opts); solver = phgMat2Solver(SOLVER_DEFAULT, B); phgSolverSetPC(solver, solver, sherman); phgOptionsPop(); for (i = 0; i < n; i++) x->data[i] = 1.0; phgMatVec(MAT_OP_N, 1.0, B, x, 0.0, &solver->rhs); phgPrintf("Solving the linear system.\n"); /* reset initial solution to zero */ memset(x->data, 0, n * sizeof(*x->data)); phgSolverVecSolve(solver, TRUE, x); for (i = 0; i < n; i++) solver->rhs->data[i] = 1.0; phgVecAXPBY(-1.0, solver->rhs, 1.0, &x); phgPrintf("Checking the result: |x - x_exact| / |x_exact| = %lg\n", (double)phgVecNorm2(x, 0, NULL) / sqrt((double)N)); phgSolverDestroy(&solver); phgSolverDestroy(&solver1); phgMatDestroy(&A); phgMatDestroy(&B); phgVecDestroy(&U); phgVecDestroy(&x); phgFree(C); phgFree(pvt); phgFinalize(); return 0; }
int main(int argc, char *argv[]) { ELEMENT *e; GRID *g; DOF *u, *v, *u_hp, *v_hp; HP_TYPE *hp; MAP *map; char *fn = "cube.dat"; char *dof_u = "P2", *dof_v = "P1"; INT step = 0, pre_refines = 0; phgOptionsRegisterFilename("-mesh_file", "Mesh file", &fn); phgOptionsRegisterInt("-pre_refines", "Pre-refinements", &pre_refines); phgOptionsRegisterString("-dof_u", "DOF type for u", &dof_u); phgOptionsRegisterString("-dof_v", "DOF type for v", &dof_v); phgInit(&argc, &argv); g = phgNewGrid(-1); if (!phgImport(g, fn, FALSE)) phgError(1, "can't read file \"%s\".\n", fn); phgRefineAllElements(g, pre_refines); phgOptionsSetHandler("-dof_type", dof_u); u = phgDofNew(g, DOF_DEFAULT, 1, "u", DofInterpolation); phgOptionsSetHandler("-dof_type", dof_v); v = phgDofNew(g, DOF_DEFAULT, 1, "v", DofInterpolation); phgPrintf("u->type = %s, v->type = %s\n", u->type->name, v->type->name); hp = phgHPNew(g, HP_HB); u_hp = phgHPDofNew(g, hp, 1, "u_hp", DofInterpolation); phgHPFree(&hp); hp = phgHPNew(g, HP_HC); v_hp = phgHPDofNew(g, hp, 1, "v_hp", DofInterpolation); phgHPFree(&hp); while (TRUE) { if (phgBalanceGrid(g, 1.1, 1, NULL, 0.)) phgPrintf("Repartition mesh, %d submeshes, load imbalance: %lg\n", g->nprocs, (double)g->lif); phgPrintf("Testing map with non HP DOFs:\n"); map = phgMapCreate(u, v, NULL); phgPrintf(" nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal); phgMapDestroy(&map); phgPrintf("Testing map with HP DOFs:\n"); ForAllElements(g, e) e->hp_order = 1 + GlobalElement(g, e->index) % 4; phgHPSetup(u_hp->hp, FALSE); ForAllElements(g, e) e->hp_order = 1 + (3 - GlobalElement(g, e->index) % 4); phgHPSetup(v_hp->hp, FALSE); map = phgMapCreate(u_hp, v_hp, NULL); phgPrintf(" nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal); phgMapDestroy(&map); phgPrintf("Testing map with HP and non HP DOFs:\n"); map = phgMapCreate(u, u_hp, v, v_hp, NULL); phgPrintf(" nlocal = %d, nglobal = %d\n", map->nlocal, map->nglobal); phgMapDestroy(&map); if (++step >= 1) break; phgRefineAllElements(g, 1); } phgDofFree(&u_hp); phgDofFree(&v_hp); phgDofFree(&u); phgDofFree(&v); phgFreeGrid(&g); phgFinalize(); return 0; }