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); } } }
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 create_kro(DOF *s_w, DOF *kro) { GRID *g = s_w->g; SIMPLEX *e; FLOAT *p_sw, *p_kro; ForAllElements(g, e){ p_sw = DofElementData(s_w, e->index); p_kro = DofElementData(kro, e->index); p_kro[0] = KRO_SWC * pow((1 - p_sw[0] - SORW) / (1 - SWC - SORW), NO); }
void create_kr(PHASE *oil, PHASE *water) { GRID *g = water->Kr->g; SIMPLEX *e; FLOAT *p_so, *p_kro, *p_krw, S =0; ForAllElements(g, e){ p_so = DofElementData(oil->S, e->index); p_kro = DofElementData(oil->Kr, e->index); p_krw = DofElementData(water->Kr, e->index); S = (1. - p_so[0] - SWC) / (1 - SWC - SOR); p_kro[0] =pow((1 - S), NO); p_krw[0] = pow(S, NW); }
static FLOAT estimate_error(FLOAT lambda, DOF *u_h, DOF *error) { GRID *g = u_h->g; ELEMENT *e; DOF *curl_u_h, *jump1, *jump2, *residual, *tmp; curl_u_h = phgDofCurl(u_h, NULL, NULL, NULL); residual = phgDofGetSameOrderDG(u_h, -1, NULL); phgDofCopy(u_h, &residual, NULL, "residual"); jump2 = phgQuadFaceJump(residual, DOF_PROJ_DOT, NULL, QUAD_DEFAULT); tmp = phgDofCurl(curl_u_h, NULL, NULL, NULL); phgDofAXPBY(-1.0, tmp, lambda, &residual); phgDofFree(&tmp); jump1 = phgQuadFaceJump(curl_u_h, DOF_PROJ_CROSS, NULL, QUAD_DEFAULT); ForAllElements(g, e) { int i; FLOAT eta, h; FLOAT diam = phgGeomGetDiameter(g, e); e->mark = 0; /* clear refinement mmark */ eta = 0.0; for (i = 0; i < NFace; i++) { if (e->bound_type[i] == DIRICHLET || e->bound_type[i] == NEUMANN) continue; /* boundary face */ h = phgGeomGetFaceDiameter(g, e, i); eta += (*DofFaceData(jump1, e->faces[i]) + *DofFaceData(jump2, e->faces[i])) * h; } eta = eta + diam * diam * phgQuadDofDotDof(e, residual, residual, QUAD_DEFAULT); *DofElementData(error, e->index) = eta; }
void Well_Pressure(DOF *p_h, FLOAT *pressure) { GRID *g = p_h->g; SIMPLEX *e; FLOAT *p_p, sum = 0; INT count = 0, i, well_no, nbas = p_h->type->nbas; ForAllElements(g, e) { *pressure = 0.0; if(e->region_mark == 2){ p_p = DofElementData(p_h, e->index); sum += p_p[0]; count++; } else if (e->region_mark == 3){ p_p = DofElementData(p_h, e->index); sum += p_p[0]; count++; } }
static void estimate_error(DOF *u, DOF *p, DOF *f, DOF *gradu, DOF *divu, DOF *e_H1) /* compute error indicators L_H1(e_u) + L2(e_p). */ { int i; GRID *g = u->g; ELEMENT *e; DOF *jump, *residual, *tmp; FLOAT eta, d, h; FLOAT diam; /* RE = [[nu \grad u - p I]] */ tmp = phgDofCopy(gradu, NULL, NULL, NULL); phgDofAFXPBY(-1.0, f_1to3, p, nu, &tmp); jump = phgQuadFaceJump(tmp, DOF_PROJ_DOT, "jumps", QUAD_DEFAULT); phgDofFree(&tmp); /* RT1 = f + nu \laplace u - (u \cdot \grad) u - \grad p * RT2 = \div u */ tmp = phgDofDivergence(gradu, NULL, NULL, NULL); residual = phgDofGetSameOrderDG(u, -1, "residual 1"); phgDofCopy(f, &residual, NULL, NULL); phgDofAXPBY(nu, tmp, 1.0, &residual); phgDofFree(&tmp); tmp = phgDofGradient(p, NULL, NULL, NULL); phgDofAXPY(-1.0, tmp, &residual); phgDofMM(MAT_OP_N, MAT_OP_T, 1, 3, 3, 1.0, u, -1, gradu, 1., &residual); phgDofFree(&tmp); ForAllElements(g, e) { diam = phgGeomGetDiameter(g, e); e->mark = 0; /* clear refinement mmark */ eta = 0.0; /* for each face F compute [grad_u \cdot n] */ for (i = 0; i < NFace; i++) { if (e->bound_type[i] & (DIRICHLET | NEUMANN)) continue; /* boundary face */ h = phgGeomGetFaceDiameter(g, e, i); d = *DofFaceData(jump, e->faces[i]); eta += d * h; } eta += diam * diam * phgQuadDofDotDof(e, residual, residual, QUAD_DEFAULT) + phgQuadDofDotDof(e, divu, divu, QUAD_DEFAULT); /* add curved boundary errors (FIXME: how to normalize?) */ eta += phgGetBoundaryError(g, e); *DofElementData(e_H1, e->index) = eta; }
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; } } }
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]); }
/* build linear system */ static void build_mat_vec(DOF *u_w, DOF *dp, DOF *p_nk, DOF *ds, DOF *s_w, DOF *s_w_l, DOF *b_o, DOF *b_o_l, DOF *kro, DOF *dot_kro, DOF *q_o, DOF *b_w, DOF *b_w_l, DOF *krw, DOF *dot_krw, DOF *q_w, DOF *phi, DOF *phi_l, MAP *map_u, MAP *map_p, MAT *A, MAT *B, MAT *TB, MAT *C, VEC *vec_f, VEC *vec_g) { GRID *g = u_w->g; SIMPLEX *e; FLOAT *p_bo, *p_bw, *p_bol, *p_bwl, *p_kro, *p_dotkro, *p_krw, *p_dotkrw, *p_swl, *p_dp, *p_ds, *p_sw, *p_phi; INT N = u_w->type->nbas * u_w->dim; INT M = dp->type->nbas * dp->dim; INT I[N], J[M]; FLOAT mat_A[N][N], mat_TB[N][M], mat_B[M][N], mat_C[M][M], rhs_f[N], rhs_g[M]; phgVecDisassemble(vec_f); phgVecDisassemble(vec_g); int i, j, k; ForAllElements(g, e) { p_phi = DofElementData(phi, e->index); p_bo = DofElementData(b_o, e->index); p_bol = DofElementData(b_o_l, e->index); p_bw = DofElementData(b_w, e->index); p_bwl = DofElementData(b_w_l, e->index); p_sw = DofElementData(s_w, e->index); p_swl = DofElementData(s_w_l, e->index); p_kro = DofElementData(kro, e->index); p_dotkro = DofElementData(dot_kro, e->index); p_krw = DofElementData(krw, e->index); p_dotkrw = DofElementData(dot_krw, e->index); p_dp = DofElementData(dp, e->index); p_ds = DofElementData(ds, e->index); FLOAT T_o = 0, T_w = 0; T_w = K * p_krw[0] * p_bw[0] / MU_W + K * p_krw[0] * C_W / (MU_W * B0_W) * p_dp[0] + K * p_bw[0] * p_dotkrw[0] / MU_W * p_ds[0]; T_o = K * p_kro[0] * p_bo[0] / MU_O + K * p_kro[0] * C_O / (MU_O * B0_O) * p_dp[0] + K * p_bo[0] * p_dotkro[0] / MU_O * p_ds[0]; for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { mat_A[i][j] = stime * phgQuadBasDotBas(e, u_w, i, u_w, j, QUAD_DEFAULT) / T_w; } } for (i = 0; i < N; i++) { for (j = 0; j < M; j++) { mat_TB[i][j] = -stime * phgQuadDivBasDotBas(e, u_w, i, dp, j, QUAD_DEFAULT); } } FLOAT wat_sw = 0, oil_sw = 0, wat_cp = 0, oil_cp = 0, beta = 0; for (i = 0; i < M; i++) { for (j = 0; j < M; j++) { wat_sw = p_phi[0] * p_bw[0] * phgQuadBasDotBas(e, ds, i, ds, j, QUAD_DEFAULT); oil_sw = p_phi[0] * p_bo[0] * phgQuadBasDotBas(e, ds, i, ds, j, QUAD_DEFAULT); } } wat_cp = p_sw[0] * (p_bw[0] * PHI0 * C_R + p_phi[0] * C_W / B0_W); oil_cp = (1. - p_sw[0]) * (p_bo[0] * PHI0 * C_R + p_phi[0] * C_O / B0_O); beta = 1. / wat_sw + T_o / (T_w * oil_sw); FLOAT quad = 0.; for (i = 0; i < M; i++) { for (j = 0; j < M; j++) { quad = phgQuadBasDotBas(e, dp, i, dp, j, QUAD_DEFAULT); mat_C[i][j] = (wat_cp / wat_sw + oil_cp / oil_sw) * quad / beta; } } /*create oil rhs*/ FLOAT quad_phi = 0., quad_phil = 0., quad_qo = 0, quad_qw = 0; FLOAT rhs_oil = 0., rhs_wat = 0.; for (i = 0; i < M; i++) { phgQuadDofTimesBas(e, q_o, dp, i, QUAD_DEFAULT, &quad_qo); phgQuadDofTimesBas(e, q_w, dp, i, QUAD_DEFAULT, &quad_qw); phgQuadDofTimesBas(e, phi, dp, i, QUAD_DEFAULT, &quad_phi); phgQuadDofTimesBas(e, phi_l, dp, i, QUAD_DEFAULT, &quad_phil); rhs_oil = -stime * quad_qo + p_bo[0] * (1. - p_sw[0]) * quad_phi - p_bol[0] * (1. - p_swl[0]) * quad_phil; rhs_wat = -stime * quad_qw + p_bw[0] * p_sw[0] * quad_phi - p_bwl[0] * p_swl[0] * quad_phil; rhs_g[i] = (rhs_wat / wat_sw + rhs_oil / oil_sw) / beta; } for (i = 0; i < N; i++) { rhs_f[i] = stime * phgQuadDofTimesDivBas(e, p_nk, u_w, i, QUAD_DEFAULT); } /* Handle Bdry Conditions*/ for (i = 0; i < N; i++) { if (phgDofGetElementBoundaryType(u_w, e, i) & (NEUMANN | DIRICHLET)) { bzero(mat_A[i], N * sizeof(mat_A[i][0])); bzero(mat_TB[i], M * sizeof(mat_TB[i][0])); for (j = 0; j < N; j++) { mat_A[j][i] = 0.; } mat_A[i][i] = 1.; rhs_f[i] = 0.; } } for (i = 0; i < N; i++) { for (j = 0; j < M; j++) { mat_B[j][i] = mat_TB[i][j]; } } for (i = 0; i < N; i++) { I[i] = phgMapE2L(map_u, 0, e, i); } for (i = 0; i < M; i++) { J[i] = phgMapE2L(map_p, 0, e, i); } phgMatAddEntries(A, N, I, N, I, mat_A[0]); phgMatAddEntries(TB, N, I, M, J, mat_TB[0]); phgMatAddEntries(B, M, J, N, I, mat_B[0]); phgMatAddEntries(C, M, J, M, J, mat_C[0]); phgVecAddEntries(vec_f, 0, N, I, rhs_f); phgVecAddEntries(vec_g, 0, M, J, rhs_g); }
static void /*build_linear_system*/ build_mat_vec(DOF *dp, DOF *d_so, DOF *d_sw, DOF *dot_muo, DOF *dot_muw, DOF *dot_mug, DOF *dso_kro, DOF *dsw_kro, DOF *dsw_krw, DOF *dso_krg, DOF *dsw_krg, DOF *u_o, DOF *p_h, DOF *p_h_newton, DOF *s_o, DOF *s_o_l, DOF *mu_o, DOF *b_o, DOF *b_o_l, DOF *kro, DOF *dot_bo, DOF *q_o, DOF *s_w, DOF *s_w_l, DOF *mu_w, DOF *b_w, DOF *b_w_l, DOF *krw, DOF *dot_bw, DOF *q_w, DOF *phi, DOF *phi_l, DOF *dot_phi, DOF *Rs, DOF *Rs_l, DOF *dot_Rs, DOF *mu_g, DOF *b_g, DOF *b_g_l, DOF *krg, DOF *dot_bg, DOF *q_g, MAP *map_u, MAP *map_p, MAT *A, MAT *B, MAT *TB, MAT *C, VEC *vec_f, VEC *vec_g) { GRID *g = u_o->g; SIMPLEX *e; FLOAT *p_so, *p_sol, *p_bo, *p_bol, *p_kro, *p_phi, *p_phil, *p_dotbo, *p_Rs, *p_dotRs, *p_bg, *p_bgl, *p_krg, *p_dotbg, *p_muo, *p_mug, *p_dotphi, *p_Rsl, *p_sw, *p_swl, *p_bw, *p_bwl, *p_krw, *p_dotbw, *p_muw; FLOAT *p_dotmuo, *p_dotmuw, *p_dotmug, *p_dsokro, *p_dswkro, *p_dswkrw, *p_dsokrg, *p_dswkrg, *p_dp, *p_dso, *p_dsw; INT N = u_o->type->nbas * u_o->dim; INT M = dp->type->nbas * dp->dim; INT I[N], J[M]; FLOAT mat_A[N][N], mat_TB[N][M], mat_B[M][N], mat_C[M][M], rhs_f[N], rhs_g[M]; phgVecDisassemble(vec_f); phgVecDisassemble(vec_g); int i, j, k; ForAllElements(g, e){ p_so = DofElementData(s_o, e->index); p_sol = DofElementData(s_o_l, e->index); p_bo = DofElementData(b_o, e->index); p_bol = DofElementData(b_o_l, e->index); p_kro = DofElementData(kro, e->index); p_phi = DofElementData(phi, e->index); p_phil = DofElementData(phi_l, e->index); p_dotphi = DofElementData(dot_phi, e->index); p_dotbo = DofElementData(dot_bo, e->index); p_Rs = DofElementData(Rs, e->index); p_Rsl = DofElementData(Rs_l, e->index); p_dotRs = DofElementData(dot_Rs, e->index); p_bg = DofElementData(b_g, e->index); p_bgl = DofElementData(b_g_l, e->index); p_krg= DofElementData(krg, e->index); p_dotbg = DofElementData(dot_bg, e->index); p_muo = DofElementData(mu_o, e->index); p_muw = DofElementData(mu_w, e->index); p_mug = DofElementData(mu_g, e->index); p_sw = DofElementData(s_w, e->index); p_swl = DofElementData(s_w_l, e->index); p_bw = DofElementData(b_w, e->index); p_bwl = DofElementData(b_w_l, e->index); p_krw = DofElementData(krw, e->index); p_dotbw = DofElementData(dot_bw, e->index); /* Add Dofs For SS */ p_dp = DofElementData(dp, e->index); p_dso = DofElementData(d_so, e->index); p_dsw = DofElementData(d_sw, e->index); p_dotmuo = DofElementData(dot_muo, e->index); p_dotmuw = DofElementData(dot_muw, e->index); p_dotmug = DofElementData(dot_mug, e->index); p_dsokro = DofElementData(dso_kro, e->index); p_dswkro = DofElementData(dsw_kro, e->index); p_dswkrw = DofElementData(dsw_krw, e->index); p_dsokrg = DofElementData(dso_krg, e->index); p_dswkrg = DofElementData(dsw_krg, e->index); /*Create inverse matrix*/ FLOAT oil_so = 0., wat_sw = 0., gas_so = 0., gas_sw = 0.; for (i = 0; i < M; i++){ for (j = 0; j < M; j++){ oil_so = p_phi[0] * p_bo[0] * phgQuadBasDotBas(e, d_so, i, d_so, j, QUAD_DEFAULT); wat_sw = p_phi[0] * p_bw[0] * phgQuadBasDotBas(e, d_sw, i, d_sw, j, QUAD_DEFAULT); gas_so = p_phi[0] * (p_bg[0] - p_Rs[0] * p_bo[0]) * phgQuadBasDotBas(e, d_so, i, d_so, j, QUAD_DEFAULT); gas_sw = p_phi[0] * p_bg[0] * phgQuadBasDotBas(e, d_sw, i, d_sw, j, QUAD_DEFAULT); } } #if SS FLOAT alpha_o = 0., alpha_w = 0., alpha_g = 0.; alpha_o = K * p_kro[0] * p_bo[0] * p_muo[0] + K * p_kro[0] * (p_bo[0] * p_dotmuo[0] + p_dotbo[0] * p_muo[0]) * p_dp[0] \ + K * p_bo[0] * p_muo[0] * (p_dsokro[0] * p_dso[0] + p_dswkro[0] * p_dsw[0]); alpha_w = K * p_krw[0] * p_bw[0] * p_muw[0] + K * p_krw[0] * (p_bw[0] * p_dotmuw[0] + p_dotbw[0] * p_muw[0]) * p_dp[0] \ + K * p_bw[0] * p_muw[0] * p_dswkrw[0] * p_dsw[0]; alpha_g = K * p_krg[0] * p_bg[0] * p_mug[0] + K * p_krg[0] * (p_bg[0] * p_dotmug[0] + p_dotbg[0] * p_mug[0]) * p_dp[0] \ + K * p_bg[0] * p_mug[0] * (p_dsokrg[0] * p_dso[0] + p_dswkrg[0] * p_dsw[0]); for (i = 0; i < N; i++){ for (j = 0; j < N; j++){ mat_A[i][j] = stime * phgQuadBasDotBas(e, u_o, i, u_o, j, QUAD_DEFAULT) / alpha_o; } } FLOAT beta = 0; beta = gas_so / oil_so + gas_sw * alpha_w / (wat_sw * alpha_o) + (p_Rs[0] + alpha_g / alpha_o); #endif #if IMPES FLOAT T_o = 0, T_w = 0, T_g = 0; T_o = K * p_kro[0] * p_bo[0] * p_muo[0]; T_w = K * p_krw[0] * p_bw[0] * p_muw[0]; T_g = K * p_krg[0] * p_bg[0] * p_mug[0]; for (i = 0; i < N; i++){ for (j = 0; j < N; j++){ mat_A[i][j] = stime * phgQuadBasDotBas(e, u_o, i, u_o, j, QUAD_DEFAULT) / T_o; } } FLOAT beta = 0; beta = gas_so / oil_so + gas_sw * T_w / (wat_sw * T_o) + (p_Rs[0] + T_g / T_o); #endif for (i = 0; i < N; i++){ for (j = 0; j < M; j++){ mat_TB[i][j] = -stime * phgQuadDivBasDotBas(e, u_o, i, dp, j, QUAD_DEFAULT); } } FLOAT quad = 0., oil_cp = 0., wat_cp = 0., gas_cp = 0.; oil_cp = p_so[0] * (p_bo[0] * p_dotphi[0] + p_phi[0] * p_dotbo[0]); wat_cp = p_sw[0] * (p_bw[0] * p_dotphi[0] + p_phi[0] * p_dotbw[0]); gas_cp = p_so[0] * p_phi[0] * p_bo[0] * p_dotRs[0] + p_Rs[0] * oil_cp + (1. - p_so[0] - p_sw[0]) * (p_phi[0] * p_dotbg[0] + p_bg[0] * p_dotphi[0]); for (i = 0; i < M; i++){ for (j = 0; j < M; j++){ quad = phgQuadBasDotBas(e, dp, i, dp, j, QUAD_DEFAULT); mat_C[i][j] = (gas_so * oil_cp / oil_so + gas_sw * wat_cp / wat_sw + gas_cp) * quad / beta; } } /*Create rhs*/ FLOAT quad_qo = 0; FLOAT quad_qw = 0.; FLOAT quad_qg = 0.; FLOAT quad_phi = 0, quad_phil = 0; FLOAT rhs_oil = 0, rhs_wat = 0., rhs_gas = 0; for (i = 0; i < M; i++){ phgQuadDofTimesBas(e, q_o, dp, i, QUAD_DEFAULT, &quad_qo); phgQuadDofTimesBas(e, q_w, dp, i, QUAD_DEFAULT, &quad_qw); phgQuadDofTimesBas(e, q_g, dp, i, QUAD_DEFAULT, &quad_qg); phgQuadDofTimesBas(e, phi, dp, i, QUAD_DEFAULT, &quad_phi); phgQuadDofTimesBas(e, phi_l, dp, i, QUAD_DEFAULT, &quad_phil); rhs_oil = -stime * quad_qo + p_so[0] * p_bo[0] * quad_phi - p_sol[0] * p_bol[0] * quad_phil; rhs_wat = -stime * quad_qw + p_sw[0] * p_bw[0] * quad_phi - p_swl[0] * p_bwl[0] * quad_phil; rhs_gas = -stime * quad_qg + (p_bg[0] * (1. - p_so[0] - p_sw[0]) + p_Rs[0] * p_so[0] * p_bo[0]) * quad_phi \ - (p_Rsl[0] * p_bol[0] * p_sol[0] + p_bgl[0] * (1. - p_sol[0] - p_swl[0])) * quad_phil; rhs_g[i] = (gas_so * rhs_oil / oil_so + gas_sw * rhs_wat / wat_sw + rhs_gas) / beta; } for (i = 0; i < N; i++){ rhs_f[i] = stime * phgQuadDofTimesDivBas(e, p_h, u_o, i, QUAD_DEFAULT); } /* Handle Bdry Conditions */ for (i = 0; i < N; i++){ if (phgDofGetElementBoundaryType(u_o, e, i) & (NEUMANN | DIRICHLET)){ bzero(mat_A[i], N *sizeof(mat_A[i][0])); bzero(mat_TB[i], M *sizeof(mat_TB[i][0])); for (j = 0; j < N; j++){ mat_A[j][i] = 0.0; } mat_A[i][i] = 1.0; rhs_f[i] = 0.; } } for (i = 0; i < N; i++){ for (j = 0; j < M; j++){ mat_B[j][i] = mat_TB[i][j]; } } for (i = 0; i < N; i++){ I[i] = phgMapE2L(map_u, 0, e, i); } for (i = 0; i < M; i++){ J[i] = phgMapE2L(map_p, 0, e, i); } phgMatAddEntries(A, N, I, N, I, mat_A[0]); phgMatAddEntries(TB, N, I, M, J, mat_TB[0]); phgMatAddEntries(B, M, J, N, I, mat_B[0]); phgMatAddEntries(C, M, J, M, J, mat_C[0]); phgVecAddEntries(vec_f, 0, N, I, rhs_f); phgVecAddEntries(vec_g, 0, M, J, rhs_g); }