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