Beispiel #1
0
static void
build_linear_system(SOLVER *solver, DOF *u_h, DOF *f_h)
{
    int i, j;
    GRID *g = u_h->g;
    ELEMENT *e;

    assert(u_h->dim == 1);
    ForAllElements(g, e) {
        int N = DofGetNBas(u_h, e);	/* number of bases in the element */
        FLOAT A[N][N], rhs[N], buffer[N];
        INT I[N];

        /* compute \int \grad\phi_j \cdot \grad\phi_i making use of symmetry */
        for (i = 0; i < N; i++) {
            I[i] = phgSolverMapE2L(solver, 0, e, i);
            for (j = 0; j <= i; j++) {
                A[j][i] = A[i][j] =
                              /* stiffness */
                              phgQuadGradBasDotGradBas(e, u_h, j, u_h, i, QUAD_DEFAULT) +
                              /* mass */
                              a * phgQuadBasDotBas(e, u_h, j, u_h, i, QUAD_DEFAULT);
            }
        }

        /* loop on basis functions */
        for (i = 0; i < N; i++) {
            if (phgDofDirichletBC(u_h, e, i, func_u, buffer, rhs+i,
                                  DOF_PROJ_NONE)) {
                phgSolverAddMatrixEntries(solver, 1, I + i, N, I, buffer);
            }
            else {	/* interior node */
                /* right hand side = \int f * phi_i */
                phgQuadDofTimesBas(e, f_h, u_h, i, QUAD_DEFAULT, rhs + i);
                phgSolverAddMatrixEntries(solver, 1, I + i, N, I, A[i]);
            }
        }
        phgSolverAddRHSEntries(solver, N, I, rhs);
    }
/****************************************************************
 * Build RHS which is the residual of the nonlinear system.
 ***************************************************************/
static void
build_rhs(SOLVER *solver, SOLVER *pc, DOF **dofs, MAT **mats)
{
    DOF *u = dofs[0], *p = dofs[1];
    DOF *f, *pbc, *gn[3], *gradu, *divu, *lapu, *gradp, *f0;
    int M = u->type->nbas;	/* num of bases of Velocity */
    int i, k, s;
    GRID *g = u->g;
    ELEMENT *e;
    FLOAT bufu[M], resu[M][Dim], tmp[9];
    INT Iu[M][Dim];

    /* Unpack Dofs */
    unpackDof(dofs, 9, &u, &p, &gradu, &divu, &f, &pbc, &gn[0], &gn[1],
	      &gn[2]);
    lapu = phgDofDivergence(gradu, NULL, NULL, NULL);
    gradp = phgDofGradient(p, NULL, NULL, NULL);
    time -= dt;
    f0 = phgDofNew(g, DOF_HB6, 3, "p_n", func_f);
    time += dt;

    ForAllElements(g, e) {
	/* Map: Element -> system */
	for (i = 0; i < M; i++)
	    for (k = 0; k < Dim; k++)
		Iu[i][k] = phgMapE2L(solver->rhs->map, 0, e, i * Dim + k);

	/* Global Matrix */
	bzero(resu, sizeof(resu));
	for (i = 0; i < M; i++) {
	    /* Dirichle Boundary for velocity. */
	    if (phgDofDirichletBC(u, e, i, func_u, bufu, &resu[i][0],
				  DOF_PROJ_NONE)) {
		/* set velocity at Dirichlet bdry */
	    }
	    else {		/* interior node or Neumann */
		/* (u(t_n), \phi) */
		phgQuadDofTimesBas(e, u, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] = tmp[k];

		/* (f, \phi_i) */
		phgQuadDofTimesBas(e, f0, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += dt * (1 - Theta) * tmp[k];

		phgQuadDofTimesBas(e, f, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += dt * Theta * tmp[k];

		/* -( ((u.\grad) u, \phi) */
		phgQuadDofDotGradDofBas(e, u, gradu, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] -= dt * (1 - Theta) * tmp[k];

		/* +\nu ( lap(u(t_n)), \phi) */
		phgQuadDofTimesBas(e, lapu, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] += (1 - Theta) * dt * nu * tmp[k];

		/* -(gradp(t_n), \phi) */
		phgQuadDofTimesBas(e, gradp, u, i, QUAD_DEFAULT, tmp);
		for (k = 0; k < Dim; k++)
		    resu[i][k] -= (1 - Theta) * dt * tmp[k];
	    }
	}			/* end of Block (1,1), (1,2) */

	/* Neumann Bdry */
	for (s = 0; s < NFace; s++) {
	    if (e->bound_type[s] & NEUMANN) {
		SHORT bases[NbasFace(u)];
		phgDofGetBasesOnFace(u, e, s, bases);

		for (i = 0; i < NbasFace(u); i++) {
		    if (phgDofGetElementBoundaryType(u, e, bases[i] * Dim)
								& DIRICHLET) {
			/* Dirichlet bas on Neumann face, do nothing */
		    }
		    else if (phgDofGetElementBoundaryType(u, e, bases[i] * Dim)
								& NEUMANN) {
			for (k = 0; k < Dim; k++)
			    resu[bases[i]][k] += dt * Theta *
				phgQuadFaceDofDotBas(e, s, gn[k],
						     DOF_PROJ_DOT, u,
						     bases[i], QUAD_DEFAULT);
		    }
		    else {
			fprintf(stderr, "Warning: unkown bdry!");
		    }
		}		/* end of base on face */
	    }			/* end of face neu */
	}			/* end of all neumann face in element */

	/* Global res */
	phgSolverAddRHSEntries(solver, M * Dim, Iu[0], &resu[0][0]);
    }				/* end element */

    solver->rhs_updated = FALSE;
    phgDofFree(&lapu);
    phgDofFree(&gradp);
    phgDofFree(&f0);
    return;
}
Beispiel #3
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]);
    }