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; }
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; }
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; }
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; } } }
/* *********************** * 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; }
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]); }
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; }
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]); }