示例#1
0
static void
getMoveDirection(MovingMesh *mmesh)
{
    GRID *g = _m->g;
    SIMPLEX *e;
    DOF *logical_move = _m->logical_move;
    DOF *logical_node = _m->logical_node;
    DOF *move = _m->move;
    DOF *logical_node_new, *grad_logical_node;
    INT i, j, k, l0, l1;
    SOLVER *solver;
    DOF *mass_lumping;
    FLOAT *v_move, *v_mass;
    FLOAT max_vol = -1e10, min_vol = 1e10;

    /* Get new monitor */
    _m->get_monitor(mmesh); DOF_SCALE(_m->monitor);

    logical_node_new = phgDofCopy(logical_node, NULL, NULL, "new logical node coordinates");
    grad_logical_node = phgDofGradient(logical_node, NULL, NULL, "grad logical node coordinates");
    /* if (logical_node_new->DB_mask == UNDEFINED) */
    /* 	phgError(1, "g->types_vert and DB_mask is VAILD in moving mesh method!!!"); */
    
    /* Create move solver */
    phgOptionsPush();
#if 0
    phgOptionsSetOptions("-default_solver mm_ml "
			 "-mm_ml_solver gmres "
			 "-mm_ml_pc mm_ml "
			 "-mm_ml_sweep0 6 "
			 "-solver_maxit 100 "
			 "-solver_rtol 1e-12 ");
#else
    phgOptionsSetOptions("-default_solver hypre "
			 "-hypre_solver gmres "
			 "-hypre_pc boomeramg "
			 "-solver_maxit 100 "
			 "-solver_rtol 1e-12 ");
#endif
    phgOptionsSetOptions(_mp->move_opts);

    setMoveConstrain(mmesh, logical_node_new);
    solver = phgSolverCreate(SOLVER_DEFAULT, logical_node_new, NULL);
    solver->mat->mv_data = phgAlloc(sizeof(*solver->mat->mv_data));
    solver->mat->mv_data[0] = (void *) mmesh;
    phgOptionsPop();

    /* build mat */
    ForAllElements(g, e) {
	int order = 1, q;
	int N = DofGetNBas(logical_node, e);	/* number of bases in the element */
	FLOAT A[N][Dim][N][Dim], rhs[N][Dim];
	INT I[N][Dim];
	QUAD *quad;
	const FLOAT *w, *lambda;
	FLOAT vol, mon;
	
	vol = phgGeomGetVolume(g, e);
	max_vol = MAX(max_vol, vol); 	
	min_vol = MIN(min_vol, vol); 

	for (i = 0; i < N; i++)
	    for (k = 0; k < Dim; k++)
		I[i][k] = phgMapE2L(solver->rhs->map, 0, e, i * Dim + k);

	bzero(A, sizeof(A));
	bzero(rhs, sizeof(rhs));

	quad = phgQuadGetQuad3D(order);
	mon = *DofElementData(_m->monitor, e->index); 
	//printf("mon:%e\n", mon);

	lambda = quad->points;
	w = quad->weights;
	assert(quad->npoints == 1);
	for (q = 0; q < quad->npoints; q++) {
	    for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
		    const FLOAT *ggi = 
			phgQuadGetBasisGradient(e, _m->move, i, quad) + q*Dim; /* grad phi_i */
		    const FLOAT *ggj = 
			phgQuadGetBasisGradient(e, _m->move, j, quad) + q*Dim; /* grad phi_j */
		    FLOAT a = vol*(*w) * mon * INNER_PRODUCT(ggj, ggi);
			
		    for (k = 0; k < Dim; k++) {
			A[i][k][j][k] += a;
		    }
		}
	    }
	    w++; lambda += Dim + 1;
	} /* end quad point */

	for (i = 0; i < N; i++) {
	    INT vert0 = e->verts[i];
	    if (_mp->fix_bdry || MM_FIXED(g->types_vert[vert0])) {
		/* no move */
		bzero(A[i], sizeof(A[i]));

		for (k = 0; k < Dim; k++) {
		    A[i][k][i][k] = 1.;
		    rhs[i][k] = logical_node->data[vert0 * Dim + k];
		}
	    } else if (g->types_vert[vert0] & MM_CONSTR) {
		VERT_CONSTRAIN *vert_constr = _m->vert_constr + _m->vert_constr_index[vert0];
		FLOAT *trans = vert_constr->Trans;
		FLOAT *bb = vert_constr->bb;
		assert(_m->vert_constr_index[vert0] >= 0);
		assert(vert0 == vert_constr->index);

		trans_left_ (&A[i][0][0][0], Dim*N, Dim*N, trans);
		trans_right_(&A[0][0][i][0], Dim*N, Dim*N, trans);

		if (vert_constr->n_constrain == 2) {
		    bzero(A[i][0], sizeof(A[i][0]));
		    bzero(A[i][1], sizeof(A[i][1]));
		    A[i][0][i][0] = 1.;
		    A[i][1][i][1] = 1.;
		    rhs[i][0] = bb[0];
		    rhs[i][1] = bb[1];
		} else if (vert_constr->n_constrain == 1) {
		    bzero(A[i][0], sizeof(A[i][0]));
		    A[i][0][i][0] = 1.;
		    rhs[i][0] = bb[0];
		} else {
		    abort();
		}
	    }
	}

	for (i = 0; i < N; i++)
	    phgSolverAddMatrixEntries(solver, Dim, &I[i][0], N * Dim, I[0], &A[i][0][0][0]);
	phgSolverAddRHSEntries(solver, N * Dim, &I[0][0], &rhs[0][0]);
    }
示例#2
0
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;
}
示例#3
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;
}