Ejemplo n.º 1
0
void
Well_Pressure(DOF *p_h, DOF *b_o, FLOAT *pressure, FLOAT *pwf)
{
	GRID *g = p_h->g;
	SIMPLEX *e;
	FLOAT *p_p, sum_vol = 0, sum_lambda = 0, sum_pressure = 0, *p_bo;
	INT count = 0;

	FLOAT	mu = 1e-9 / 3600, K = 1e-13, rw = 0.1, re = 10.; 
	ForAllElements(g, e){
		if(e->region_mark == 1){
			p_p = DofElementData(p_h, e->index);
			p_bo = DofElementData(b_o, e->index);
			sum_pressure += p_p[0] * phgGeomGetVolume(g, e);
			sum_lambda += p_bo[0] * phgGeomGetVolume(g, e); 
			sum_vol += phgGeomGetVolume(g, e);
		}
	}

#if USE_MPI
	FLOAT sum_vol0 = sum_vol, sum_lambda0 = sum_lambda, sum_pressure0 = sum_pressure;
	MPI_Allreduce(&sum_vol0, &sum_vol, 1, MPI_DOUBLE, MPI_SUM, g->comm);
	MPI_Allreduce(&sum_lambda0, &sum_lambda, 1, MPI_DOUBLE, MPI_SUM, g->comm);
	MPI_Allreduce(&sum_pressure0, &sum_pressure, 1, MPI_DOUBLE, MPI_SUM, g->comm);
#endif
	*pressure = sum_pressure / sum_vol;
	sum_lambda = sum_lambda / sum_vol;
    FLOAT tmp  = (-PRODUCTION * mu * sum_lambda * (log(re/rw) + 3 - 0.5)) / (2 * M_PI * K * MESH_HEIGHT); 
    *pwf = *pressure + tmp;
}
Ejemplo n.º 2
0
void
Well_init(DOF *source)
{
	GRID *g = source->g;
	SIMPLEX *e;
	FLOAT *p_source;
	FLOAT vol_1 = 0, vol_2 =0;
	ForAllElements(g, e){
		if(e->region_mark == 2){
			vol_1 += phgGeomGetVolume(g, e);
		}
		else if(e->region_mark == 3)
		{
			vol_2 += phgGeomGetVolume(g, e);
		}
	}
#if USE_MPI
	FLOAT vol_10 = vol_1;
	FLOAT vol_20 = vol_2;
//	memcpy(vol0, vol, sizeof(FLOAT));
	MPI_Allreduce(&vol_10, &vol_1, 1, MPI_DOUBLE, MPI_SUM, g->comm);
	MPI_Allreduce(&vol_20, &vol_2, 1, MPI_DOUBLE, MPI_SUM, g->comm);
#endif
	ForAllElements(g, e){
		if(e->region_mark == 2){
			p_source = DofElementData(source, e->index);
			p_source[0] = - PRODUCTION / (vol_1+vol_2);
		}
		else if(e->region_mark == 3){
			p_source = DofElementData(source, e->index);
			p_source[0] = - PRODUCTION / (vol_2+vol_1);
		}
	}
}
/* *******************************************************
 * ( (u.\grad) phi_j, phi_i )
 * return 1 value
 *  */
FLOAT
phgQuadDofDotGradBasBas(ELEMENT *e, DOF *u, DOF *v, int m, int n, int order)
{
    int i;
    const FLOAT *g1, *g2, *gu, *w, *lambda;
    FLOAT d, d0;
    QUAD *quad;

    assert(u->dim == 3);

    if (order < 0)
	order = DofTypeOrder(u, e) +
	      BasisOrder(v, e, m) - 1 + BasisOrder(v, e, n);
    if (order < 0)
	order = 0;
    quad = phgQuadGetQuad3D(order);

    gu = phgQuadGetDofValues(e, u, quad);
    g1 = phgQuadGetBasisGradient(e, v, m, quad);
    g2 = phgQuadGetBasisValues(e, v, n, quad);
    d = 0.;
    lambda = quad->points;
    w = quad->weights;
    for (i = 0; i < quad->npoints; i++) {
	d0 = 0.;
	d0 += (*(gu++)) * (*(g1++)) * (*(g2));	/* u dphi_m/dx phi_n */
	d0 += (*(gu++)) * (*(g1++)) * (*(g2));	/* v dphi_m/dy phi_n */
	d0 += (*(gu++)) * (*(g1++)) * (*(g2));	/* w dphi_m/dz phi_n */
	g2++;
	d += d0 * (*(w++));
	lambda += Dim + 1;
    }

    return d * phgGeomGetVolume(u->g, e);
}
/* **********************
 * \grad phi_j \times \phi_i
 * return 3 values
 *  */
void
phgQuadGradBasDotBas3(ELEMENT *e, DOF *s, int m, DOF *v, int n,
		      FLOAT *values, int order)
{
    int i, j, nvalues = DofTypeDim(v);
    const FLOAT *g1, *g2, *w, *lambda;
    FLOAT d1, d2, d3, dd1, dd2, dd3;
    QUAD *quad;

    assert(!SpecialDofType(s->type) && !SpecialDofType(v->type));

    if (nvalues != DofTypeDim(s))
	phgError(1, "%s:%d, dimensions mismatch: grad(%s) <==> (%s)\n",
		 __FILE__, __LINE__, s->name, v->name);

    if (order < 0)
	order = BasisOrder(s, e, m) - 1 + BasisOrder(v, e, n);
    if (order < 0)
	order = 0;
    quad = phgQuadGetQuad3D(order);

    g1 = phgQuadGetBasisGradient(e, s, m, quad);
    g2 = phgQuadGetBasisValues(e, v, n, quad);
    dd1 = 0.;
    dd2 = 0.;
    dd3 = 0.;
    lambda = quad->points;
    w = quad->weights;
    for (i = 0; i < quad->npoints; i++) {
	d1 = d2 = d3 = 0.;
	for (j = 0; j < nvalues; j++) {
	    d1 += *(g1++) * *g2;
	    d2 += *(g1++) * *g2;
	    d3 += *(g1++) * *g2;
	    g2++;
	}
	dd1 += d1 * *w;
	dd2 += d2 * *w;
	dd3 += d3 * *w;
	w++;
	lambda += Dim + 1;
    }
    values[0] = dd1 * phgGeomGetVolume(s->g, e);
    values[1] = dd2 * phgGeomGetVolume(s->g, e);
    values[2] = dd3 * phgGeomGetVolume(s->g, e);
    return;
}
/* ***************************
 * ( (u.\grad) u, phi_i )
 * return 3 values.
 *  */
void
phgQuadDofDotGradDofBas(ELEMENT *e, DOF *u, DOF *gradu,
			int n, int order, FLOAT *values)
{
    int i;
    const FLOAT *g2, *gu, *ggu, *w, *lambda;
    FLOAT d1, d2, d3, dd1, dd2, dd3, vol;
    QUAD *quad;

    assert(gradu->dim == 9 && u->dim == 3);

    if (order < 0)
	order = DofTypeOrder(u, e) +
	       DofTypeOrder(gradu, e) + BasisOrder(u, e, n);
    if (order < 0)
	order = 0;
    quad = phgQuadGetQuad3D(order);

    gu = phgQuadGetDofValues(e, u, quad);
    ggu = phgQuadGetDofValues(e, gradu, quad);
    g2 = phgQuadGetBasisValues(e, u, n, quad);
    dd1 = dd2 = dd3 = 0.;
    lambda = quad->points;
    w = quad->weights;
    for (i = 0; i < quad->npoints; i++) {
	d1 = d2 = d3 = 0.;

	d1 += *(gu) * (*(ggu++)) * (*(g2));	/* u du/dx phi_n */
	d1 += *(gu + 1) * (*(ggu++)) * (*(g2));	/* v du/dy phi_n */
	d1 += *(gu + 2) * (*(ggu++)) * (*(g2));	/* w du/dz phi_n */

	d2 += *(gu) * (*(ggu++)) * (*(g2));	/* u dv/dx phi_n */
	d2 += *(gu + 1) * (*(ggu++)) * (*(g2));	/* v dv/dy phi_n */
	d2 += *(gu + 2) * (*(ggu++)) * (*(g2));	/* w dv/dz phi_n */

	d3 += *(gu) * (*(ggu++)) * (*(g2));	/* u dw/dx phi_n */
	d3 += *(gu + 1) * (*(ggu++)) * (*(g2));	/* v dw/dy phi_n */
	d3 += *(gu + 2) * (*(ggu++)) * (*(g2));	/* w dw/dz phi_n */

	dd1 += d1 * (*w);
	dd2 += d2 * (*w);
	dd3 += d3 * (*w);

	gu += 3;
	g2++;
	w++;
	lambda += Dim + 1;
    }

    vol = phgGeomGetVolume(u->g, e);
    values[0] = dd1 * vol;
    values[1] = dd2 * vol;
    values[2] = dd3 * vol;
    return;
}
Ejemplo n.º 6
0
static void
stiffness_matrix(ELEMENT *e, DOF *u, int m, int n, FLOAT E, FLOAT nu,
		 int lda, FLOAT *pA, QUAD *quad)
/* returns in 'A' the contribution of the m-th and n-th basis functions
 * to the element stiffness matrix. Elements of the 3x3 small matrix are
 * stored at A[j * lda + k] (j,k = 0,1,2) */
{
    int i;
    FLOAT (*A)[lda] = (void *)pA;
    const FLOAT *pm, *pn, *w;
    FLOAT a00, a01, a02, a10, a11, a12, a20, a21, a22;
    FLOAT a = nu / (1.0 - nu);
    FLOAT b = (1. - 2. * nu) / (2. * (1. - nu));
    FLOAT c = E * (1. - nu) / ((1. + nu) * (1. - 2. * nu)) *
		phgGeomGetVolume(u->g, e);
 
    pm = phgQuadGetBasisGradient(e, u, m, quad);
    pn = phgQuadGetBasisGradient(e, u, n, quad);
    w = quad->weights;

    a00 = a01 = a02 = a10 = a11 = a12 = a20 = a21 = a22 = 0.;
    for (i = 0; i < quad->npoints; i++) {
	a00 += (pm[0] * pn[0] + b * (pm[1] * pn[1] + pm[2] * pn[2])) * *w;
	a01 += (a * pm[0] * pn[1] + b * pm[1] * pn[0]) * *w;
	a02 += (a * pm[0] * pn[2] + b * pm[2] * pn[0]) * *w;

	a10 += (a * pm[1] * pn[0] + b * pm[0] * pn[1]) * *w;
	a11 += (pm[1] * pn[1] + b * (pm[0] * pn[0] + pm[2] * pn[2])) * *w;
	a12 += (a * pm[1] * pn[2] + b * pm[2] * pn[1]) * *w;

	a20 += (a * pm[2] * pn[0] + b * pm[0] * pn[2]) * *w;
	a21 += (a * pm[2] * pn[1] + b * pm[1] * pn[2]) * *w;
	a22 += (pm[2] * pn[2] + b * (pm[0] * pn[0] + pm[1] * pn[1])) * *w;
	pn += 3;
	pm += 3;
	w++;
    }

    A[0][0] = a00 * c;
    A[0][1] = a01 * c;
    A[0][2] = a02 * c;

    A[1][0] = a10 * c;
    A[1][1] = a11 * c;
    A[1][2] = a12 * c;

    A[2][0] = a20 * c;
    A[2][1] = a21 * c;
    A[2][2] = a22 * c;

/*printf("a%d%d=[%lg %lg %lg; %lg %lg %lg; %lg %lg %lg];\n", m, n, a00*c, a01*c, a02*c, a10*c, a11*c, a12*c, a20*c, a21*c, a22*c);*/

    return;
}
/* *****************************
 * (grad(u_3), grad(\phi))
 * return 3 values.
 * */
void
phgQuadGradDof3GradBas(ELEMENT *e, DOF *gradu, DOF *u, int m, int order,
		       FLOAT *values)
{
    int i;
    const FLOAT *g2, *gu, *w, *lambda;
    FLOAT d1, d2, d3, dd1, dd2, dd3, vol;
    QUAD *quad;

    assert(gradu->dim == 9 && u->dim == 3);

    if (order < 0)
	order = 2 * BasisOrder(u, e, m) - 1;
    if (order < 0)
	order = 0;
    quad = phgQuadGetQuad3D(order);

    gu = phgQuadGetDofValues(e, gradu, quad);
    g2 = phgQuadGetBasisGradient(e, u, m, quad);
    dd1 = dd2 = dd3 = 0.;
    lambda = quad->points;
    w = quad->weights;
    for (i = 0; i < quad->npoints; i++) {
	d1 = d2 = d3 = 0.;

	d1 += (*(gu++)) * (*(g2));
	d1 += (*(gu++)) * (*(g2 + 1));
	d1 += (*(gu++)) * (*(g2 + 2));

	d2 += (*(gu++)) * (*(g2));
	d2 += (*(gu++)) * (*(g2 + 1));
	d2 += (*(gu++)) * (*(g2 + 2));

	d3 += (*(gu++)) * (*(g2));
	d3 += (*(gu++)) * (*(g2 + 1));
	d3 += (*(gu++)) * (*(g2 + 2));

	dd1 += d1 * (*w);
	dd2 += d2 * (*w);
	dd3 += d3 * (*w);

	g2 += 3;
	w++;
	lambda += Dim + 1;
    }

    vol = phgGeomGetVolume(u->g, e);
    values[0] = dd1 * vol;
    values[1] = dd2 * vol;
    values[2] = dd3 * vol;
    return;
}
/* ****************************************
 * ( d[uvw]/d[xyz]*phi_j, phi_i )
 * return static float[9] managed by user.
 *  */
void
phgQuadGradDofBasDotBas(ELEMENT *e, DOF *gradu, DOF *u, int m, int n,
			int order, FLOAT *value)
{
    int i;
    const FLOAT *g1, *g2, *gu, *w, *lambda;
    FLOAT d[9], *pd, vol;
    QUAD *quad;

    assert(gradu->dim == 9 && u->dim == 3);

    if (order < 0)
	order = DofTypeOrder(gradu, e) +
	       BasisOrder(u, e, m) + BasisOrder(u, e, n) ;
    if (order < 0)
	order = 0;
    quad = phgQuadGetQuad3D(order);

    gu = phgQuadGetDofValues(e, gradu, quad);
    g1 = phgQuadGetBasisValues(e, u, m, quad);
    g2 = phgQuadGetBasisValues(e, u, n, quad);
    lambda = quad->points;
    w = quad->weights;
    for (i = 0; i < 9; i++)
	d[i] = 0;
    for (i = 0; i < quad->npoints; i++) {
	pd = d;
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* du/dx phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* du/dy phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* du/dz phi_m phi_n */

	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dv/dx phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dv/dy phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dv/dz phi_m phi_n */

	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dw/dx phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dw/dy phi_m phi_n */
	(*pd++) += (*(gu++)) * (*g1) * (*g2) * (*w);	/* dw/dz phi_m phi_n */

	g1++;
	g2++;
	w++;
	lambda += Dim + 1;
    }

    vol = phgGeomGetVolume(u->g, e);
    for (i = 0; i < 9; i++)
	value[i] = d[i] * vol;

    return;
}
Ejemplo n.º 9
0
void
Well_init(DOF *source)
{
	GRID *g = source->g;
	SIMPLEX *e;
	FLOAT *p_source;
	FLOAT vol = 0;
	ForAllElements(g, e){
		if(e->region_mark == 1){
			vol += phgGeomGetVolume(g, e);
		}
	}
#if USE_MPI
	FLOAT vol0 = vol;
	MPI_Allreduce(&vol0, &vol, 1, MPI_DOUBLE, MPI_SUM, g->comm);
#endif
	ForAllElements(g, e){
		if(e->region_mark == 1){
			p_source = DofElementData(source, e->index);
			p_source[0] = - PRODUCTION / vol;
		}
	}
}
Ejemplo n.º 10
0
/* ***********************
 * p \times \grad \phi_m
 * return 3 values.
 * */
void
phgQuadDofAGradBas3(ELEMENT *e, DOF *p, DOF *v, int m, int order, FLOAT *values)
{
    int i, j;
    const FLOAT *g1, *g2, *w;
    FLOAT d1, d2, d3, vol;
    QUAD *quad;

    assert(!SpecialDofType(v->type));
    assert(p->dim == 1);

    if (order < 0) {
	order = ((j = DofTypeOrder(p, e)) >= 0 ? j : BasisOrder(v, e, m));
	order += BasisOrder(v, e, m) - 1;
    }
    quad = phgQuadGetQuad3D(order);

    g1 = phgQuadGetDofValues(e, p, quad);
    g2 = phgQuadGetBasisGradient(e, v, m, quad);
    w = quad->weights;

    d1 = d2 = d3 = 0.;
    for (i = 0; i < quad->npoints; i++) {
	d1 += *(g1) * (*g2++) * (*w);
	d2 += *(g1) * (*g2++) * (*w);
	d3 += *(g1) * (*g2++) * (*w);
	g1++;
	w++;
    }

    vol = phgGeomGetVolume(p->g, e);
    values[0] = d1 * vol;
    values[1] = d2 * vol;
    values[2] = d3 * vol;
    return;
}
Ejemplo n.º 11
0
static void
build_matrices(MAT *ma, MAT *mb, VEC *rhs_vec, DOF *u_h, DOF *f)
/* build stiffness (ma) and mass (mb) matrices */
{
    int N = u_h->type->nbas;	/* number of element basis functions */
    int i, j, k, l;
    GRID *g = u_h->g;
    ELEMENT *e;
    FLOAT A[N][3][N][3], buffer[N], rhs[N][3], d;
    static FLOAT *B0 = NULL;
    FLOAT B[N][N];
    INT I[N][3], J[3][N];
    QUAD *quad = phgQuadGetQuad3D((u_h->type->order - 1) * 2);

    assert(u_h->type->dim == 1 && u_h->dim == 3);
    assert(mb == NULL || u_h->type->invariant);

    if (mb != NULL && B0 == NULL && g->nroot > 0) {
	/* (\int \phi_j\cdot\phi_i)/vol is independent of element */
	FreeAtExit(B0);
	B0 = phgAlloc(N * N * sizeof(*B0));
	e = g->roots;
	d = 1. / phgGeomGetVolume(g, e);
	for (i = 0; i < N; i++)
	    for (j = 0; j <= i; j++)
		B0[i * N + j] = B0[i + j * N] = d *
		    phgQuadBasDotBas(e, u_h, j, u_h, i, QUAD_DEFAULT);
    }

    ForAllElements(g, e) {
	d = phgGeomGetVolume(g, e) * rho;
	for (i = 0; i < N; i++) {
	    for (k = 0; k < 3; k++)
		J[k][i] = I[i][k] = phgMapE2L(ma->rmap, 0, e, i * 3 + k);
	    for (j = 0; j <= i; j++) {
		/* the stiffness matrix */
		stiffness_matrix(e, u_h, i, j, E, nu, 3 * N, &A[i][0][j][0],
				 quad);
		if (j != i) {
		    for (k = 0; k < 3; k++)
			for (l = 0; l < 3; l++)
			    A[j][k][i][l] = A[i][l][j][k];
		}
		/* the mass matrix: \int \phi_i\cdot\phi_j */
		if (mb != NULL)
		    B[j][i] = B[i][j] = B0[i * N + j] * d;
	    }
	}
#if 0
/* print element stiffness matrix */
FLOAT *p = (void *)A;
printf("vol = %0.16lg;\n", phgGeomGetVolume(g, e));
printf("a = [\n");
for (i = 0; i < 3 * N; i++) {
 for (j = 0; j < 3 * N; j++) printf("%0.16lg ", p[i * 3 * N + j]); printf("\n");
}
printf("];\n");
printf("b = [\n");
for (i = 0; i < N; i++) for (k = 0; k < 3; k++) {
 for (j = 0; j < N; j++) for (l = 0; l < 3; l++)
  printf("%0.16lg ", l == k ? B[i][j] : 0.0);
 printf("\n");
}
printf("];\n");
exit(0);
#endif

	/* loop on basis functions */
	for (i = 0; i < N; i++) {
	    if (phgDofDirichletBC(u_h, e, i, func_g, buffer, rhs[i],
					DOF_PROJ_NONE)) {
		/* Dirichlet boundary */
		for (k = 0; k < 3; k++) {
		    phgMatAddEntries(ma, 1, I[i] + k, N, J[k], buffer);
		    if (mb != NULL)
			phgMatAddEntries(mb, 1, I[i] + k, N, J[k], buffer);
		}
	    }
	    else {
		/* interior node */
		phgMatAddEntries(ma, 3, I[i], 3 * N, I[0], &A[i][0][0][0]);
		if (mb == NULL) {
		    phgQuadDofTimesBas(e, f, u_h, i, QUAD_DEFAULT, rhs[i]);
		    for (k = 0; k < 3; k++)
			rhs[i][k] = -rhs[i][k];
		}
		else {
		    for (k = 0; k < 3; k++)
			phgMatAddEntries(mb, 1, I[i] + k, N, J[k], B[i]);
		}
	    }
	}
	if (rhs_vec != NULL)
	    phgVecAddEntries(rhs_vec, 0, N * 3, I[0], rhs[0]);
    }
Ejemplo n.º 12
0
DOF *
phgDofCopy_(DOF *src, DOF **dest_ptr, DOF_TYPE *newtype,
	    const char *name, const char *srcfile, int srcline)
/* returns a new DOF whose type is 'newtype', and whose values are evaluated
 * using 'src' (a copy of src). */
{
    GRID *g = src->g;
    SIMPLEX *e;
    FLOAT w = 1.0, *basvalues = NULL, *a, *d, *buffer = NULL;
    int i, k, dim, dim_new, count = 0, nvalues, nd;
    INT n;
    DOF *wgts = NULL;
    DOF *dest = (dest_ptr == NULL ? NULL : *dest_ptr);
    BYTE *flags0, *flags;
    char *auto_name;
    DOF_TYPE *oldtype;
    BOOLEAN basflag = FALSE;

    MagicCheck(DOF, dest)

    if (dest != NULL && newtype != NULL && dest->type != newtype) {
	phgDofFree(&dest);
	dest = NULL;
    }

    dim = DofDim(src);
    /* the name of dest */
    if ((auto_name = (void *)name) == NULL) {
#if 0
	auto_name = phgAlloc(strlen(src->name) + 8 + 1);
	sprintf(auto_name, "copy of %s", src->name);
#else
	auto_name = strdup(src->name);
#endif
    }

    if (dest == NULL) {
	if (newtype == NULL)
	    newtype = src->type;
	dim_new = (newtype == NULL ? DofTypeDim(src) : newtype->dim);
	assert(dim % dim_new == 0);
	dest = phgDofNew_(g, newtype, newtype == NULL ? src->hp : NULL,
			  dim / dim_new, auto_name, DofNoAction,
			  srcfile, srcline);
	if (dest_ptr != NULL)
	    *dest_ptr = dest;
    }
    else {
	assert(dim == DofDim(dest));
	phgFree(dest->name); dest->name = strdup(auto_name);
	dest->srcfile = srcfile;
	dest->srcline = srcline;
	phgFree(dest->cache_func); dest->cache_func = NULL;
	newtype = dest->type;
	if (!SpecialDofType(newtype))
	    memset(dest->data, 0, DofGetDataCount(dest) * sizeof(*dest->data));
    }
    if (auto_name != name)
	phgFree(auto_name);

    phgDofClearCache(NULL, dest, NULL, NULL, FALSE);

    dest->DB_mask = src->DB_mask;
    if (src->DB_masks != NULL) {
	if (dest->DB_masks == NULL)
	    dest->DB_masks = phgAlloc(dest->dim * sizeof(*dest->DB_masks));
	memcpy(dest->DB_masks, src->DB_masks, dest->dim * sizeof(*dest->DB_masks));
    }
    dest->invariant = src->invariant;

    if (SpecialDofType(newtype)) {
	assert(newtype == src->type);
	dest->userfunc = src->userfunc;
	dest->userfunc_lambda = src->userfunc_lambda;
	if (newtype == DOF_CONSTANT)
	    memcpy(dest->data, src->data, dim * sizeof(*dest->data));
	return dest;
    }

    if ((newtype != NULL && newtype == src->type) ||
	(newtype == NULL && src->hp == dest->hp)) {
	/* simply duplicate the data */
	size_t size = DofGetDataCount(dest);
	if (size > 0)
	    memcpy(dest->data, src->data, sizeof(FLOAT) * size);
	dest->userfunc = src->userfunc;
	dest->userfunc_lambda = src->userfunc_lambda;
	return dest;
    }

    if (src->type == DOF_ANALYTIC) {
	if (src->userfunc_lambda != NULL)
	    phgDofSetDataByLambdaFunction(dest, src->userfunc_lambda);
	else
	    phgDofSetDataByFunction(dest, src->userfunc);
	return dest;
    }

    if (newtype != NULL && newtype->BasFuncs == NULL)
	phgError(1, "phgDofCopy: basis funcs for DOF type \"%s\" undefined.\n",
		 newtype->name);

    dest->userfunc = src->userfunc;
    dest->userfunc_lambda = src->userfunc_lambda;

    oldtype = src->type;
    if (oldtype == NULL)
	oldtype = src->hp->info->types[src->hp->info->min_order];

    if (!SpecialDofType(oldtype) && newtype != NULL && newtype->points != NULL
	&& !DofIsHP(src)) {
	basflag = TRUE;
	count = oldtype->nbas * oldtype->dim;
	basvalues = phgAlloc(newtype->nbas * count * sizeof(*basvalues));

	if (oldtype->invariant == TRUE)
	    get_bas_funcs(src, dest, src->g->roots, basvalues);
    }

    if (newtype == NULL)
	newtype = dest->hp->info->types[dest->hp->max_order];

    flags0 = phgCalloc((newtype->np_vert > 0 ? g->nvert : 0)
		       + (newtype->np_edge > 0 ? g->nedge : 0)
		       + (newtype->np_face > 0 ? g->nface : 0),
		       sizeof(*flags0));

    if (!SpecialDofType(oldtype) && oldtype->continuity < 0) {
	static DOF_TYPE DOF_WGTS = {DofCache,
	    "Weights", NULL, NULL, NULL, NULL, NULL, NULL, NULL,
	    phgDofInitFuncPoint, NULL, NULL, NULL, FE_None,
	    FALSE, FALSE, -1, 0, 0, -1, 1, 0, 0, 0, 0
	};
	DOF_WGTS.np_vert = (newtype->np_vert > 0) ? 1 : 0;
	DOF_WGTS.np_edge = (newtype->np_edge > 0) ? 1 : 0;
	DOF_WGTS.np_face = (newtype->np_face > 0) ? 1 : 0;
	DOF_WGTS.nbas = DOF_WGTS.np_vert * NVert + DOF_WGTS.np_edge * NEdge +
	    DOF_WGTS.np_face * NFace;
	if (DOF_WGTS.nbas > 0) {
	    /* Other cases will be implemented later when really needed */
	    wgts = phgDofNew(g, &DOF_WGTS, 1, "weights", DofNoAction);
	    phgDofSetDataByValue(wgts, 0.0);
	    phgDofSetDataByValue(dest, 0.0);
	    /* allocate buffer for storing weighted vertex/edge/face data */
	    if ((n = DofGetDataCount(dest) - DofGetElementDataCount(dest)) > 0)
		buffer = phgCalloc(n, sizeof(*buffer));
	}
    }

    nvalues = dest->dim;
    cache_dof = src;
    bas_count = count;
    ForAllElements(g, e) {
	if (wgts != NULL) {
#if 0
	    /* use element volume as weight */
	    w = phgGeomGetVolume(g, e);
#else
	    /* use 1 as weight */
	    w = 1.0;
#endif
	}

	if (basflag && oldtype->invariant == FALSE)
	    get_bas_funcs(src, dest, e, basvalues);
	bas = basvalues;
	flags = flags0;

	if (DofIsHP(dest))
	    newtype = dest->hp->info->types[dest->hp->elem_order[e->index]];

	if (newtype->np_vert > 0) {
	    nd = nvalues * newtype->np_vert;
	    for (k = 0; k < NVert; k++) {
		if (flags[n = e->verts[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_vert;
		    continue;
		}
		flags[n] = TRUE;
		a = DofVertexData(dest, n);
		newtype->InitFunc(dest, e, VERTEX, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofVertexData(wgts, n) += w;
		}
	    }
	    flags += g->nvert;
	}

	if (newtype->np_edge > 0) {
	    nd = nvalues * newtype->np_edge;
	    for (k = 0; k < NEdge; k++) {
		if (flags[n = e->edges[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_edge;
		    continue;
		}
		flags[n] = TRUE;
		a = DofEdgeData(dest, n);
		newtype->InitFunc(dest, e, EDGE, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    if (DofIsHP(dest))
			nd = dest->dim * (dest->hp->edge_index[n + 1] -
					  dest->hp->edge_index[n]);
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofEdgeData(wgts, n) += w;
		}
	    }
	    flags += g->nedge;
	}

	if (newtype->np_face > 0) {
	    nd = nvalues * newtype->np_face;
	    for (k = 0; k < NFace; k++) {
		if (flags[n = e->faces[k]] && wgts == NULL) {
		    /* note: count==0 and bas==NULL for variable order DOF */
		    bas += count * newtype->np_face;
		    continue;
		}
		flags[n] = TRUE;
		a = DofFaceData(dest, n);
		newtype->InitFunc(dest, e, FACE, k, NULL, func, NULL, a,
					NULL);
		if (wgts != NULL) {
		    d = buffer + (a - DofData(dest));
		    if (DofIsHP(dest))
			nd = dest->dim * (dest->hp->face_index[n + 1] -
						 dest->hp->face_index[n]);
		    for (i = 0; i < nd; i++)
			*(d++) += *(a++) * w;
		    *DofFaceData(wgts, n) += w;
		}
	    }
	}

	if (newtype->np_elem > 0) {
	    a = DofElementData(dest, e->index);
	    newtype->InitFunc(dest, e, ELEMENT, 0, NULL, func, NULL, a,
					NULL);
	}
    }

    phgFree(basvalues);
    phgFree(flags0);

    if (wgts == NULL)
	return dest;

    if ((n = DofGetDataCount(dest) - DofGetElementDataCount(dest)) > 0) {
	memcpy(DofData(dest), buffer, n * sizeof(*buffer));
	phgFree(buffer);
    }

    if (DofIsHP(dest))
	newtype = dest->hp->info->types[dest->hp->max_order];

    a = DofData(dest);
    d = DofData(wgts);

#if USE_MPI
    /* FIXME: directly interacting with the vector assembly code in solver.c
       is more efficient */
    if (g->nprocs > 1) {
	SOLVER *solver = phgSolverCreate(SOLVER_BUILTIN, dest, NULL);
	INT K = 0, I;
	int j;

	if (newtype->np_vert > 0) {
	    nd = dest->count_vert;
	    for (n = 0; n < g->nvert; n++, d++) {
		if (g->types_vert[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_edge > 0) {
	    nd = nvalues * newtype->np_edge;
	    for (n = 0; n < g->nedge; n++, d++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->edge_index[n + 1] -
					     dest->hp->edge_index[n]);
		if (g->types_edge[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_face > 0) {
	    nd = nvalues * newtype->np_face;
	    for (n = 0; n < g->nface; n++, d++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->face_index[n + 1] -
					     dest->hp->face_index[n]);
		if (g->types_face[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, *d);
		}
	    }
	}

	if (newtype->np_elem > 0) {
	    nd = nvalues * newtype->np_elem;
	    for (n = 0; n < g->nelem; n++) {
		if (DofIsHP(dest))
		    nd = dest->dim * (dest->hp->elem_index[n + 1] -
					     dest->hp->elem_index[n]);
		if (g->types_elem[n] == UNREFERENCED) {
		    K += nd;
		    a += nd;
		    continue;
		}
		for (j = 0; j < nd; j++, K++, a++) {
		    I = phgSolverMapD2L(solver, 0, K);
		    assert(I >= 0 && I < solver->mat->rmap->localsize);
		    phgSolverAddRHSEntry(solver, I, *a);
		    phgSolverAddMatrixEntry(solver, I, I, 1.0);
		}
	    }
	}

	phgSolverSolve(solver, TRUE, dest, NULL);
	phgSolverDestroy(&solver);

	phgDofFree(&wgts);

	return dest;
    }
#endif

    if (newtype->np_vert > 0) {
	k = nvalues * newtype->np_vert;
	for (n = 0; n < g->nvert; n++) {
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    if (newtype->np_edge > 0) {
	k = nvalues * newtype->np_edge;
	for (n = 0; n < g->nedge; n++) {
	    if (DofIsHP(dest))
		k = dest->dim * (dest->hp->edge_index[n + 1] -
					dest->hp->edge_index[n]);
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    if (newtype->np_face > 0) {
	k = nvalues * newtype->np_face;
	for (n = 0; n < g->nface; n++) {
	    if (DofIsHP(dest))
		k = dest->dim * (dest->hp->face_index[n + 1] -
					dest->hp->face_index[n]);
	    if ((w = *(d++)) == 0.0) {
		a += k;
	    }
	    else if (k == 1) {
		*(a++) /= w;
	    }
	    else {
		w = 1.0 / w;
		for (i = 0; i < k; i++)
		    *(a++) *= w;
	    }
	}
    }

    phgDofFree(&wgts);

    return dest;
}
Ejemplo n.º 13
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]);
    }