1811d88abSStefano Zampini static char help[] = "Biological network from https://link.springer.com/article/10.1007/s42967-023-00297-3\n\n\n"; 2811d88abSStefano Zampini 3811d88abSStefano Zampini #include <petscts.h> 4811d88abSStefano Zampini #include <petscsf.h> 5811d88abSStefano Zampini #include <petscdmplex.h> 6811d88abSStefano Zampini #include <petscdmplextransform.h> 7811d88abSStefano Zampini #include <petscdmforest.h> 8811d88abSStefano Zampini #include <petscviewerhdf5.h> 9811d88abSStefano Zampini #include <petscds.h> 10811d88abSStefano Zampini 11811d88abSStefano Zampini /* 1266edf50cSStefano Zampini Here we solve the system of PDEs on \Omega \in R^d: 13811d88abSStefano Zampini 1466edf50cSStefano Zampini * dC/dt - D^2 \Delta C - \nabla p \cross \nabla p + \alpha sqrt(||C||^2_F + eps)^(\gamma-2) C = 0 15811d88abSStefano Zampini * - \nabla \cdot ((r + C) \nabla p) = S 16811d88abSStefano Zampini 17811d88abSStefano Zampini where: 1866edf50cSStefano Zampini C = symmetric dxd conductivity tensor 19811d88abSStefano Zampini p = potential 20811d88abSStefano Zampini S = source 21811d88abSStefano Zampini 22811d88abSStefano Zampini with natural boundary conditions on \partial\Omega: 23811d88abSStefano Zampini \nabla C \cdot n = 0 24811d88abSStefano Zampini \nabla ((r + C)\nabla p) \cdot n = 0 25811d88abSStefano Zampini 26811d88abSStefano Zampini Parameters: 27811d88abSStefano Zampini D = diffusion constant 28811d88abSStefano Zampini \alpha = metabolic coefficient 29811d88abSStefano Zampini \gamma = metabolic exponent 30811d88abSStefano Zampini r, eps are regularization parameters 31811d88abSStefano Zampini 32811d88abSStefano Zampini We use Lagrange elements for C_ij and P. 3366edf50cSStefano Zampini Equations are rescaled to obtain a symmetric Jacobian. 34811d88abSStefano Zampini */ 35811d88abSStefano Zampini 36811d88abSStefano Zampini typedef enum _fieldidx { 37811d88abSStefano Zampini C_FIELD_ID = 0, 38811d88abSStefano Zampini P_FIELD_ID, 39811d88abSStefano Zampini NUM_FIELDS 40811d88abSStefano Zampini } FieldIdx; 41811d88abSStefano Zampini 42811d88abSStefano Zampini typedef enum _constantidx { 43811d88abSStefano Zampini R_ID = 0, 44811d88abSStefano Zampini EPS_ID, 45811d88abSStefano Zampini ALPHA_ID, 46811d88abSStefano Zampini GAMMA_ID, 47811d88abSStefano Zampini D_ID, 48204aa523SStefano Zampini FIXC_ID, 4966edf50cSStefano Zampini SPLIT_ID, 50811d88abSStefano Zampini NUM_CONSTANTS 51811d88abSStefano Zampini } ConstantIdx; 52811d88abSStefano Zampini 53811d88abSStefano Zampini PetscLogStage SetupStage, SolveStage; 54811d88abSStefano Zampini 5566edf50cSStefano Zampini #define NORM2C(c00, c01, c11) (PetscSqr(c00) + 2 * PetscSqr(c01) + PetscSqr(c11)) 5666edf50cSStefano Zampini #define NORM2C_3d(c00, c01, c02, c11, c12, c22) (PetscSqr(c00) + 2 * PetscSqr(c01) + 2 * PetscSqr(c02) + PetscSqr(c11) + 2 * PetscSqr(c12) + PetscSqr(c22)) 5766edf50cSStefano Zampini 5866edf50cSStefano Zampini /* Eigenvalues real 3x3 symmetric matrix https://onlinelibrary.wiley.com/doi/full/10.1002/nme.7153 */ 5966edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 6066edf50cSStefano Zampini static inline void Eigenvalues_Sym3x3(PetscReal a11, PetscReal a12, PetscReal a13, PetscReal a22, PetscReal a23, PetscReal a33, PetscReal x[3]) 6166edf50cSStefano Zampini { 6266edf50cSStefano Zampini const PetscBool td = (PetscBool)(a13 == 0 && a23 == 0); 6366edf50cSStefano Zampini if (td) { /* two-dimensional case */ 6466edf50cSStefano Zampini PetscReal a12_2 = PetscSqr(a12); 6566edf50cSStefano Zampini PetscReal delta = PetscSqr(a11 - a22) + 4 * a12_2; 6666edf50cSStefano Zampini PetscReal b = -(a11 + a22); 6766edf50cSStefano Zampini PetscReal c = a11 * a22 - a12_2; 6866edf50cSStefano Zampini PetscReal temp = -0.5 * (b + PetscCopysignReal(1.0, b) * PetscSqrtReal(delta)); 6966edf50cSStefano Zampini 7066edf50cSStefano Zampini x[0] = temp; 7166edf50cSStefano Zampini x[1] = c / temp; 7266edf50cSStefano Zampini x[2] = a33; 7366edf50cSStefano Zampini } else { 7466edf50cSStefano Zampini const PetscReal I1 = a11 + a22 + a33; 7566edf50cSStefano Zampini const PetscReal J2 = (PetscSqr(a11 - a22) + PetscSqr(a22 - a33) + PetscSqr(a33 - a11)) / 6 + PetscSqr(a12) + PetscSqr(a23) + PetscSqr(a13); 7666edf50cSStefano Zampini const PetscReal s = PetscSqrtReal(J2 / 3); 7766edf50cSStefano Zampini const PetscReal tol = PETSC_MACHINE_EPSILON; 7866edf50cSStefano Zampini 7966edf50cSStefano Zampini if (s < tol) { 8066edf50cSStefano Zampini x[0] = x[1] = x[2] = 0.0; 8166edf50cSStefano Zampini } else { 8266edf50cSStefano Zampini const PetscReal S[] = {a11 - I1 / 3, a12, a13, a22 - I1 / 3, a23, a33 - I1 / 3}; 8366edf50cSStefano Zampini 8466edf50cSStefano Zampini /* T = S^2 */ 8566edf50cSStefano Zampini PetscReal T[6]; 8666edf50cSStefano Zampini T[0] = S[0] * S[0] + S[1] * S[1] + S[2] * S[2]; 8766edf50cSStefano Zampini T[1] = S[0] * S[1] + S[1] * S[3] + S[2] * S[4]; 8866edf50cSStefano Zampini T[2] = S[0] * S[2] + S[1] * S[4] + S[2] * S[5]; 8966edf50cSStefano Zampini T[3] = S[1] * S[1] + S[3] * S[3] + S[4] * S[4]; 9066edf50cSStefano Zampini T[4] = S[1] * S[2] + S[3] * S[4] + S[4] * S[5]; 9166edf50cSStefano Zampini T[5] = S[2] * S[2] + S[4] * S[4] + S[5] * S[5]; 9266edf50cSStefano Zampini 9366edf50cSStefano Zampini T[0] = T[0] - 2.0 * J2 / 3.0; 9466edf50cSStefano Zampini T[3] = T[3] - 2.0 * J2 / 3.0; 9566edf50cSStefano Zampini T[5] = T[5] - 2.0 * J2 / 3.0; 9666edf50cSStefano Zampini 9766edf50cSStefano Zampini const PetscReal aa = NORM2C_3d(T[0] - s * S[0], T[1] - s * S[1], T[2] - s * S[2], T[3] - s * S[3], T[4] - s * S[4], T[5] - s * S[5]); 9866edf50cSStefano Zampini const PetscReal bb = NORM2C_3d(T[0] + s * S[0], T[1] + s * S[1], T[2] + s * S[2], T[3] + s * S[3], T[4] + s * S[4], T[5] + s * S[5]); 9966edf50cSStefano Zampini const PetscReal d = PetscSqrtReal(aa / bb); 10066edf50cSStefano Zampini const PetscBool sj = (PetscBool)(1.0 - d > 0.0); 10166edf50cSStefano Zampini 10266edf50cSStefano Zampini if (PetscAbsReal(1 - d) < tol) { 10366edf50cSStefano Zampini x[0] = -PetscSqrtReal(J2); 10466edf50cSStefano Zampini x[1] = 0.0; 10566edf50cSStefano Zampini x[2] = PetscSqrtReal(J2); 10666edf50cSStefano Zampini } else { 10766edf50cSStefano Zampini const PetscReal sjn = sj ? 1.0 : -1.0; 10866edf50cSStefano Zampini //const PetscReal atanarg = sj ? d : 1.0 / d; 10966edf50cSStefano Zampini //const PetscReal alpha = 2.0 * PetscAtanReal(atanarg) / 3.0; 11066edf50cSStefano Zampini const PetscReal atanval = d > tol ? 2.0 * PetscAtanReal(sj ? d : 1.0 / d) : (sj ? 0.0 : PETSC_PI); 11166edf50cSStefano Zampini const PetscReal alpha = atanval / 3.0; 11266edf50cSStefano Zampini const PetscReal cd = s * PetscCosReal(alpha) * sjn; 11366edf50cSStefano Zampini const PetscReal sd = PetscSqrtReal(J2) * PetscSinReal(alpha); 11466edf50cSStefano Zampini 11566edf50cSStefano Zampini x[0] = 2 * cd; 11666edf50cSStefano Zampini x[1] = -cd + sd; 11766edf50cSStefano Zampini x[2] = -cd - sd; 11866edf50cSStefano Zampini } 11966edf50cSStefano Zampini } 12066edf50cSStefano Zampini x[0] += I1 / 3.0; 12166edf50cSStefano Zampini x[1] += I1 / 3.0; 12266edf50cSStefano Zampini x[2] += I1 / 3.0; 12366edf50cSStefano Zampini } 12466edf50cSStefano Zampini } 12566edf50cSStefano Zampini #endif 12666edf50cSStefano Zampini 12766edf50cSStefano Zampini /* compute shift to make C positive definite */ 12866edf50cSStefano Zampini static inline PetscReal FIX_C_3d(PetscScalar C00, PetscScalar C01, PetscScalar C02, PetscScalar C11, PetscScalar C12, PetscScalar C22) 12966edf50cSStefano Zampini { 13066edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 13166edf50cSStefano Zampini PetscReal eigs[3], s = 0.0; 13266edf50cSStefano Zampini PetscBool twod = (PetscBool)(C02 == 0 && C12 == 0 && C22 == 0); 13366edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 13466edf50cSStefano Zampini if (twod) eigs[2] = 1.0; 13566edf50cSStefano Zampini if (eigs[0] <= 0 || eigs[1] <= 0 || eigs[2] <= 0) s = -PetscMin(eigs[0], PetscMin(eigs[1], eigs[2])) + PETSC_SMALL; 13666edf50cSStefano Zampini return s; 13766edf50cSStefano Zampini #else 13866edf50cSStefano Zampini return 0.0; 13966edf50cSStefano Zampini #endif 14066edf50cSStefano Zampini } 14166edf50cSStefano Zampini 14266edf50cSStefano Zampini static inline PetscReal FIX_C(PetscScalar C00, PetscScalar C01, PetscScalar C11) 14366edf50cSStefano Zampini { 14466edf50cSStefano Zampini return FIX_C_3d(C00, C01, 0, C11, 0, 0); 14566edf50cSStefano Zampini } 146811d88abSStefano Zampini 147811d88abSStefano Zampini /* residual for C when tested against basis functions */ 148811d88abSStefano Zampini static void C_0(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 149811d88abSStefano Zampini { 150811d88abSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 151811d88abSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 152811d88abSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 15366edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 15466edf50cSStefano Zampini const PetscScalar *gradp = split ? a_x + aOff_x[P_FIELD_ID] : u_x + uOff_x[P_FIELD_ID]; 15566edf50cSStefano Zampini const PetscScalar outerp[] = {gradp[0] * gradp[0], gradp[0] * gradp[1], gradp[1] * gradp[1]}; 15666edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 15766edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 15866edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 159811d88abSStefano Zampini const PetscScalar norm = NORM2C(C00, C01, C11) + eps; 160811d88abSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 161811d88abSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 16266edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; /* equations rescaling for a symmetric Jacobian */ 163811d88abSStefano Zampini 16466edf50cSStefano Zampini for (PetscInt k = 0; k < 3; k++) f0[k] = eqss[k] * (u_t[uOff[C_FIELD_ID] + k] - outerp[k] + alpha * fnorm * u[uOff[C_FIELD_ID] + k]); 16566edf50cSStefano Zampini } 16666edf50cSStefano Zampini 16766edf50cSStefano Zampini /* 3D version */ 16866edf50cSStefano Zampini static void C_0_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 16966edf50cSStefano Zampini { 17066edf50cSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 17166edf50cSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 17266edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 17366edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 17466edf50cSStefano Zampini const PetscScalar *gradp = split ? a_x + aOff_x[P_FIELD_ID] : u_x + uOff_x[P_FIELD_ID]; 17566edf50cSStefano Zampini const PetscScalar outerp[] = {gradp[0] * gradp[0], gradp[0] * gradp[1], gradp[0] * gradp[2], gradp[1] * gradp[1], gradp[1] * gradp[2], gradp[2] * gradp[2]}; 17666edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 17766edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 17866edf50cSStefano Zampini const PetscScalar C02 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 17966edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 3] : u[uOff[C_FIELD_ID] + 3]; 18066edf50cSStefano Zampini const PetscScalar C12 = split ? a[aOff[C_FIELD_ID] + 4] : u[uOff[C_FIELD_ID] + 4]; 18166edf50cSStefano Zampini const PetscScalar C22 = split ? a[aOff[C_FIELD_ID] + 5] : u[uOff[C_FIELD_ID] + 5]; 18266edf50cSStefano Zampini const PetscScalar norm = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 18366edf50cSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 18466edf50cSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 18566edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 18666edf50cSStefano Zampini 18766edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) f0[k] = eqss[k] * (u_t[uOff[C_FIELD_ID] + k] - outerp[k] + alpha * fnorm * u[uOff[C_FIELD_ID] + k]); 188811d88abSStefano Zampini } 189811d88abSStefano Zampini 190811d88abSStefano Zampini /* Jacobian for C against C basis functions */ 191811d88abSStefano Zampini static void JC_0_c0c0(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 192811d88abSStefano Zampini { 193811d88abSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 194811d88abSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 195811d88abSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 19666edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 19766edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 19866edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 19966edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 200811d88abSStefano Zampini const PetscScalar norm = NORM2C(C00, C01, C11) + eps; 201811d88abSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 202811d88abSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 203811d88abSStefano Zampini const PetscScalar dfnorm = nexp * PetscPowScalar(norm, nexp - 1.0); 204811d88abSStefano Zampini const PetscScalar dC[] = {2 * C00, 4 * C01, 2 * C11}; 20566edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; 206811d88abSStefano Zampini 207811d88abSStefano Zampini for (PetscInt k = 0; k < 3; k++) { 20866edf50cSStefano Zampini if (!split) { 20966edf50cSStefano Zampini for (PetscInt j = 0; j < 3; j++) J[k * 3 + j] = eqss[k] * (alpha * dfnorm * dC[j] * u[uOff[C_FIELD_ID] + k]); 21066edf50cSStefano Zampini } 21166edf50cSStefano Zampini J[k * 3 + k] += eqss[k] * (alpha * fnorm + u_tShift); 21266edf50cSStefano Zampini } 21366edf50cSStefano Zampini } 21466edf50cSStefano Zampini 21566edf50cSStefano Zampini static void JC_0_c0c0_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 21666edf50cSStefano Zampini { 21766edf50cSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 21866edf50cSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 21966edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 22066edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 22166edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 22266edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 22366edf50cSStefano Zampini const PetscScalar C02 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 22466edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 3] : u[uOff[C_FIELD_ID] + 3]; 22566edf50cSStefano Zampini const PetscScalar C12 = split ? a[aOff[C_FIELD_ID] + 4] : u[uOff[C_FIELD_ID] + 4]; 22666edf50cSStefano Zampini const PetscScalar C22 = split ? a[aOff[C_FIELD_ID] + 5] : u[uOff[C_FIELD_ID] + 5]; 22766edf50cSStefano Zampini const PetscScalar norm = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 22866edf50cSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 22966edf50cSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 23066edf50cSStefano Zampini const PetscScalar dfnorm = nexp * PetscPowScalar(norm, nexp - 1.0); 23166edf50cSStefano Zampini const PetscScalar dC[] = {2 * C00, 4 * C01, 4 * C02, 2 * C11, 4 * C12, 2 * C22}; 23266edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 23366edf50cSStefano Zampini 23466edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) { 23566edf50cSStefano Zampini if (!split) { 23666edf50cSStefano Zampini for (PetscInt j = 0; j < 6; j++) J[k * 6 + j] = eqss[k] * (alpha * dfnorm * dC[j] * u[uOff[C_FIELD_ID] + k]); 23766edf50cSStefano Zampini } 23866edf50cSStefano Zampini J[k * 6 + k] += eqss[k] * (alpha * fnorm + u_tShift); 239811d88abSStefano Zampini } 240811d88abSStefano Zampini } 241811d88abSStefano Zampini 242811d88abSStefano Zampini /* Jacobian for C against C basis functions and gradients of P basis functions */ 243811d88abSStefano Zampini static void JC_0_c0p1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 244811d88abSStefano Zampini { 24566edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 24666edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; 247811d88abSStefano Zampini 24866edf50cSStefano Zampini J[0] = -2 * gradp[0] * eqss[0]; 249811d88abSStefano Zampini J[1] = 0.0; 25066edf50cSStefano Zampini 25166edf50cSStefano Zampini J[2] = -gradp[1] * eqss[1]; 25266edf50cSStefano Zampini J[3] = -gradp[0] * eqss[1]; 25366edf50cSStefano Zampini 254811d88abSStefano Zampini J[4] = 0.0; 25566edf50cSStefano Zampini J[5] = -2 * gradp[1] * eqss[2]; 25666edf50cSStefano Zampini } 25766edf50cSStefano Zampini 25866edf50cSStefano Zampini static void JC_0_c0p1_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 25966edf50cSStefano Zampini { 26066edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 26166edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 26266edf50cSStefano Zampini 26366edf50cSStefano Zampini J[0] = -2 * gradp[0] * eqss[0]; 26466edf50cSStefano Zampini J[1] = 0.0; 26566edf50cSStefano Zampini J[2] = 0.0; 26666edf50cSStefano Zampini 26766edf50cSStefano Zampini J[3] = -gradp[1] * eqss[1]; 26866edf50cSStefano Zampini J[4] = -gradp[0] * eqss[1]; 26966edf50cSStefano Zampini J[5] = 0.0; 27066edf50cSStefano Zampini 27166edf50cSStefano Zampini J[6] = -gradp[2] * eqss[2]; 27266edf50cSStefano Zampini J[7] = 0.0; 27366edf50cSStefano Zampini J[8] = -gradp[0] * eqss[2]; 27466edf50cSStefano Zampini 27566edf50cSStefano Zampini J[9] = 0.0; 27666edf50cSStefano Zampini J[10] = -2 * gradp[1] * eqss[3]; 27766edf50cSStefano Zampini J[11] = 0.0; 27866edf50cSStefano Zampini 27966edf50cSStefano Zampini J[12] = 0.0; 28066edf50cSStefano Zampini J[13] = -gradp[2] * eqss[4]; 28166edf50cSStefano Zampini J[14] = -gradp[1] * eqss[4]; 28266edf50cSStefano Zampini 28366edf50cSStefano Zampini J[15] = 0.0; 28466edf50cSStefano Zampini J[16] = 0.0; 28566edf50cSStefano Zampini J[17] = -2 * gradp[2] * eqss[5]; 286811d88abSStefano Zampini } 287811d88abSStefano Zampini 288811d88abSStefano Zampini /* residual for C when tested against gradients of basis functions */ 289811d88abSStefano Zampini static void C_1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 290811d88abSStefano Zampini { 291811d88abSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 292811d88abSStefano Zampini for (PetscInt k = 0; k < 3; k++) 293811d88abSStefano Zampini for (PetscInt d = 0; d < 2; d++) f1[k * 2 + d] = PetscSqr(D) * u_x[uOff_x[C_FIELD_ID] + k * 2 + d]; 294811d88abSStefano Zampini } 295811d88abSStefano Zampini 29666edf50cSStefano Zampini static void C_1_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 29766edf50cSStefano Zampini { 29866edf50cSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 29966edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) 30066edf50cSStefano Zampini for (PetscInt d = 0; d < 3; d++) f1[k * 3 + d] = PetscSqr(D) * u_x[uOff_x[C_FIELD_ID] + k * 3 + d]; 30166edf50cSStefano Zampini } 30266edf50cSStefano Zampini 303811d88abSStefano Zampini /* Jacobian for C against gradients of C basis functions */ 304811d88abSStefano Zampini static void JC_1_c1c1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 305811d88abSStefano Zampini { 306811d88abSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 307811d88abSStefano Zampini for (PetscInt k = 0; k < 3; k++) 308811d88abSStefano Zampini for (PetscInt d = 0; d < 2; d++) J[k * (3 + 1) * 2 * 2 + d * 2 + d] = PetscSqr(D); 309811d88abSStefano Zampini } 310811d88abSStefano Zampini 31166edf50cSStefano Zampini static void JC_1_c1c1_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 312811d88abSStefano Zampini { 31366edf50cSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 31466edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) 31566edf50cSStefano Zampini for (PetscInt d = 0; d < 3; d++) J[k * (6 + 1) * 3 * 3 + d * 3 + d] = PetscSqr(D); 316811d88abSStefano Zampini } 317811d88abSStefano Zampini 31866edf50cSStefano Zampini /* residual for P when tested against basis functions. 31966edf50cSStefano Zampini The source term always comes from the auxiliary data because it must be zero mean (algebraically) */ 32066edf50cSStefano Zampini static void P_0(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 321204aa523SStefano Zampini { 32266edf50cSStefano Zampini PetscScalar S = a[aOff[NUM_FIELDS]]; 323204aa523SStefano Zampini 32466edf50cSStefano Zampini f0[0] = S; 32566edf50cSStefano Zampini } 32666edf50cSStefano Zampini 32766edf50cSStefano Zampini /* residual for P when tested against basis functions for the initial condition problem 32866edf50cSStefano Zampini here we don't impose symmetry, and we thus flip the sign of the source function */ 32966edf50cSStefano Zampini static void P_0_aux(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 33066edf50cSStefano Zampini { 33166edf50cSStefano Zampini PetscScalar S = a[aOff[NUM_FIELDS]]; 33266edf50cSStefano Zampini 33366edf50cSStefano Zampini f0[0] = -S; 334204aa523SStefano Zampini } 335204aa523SStefano Zampini 336811d88abSStefano Zampini /* residual for P when tested against gradients of basis functions */ 337811d88abSStefano Zampini static void P_1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 338811d88abSStefano Zampini { 339811d88abSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 340204aa523SStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 341811d88abSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 342811d88abSStefano Zampini const PetscScalar C10 = C01; 343204aa523SStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2] + r; 34466edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 345204aa523SStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 346204aa523SStefano Zampini const PetscScalar s = fix_c ? FIX_C(C00, C01, C11) : 0.0; 347811d88abSStefano Zampini 34866edf50cSStefano Zampini f1[0] = -((C00 + s) * gradp[0] + C01 * gradp[1]); 34966edf50cSStefano Zampini f1[1] = -(C10 * gradp[0] + (C11 + s) * gradp[1]); 350811d88abSStefano Zampini } 351811d88abSStefano Zampini 35266edf50cSStefano Zampini static void P_1_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 35366edf50cSStefano Zampini { 35466edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 35566edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 35666edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 35766edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 35866edf50cSStefano Zampini const PetscScalar C10 = C01; 35966edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 36066edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 36166edf50cSStefano Zampini const PetscScalar C20 = C02; 36266edf50cSStefano Zampini const PetscScalar C21 = C12; 36366edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 36466edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 36566edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 36666edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 36766edf50cSStefano Zampini 36866edf50cSStefano Zampini f1[0] = -((C00 + s) * gradp[0] + C01 * gradp[1] + C02 * gradp[2]); 36966edf50cSStefano Zampini f1[1] = -(C10 * gradp[0] + (C11 + s) * gradp[1] + C12 * gradp[2]); 37066edf50cSStefano Zampini f1[2] = -(C20 * gradp[0] + C21 * gradp[1] + (C22 + s) * gradp[2]); 37166edf50cSStefano Zampini } 37266edf50cSStefano Zampini 37366edf50cSStefano Zampini /* Same as above except that the conductivity values come from the auxiliary vec */ 374811d88abSStefano Zampini static void P_1_aux(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 375811d88abSStefano Zampini { 376811d88abSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 377204aa523SStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 378811d88abSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 379811d88abSStefano Zampini const PetscScalar C10 = C01; 380204aa523SStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 2] + r; 38166edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[Nf > 1 ? P_FIELD_ID : 0]; 382204aa523SStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 383204aa523SStefano Zampini const PetscScalar s = fix_c ? FIX_C(C00, C01, C11) : 0.0; 384811d88abSStefano Zampini 385204aa523SStefano Zampini f1[0] = (C00 + s) * gradp[0] + C01 * gradp[1]; 386204aa523SStefano Zampini f1[1] = C10 * gradp[0] + (C11 + s) * gradp[1]; 387811d88abSStefano Zampini } 388811d88abSStefano Zampini 38966edf50cSStefano Zampini static void P_1_aux_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f1[]) 39066edf50cSStefano Zampini { 39166edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 39266edf50cSStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 39366edf50cSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 39466edf50cSStefano Zampini const PetscScalar C02 = a[aOff[C_FIELD_ID] + 2]; 39566edf50cSStefano Zampini const PetscScalar C10 = C01; 39666edf50cSStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 3] + r; 39766edf50cSStefano Zampini const PetscScalar C12 = a[aOff[C_FIELD_ID] + 4]; 39866edf50cSStefano Zampini const PetscScalar C20 = C02; 39966edf50cSStefano Zampini const PetscScalar C21 = C12; 40066edf50cSStefano Zampini const PetscScalar C22 = a[aOff[C_FIELD_ID] + 5] + r; 40166edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[Nf > 1 ? P_FIELD_ID : 0]; 40266edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 40366edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 40466edf50cSStefano Zampini 40566edf50cSStefano Zampini f1[0] = (C00 + s) * gradp[0] + C01 * gradp[1] + C02 * gradp[2]; 40666edf50cSStefano Zampini f1[1] = C10 * gradp[0] + (C11 + s) * gradp[1] + C12 * gradp[2]; 40766edf50cSStefano Zampini f1[2] = C20 * gradp[0] + C21 * gradp[1] + (C22 + s) * gradp[2]; 40866edf50cSStefano Zampini } 40966edf50cSStefano Zampini 410811d88abSStefano Zampini /* Jacobian for P against gradients of P basis functions */ 411811d88abSStefano Zampini static void JP_1_p1p1(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 412811d88abSStefano Zampini { 413811d88abSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 414204aa523SStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 415811d88abSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 416811d88abSStefano Zampini const PetscScalar C10 = C01; 417204aa523SStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2] + r; 418204aa523SStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 419204aa523SStefano Zampini const PetscScalar s = fix_c ? FIX_C(C00, C01, C11) : 0.0; 420811d88abSStefano Zampini 42166edf50cSStefano Zampini J[0] = -(C00 + s); 42266edf50cSStefano Zampini J[1] = -C01; 42366edf50cSStefano Zampini J[2] = -C10; 42466edf50cSStefano Zampini J[3] = -(C11 + s); 425811d88abSStefano Zampini } 426811d88abSStefano Zampini 42766edf50cSStefano Zampini static void JP_1_p1p1_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 42866edf50cSStefano Zampini { 42966edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 43066edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 43166edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 43266edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 43366edf50cSStefano Zampini const PetscScalar C10 = C01; 43466edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 43566edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 43666edf50cSStefano Zampini const PetscScalar C20 = C02; 43766edf50cSStefano Zampini const PetscScalar C21 = C12; 43866edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 43966edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 44066edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 44166edf50cSStefano Zampini 44266edf50cSStefano Zampini J[0] = -(C00 + s); 44366edf50cSStefano Zampini J[1] = -C01; 44466edf50cSStefano Zampini J[2] = -C02; 44566edf50cSStefano Zampini J[3] = -C10; 44666edf50cSStefano Zampini J[4] = -(C11 + s); 44766edf50cSStefano Zampini J[5] = -C12; 44866edf50cSStefano Zampini J[6] = -C20; 44966edf50cSStefano Zampini J[7] = -C21; 45066edf50cSStefano Zampini J[8] = -(C22 + s); 45166edf50cSStefano Zampini } 45266edf50cSStefano Zampini 453811d88abSStefano Zampini static void JP_1_p1p1_aux(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 454811d88abSStefano Zampini { 455811d88abSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 456204aa523SStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 457811d88abSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 458811d88abSStefano Zampini const PetscScalar C10 = C01; 459204aa523SStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 2] + r; 460204aa523SStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 461204aa523SStefano Zampini const PetscScalar s = fix_c ? FIX_C(C00, C01, C11) : 0.0; 462811d88abSStefano Zampini 463204aa523SStefano Zampini J[0] = C00 + s; 464811d88abSStefano Zampini J[1] = C01; 465811d88abSStefano Zampini J[2] = C10; 466204aa523SStefano Zampini J[3] = C11 + s; 467811d88abSStefano Zampini } 468811d88abSStefano Zampini 46966edf50cSStefano Zampini static void JP_1_p1p1_aux_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 47066edf50cSStefano Zampini { 47166edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 47266edf50cSStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 47366edf50cSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 47466edf50cSStefano Zampini const PetscScalar C02 = a[aOff[C_FIELD_ID] + 2]; 47566edf50cSStefano Zampini const PetscScalar C10 = C01; 47666edf50cSStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 3] + r; 47766edf50cSStefano Zampini const PetscScalar C12 = a[aOff[C_FIELD_ID] + 4]; 47866edf50cSStefano Zampini const PetscScalar C20 = C02; 47966edf50cSStefano Zampini const PetscScalar C21 = C12; 48066edf50cSStefano Zampini const PetscScalar C22 = a[aOff[C_FIELD_ID] + 5] + r; 48166edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 48266edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 48366edf50cSStefano Zampini 48466edf50cSStefano Zampini J[0] = C00 + s; 48566edf50cSStefano Zampini J[1] = C01; 48666edf50cSStefano Zampini J[2] = C02; 48766edf50cSStefano Zampini J[3] = C10; 48866edf50cSStefano Zampini J[4] = C11 + s; 48966edf50cSStefano Zampini J[5] = C12; 49066edf50cSStefano Zampini J[6] = C20; 49166edf50cSStefano Zampini J[7] = C21; 49266edf50cSStefano Zampini J[8] = C22 + s; 49366edf50cSStefano Zampini } 49466edf50cSStefano Zampini 495811d88abSStefano Zampini /* Jacobian for P against gradients of P basis functions and C basis functions */ 496811d88abSStefano Zampini static void JP_1_p1c0(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 497811d88abSStefano Zampini { 49866edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 499811d88abSStefano Zampini 50066edf50cSStefano Zampini J[0] = -gradp[0]; 501811d88abSStefano Zampini J[1] = 0; 50266edf50cSStefano Zampini 50366edf50cSStefano Zampini J[2] = -gradp[1]; 50466edf50cSStefano Zampini J[3] = -gradp[0]; 50566edf50cSStefano Zampini 506811d88abSStefano Zampini J[4] = 0; 50766edf50cSStefano Zampini J[5] = -gradp[1]; 508811d88abSStefano Zampini } 509811d88abSStefano Zampini 51066edf50cSStefano Zampini static void JP_1_p1c0_3d(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, PetscReal u_tShift, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar J[]) 511811d88abSStefano Zampini { 51266edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 51366edf50cSStefano Zampini 51466edf50cSStefano Zampini J[0] = -gradp[0]; 51566edf50cSStefano Zampini J[1] = 0; 51666edf50cSStefano Zampini J[2] = 0; 51766edf50cSStefano Zampini 51866edf50cSStefano Zampini J[3] = -gradp[1]; 51966edf50cSStefano Zampini J[4] = -gradp[0]; 52066edf50cSStefano Zampini J[5] = 0; 52166edf50cSStefano Zampini 52266edf50cSStefano Zampini J[6] = -gradp[2]; 52366edf50cSStefano Zampini J[7] = 0; 52466edf50cSStefano Zampini J[8] = -gradp[0]; 52566edf50cSStefano Zampini 52666edf50cSStefano Zampini J[9] = 0; 52766edf50cSStefano Zampini J[10] = -gradp[1]; 52866edf50cSStefano Zampini J[11] = 0; 52966edf50cSStefano Zampini 53066edf50cSStefano Zampini J[12] = 0; 53166edf50cSStefano Zampini J[13] = -gradp[2]; 53266edf50cSStefano Zampini J[14] = -gradp[1]; 53366edf50cSStefano Zampini 53466edf50cSStefano Zampini J[15] = 0; 53566edf50cSStefano Zampini J[16] = 0; 53666edf50cSStefano Zampini J[17] = -gradp[2]; 53766edf50cSStefano Zampini } 53866edf50cSStefano Zampini 53966edf50cSStefano Zampini /* a collection of gaussian, Dirac-like, source term S(x) = scale * cos(2*pi*(frequency*t + phase)) * exp(-w*||x - x0||^2) */ 54066edf50cSStefano Zampini typedef struct { 54166edf50cSStefano Zampini PetscInt n; 54266edf50cSStefano Zampini PetscReal *x0; 54366edf50cSStefano Zampini PetscReal *w; 54466edf50cSStefano Zampini PetscReal *k; 54566edf50cSStefano Zampini PetscReal *p; 54666edf50cSStefano Zampini PetscReal *r; 54766edf50cSStefano Zampini } MultiSourceCtx; 54866edf50cSStefano Zampini 54966edf50cSStefano Zampini typedef struct { 55066edf50cSStefano Zampini PetscReal x0[3]; 55166edf50cSStefano Zampini PetscReal w; 55266edf50cSStefano Zampini PetscReal k; 55366edf50cSStefano Zampini PetscReal p; 55466edf50cSStefano Zampini PetscReal r; 55566edf50cSStefano Zampini } SingleSourceCtx; 55666edf50cSStefano Zampini 55766edf50cSStefano Zampini static PetscErrorCode gaussian(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx) 55866edf50cSStefano Zampini { 55966edf50cSStefano Zampini SingleSourceCtx *s = (SingleSourceCtx *)ctx; 56066edf50cSStefano Zampini const PetscReal *x0 = s->x0; 56166edf50cSStefano Zampini const PetscReal w = s->w; 56266edf50cSStefano Zampini const PetscReal k = s->k; /* frequency */ 56366edf50cSStefano Zampini const PetscReal p = s->p; /* phase */ 56466edf50cSStefano Zampini const PetscReal r = s->r; /* scale */ 565811d88abSStefano Zampini PetscReal n = 0; 566811d88abSStefano Zampini 567811d88abSStefano Zampini for (PetscInt d = 0; d < dim; ++d) n += (x[d] - x0[d]) * (x[d] - x0[d]); 56866edf50cSStefano Zampini u[0] = r * PetscCosReal(2 * PETSC_PI * (k * time + p)) * PetscExpReal(-w * n); 569811d88abSStefano Zampini return PETSC_SUCCESS; 570811d88abSStefano Zampini } 571811d88abSStefano Zampini 57266edf50cSStefano Zampini static PetscErrorCode source(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx) 573811d88abSStefano Zampini { 57466edf50cSStefano Zampini MultiSourceCtx *s = (MultiSourceCtx *)ctx; 575811d88abSStefano Zampini 57666edf50cSStefano Zampini u[0] = 0.0; 57766edf50cSStefano Zampini for (PetscInt i = 0; i < s->n; i++) { 57866edf50cSStefano Zampini SingleSourceCtx sctx; 57966edf50cSStefano Zampini PetscScalar ut[1]; 58066edf50cSStefano Zampini 58166edf50cSStefano Zampini sctx.x0[0] = s->x0[dim * i]; 58266edf50cSStefano Zampini sctx.x0[1] = s->x0[dim * i + 1]; 58366edf50cSStefano Zampini sctx.x0[2] = dim > 2 ? s->x0[dim * i + 2] : 0.0; 58466edf50cSStefano Zampini sctx.w = s->w[i]; 58566edf50cSStefano Zampini sctx.k = s->k[i]; 58666edf50cSStefano Zampini sctx.p = s->p[i]; 58766edf50cSStefano Zampini sctx.r = s->r[i]; 58866edf50cSStefano Zampini 58966edf50cSStefano Zampini PetscCall(gaussian(dim, time, x, Nf, ut, &sctx)); 59066edf50cSStefano Zampini 591811d88abSStefano Zampini u[0] += ut[0]; 59266edf50cSStefano Zampini } 593811d88abSStefano Zampini return PETSC_SUCCESS; 594811d88abSStefano Zampini } 595811d88abSStefano Zampini 596811d88abSStefano Zampini /* functionals to be integrated: average -> \int_\Omega u dx */ 597811d88abSStefano Zampini static void average(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]) 598811d88abSStefano Zampini { 59966edf50cSStefano Zampini const PetscInt fid = (PetscInt)PetscRealPart(constants[numConstants]); 60066edf50cSStefano Zampini obj[0] = u[uOff[fid]]; 601811d88abSStefano Zampini } 602811d88abSStefano Zampini 60366edf50cSStefano Zampini /* functionals to be integrated: volume -> \int_\Omega dx */ 60466edf50cSStefano Zampini static void volume(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]) 605811d88abSStefano Zampini { 60666edf50cSStefano Zampini obj[0] = 1; 607811d88abSStefano Zampini } 608811d88abSStefano Zampini 609811d88abSStefano Zampini /* functionals to be integrated: energy -> D^2/2 * ||\nabla C||^2 + c^2\nabla p * (r + C) * \nabla p + \alpha/ \gamma * ||C||^\gamma */ 610811d88abSStefano Zampini static void energy(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]) 611811d88abSStefano Zampini { 612811d88abSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 613811d88abSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 614811d88abSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 615811d88abSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 61666edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 61766edf50cSStefano Zampini 61866edf50cSStefano Zampini if (dim == 2) { 619811d88abSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 620811d88abSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 621811d88abSStefano Zampini const PetscScalar C10 = C01; 622811d88abSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2]; 62366edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 62466edf50cSStefano Zampini const PetscScalar *gradC00 = u_x + uOff_x[C_FIELD_ID]; 62566edf50cSStefano Zampini const PetscScalar *gradC01 = u_x + uOff_x[C_FIELD_ID] + 2; 62666edf50cSStefano Zampini const PetscScalar *gradC11 = u_x + uOff_x[C_FIELD_ID] + 4; 62766edf50cSStefano Zampini const PetscScalar normC = NORM2C(C00, C01, C11) + eps; 628811d88abSStefano Zampini const PetscScalar normgradC = NORM2C(gradC00[0], gradC01[0], gradC11[0]) + NORM2C(gradC00[1], gradC01[1], gradC11[1]); 629811d88abSStefano Zampini const PetscScalar nexp = gamma / 2.0; 630811d88abSStefano Zampini 631811d88abSStefano Zampini const PetscScalar t0 = PetscSqr(D) / 2.0 * normgradC; 63266edf50cSStefano Zampini const PetscScalar t1 = gradp[0] * ((C00 + r) * gradp[0] + C01 * gradp[1]) + gradp[1] * (C10 * gradp[0] + (C11 + r) * gradp[1]); 63366edf50cSStefano Zampini const PetscScalar t2 = alpha / gamma * PetscPowScalar(normC, nexp); 63466edf50cSStefano Zampini 63566edf50cSStefano Zampini obj[0] = t0 + t1 + t2; 63666edf50cSStefano Zampini } else { 63766edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 63866edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 63966edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 64066edf50cSStefano Zampini const PetscScalar C10 = C01; 64166edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3]; 64266edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 64366edf50cSStefano Zampini const PetscScalar C20 = C02; 64466edf50cSStefano Zampini const PetscScalar C21 = C12; 64566edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5]; 64666edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 64766edf50cSStefano Zampini const PetscScalar *gradC00 = u_x + uOff_x[C_FIELD_ID]; 64866edf50cSStefano Zampini const PetscScalar *gradC01 = u_x + uOff_x[C_FIELD_ID] + 3; 64966edf50cSStefano Zampini const PetscScalar *gradC02 = u_x + uOff_x[C_FIELD_ID] + 6; 65066edf50cSStefano Zampini const PetscScalar *gradC11 = u_x + uOff_x[C_FIELD_ID] + 9; 65166edf50cSStefano Zampini const PetscScalar *gradC12 = u_x + uOff_x[C_FIELD_ID] + 12; 65266edf50cSStefano Zampini const PetscScalar *gradC22 = u_x + uOff_x[C_FIELD_ID] + 15; 65366edf50cSStefano Zampini const PetscScalar normC = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 65466edf50cSStefano Zampini const PetscScalar normgradC = NORM2C_3d(gradC00[0], gradC01[0], gradC02[0], gradC11[0], gradC12[0], gradC22[0]) + NORM2C_3d(gradC00[1], gradC01[1], gradC02[1], gradC11[1], gradC12[1], gradC22[1]) + NORM2C_3d(gradC00[2], gradC01[2], gradC02[2], gradC11[2], gradC12[2], gradC22[2]); 65566edf50cSStefano Zampini const PetscScalar nexp = gamma / 2.0; 65666edf50cSStefano Zampini 65766edf50cSStefano Zampini const PetscScalar t0 = PetscSqr(D) / 2.0 * normgradC; 65866edf50cSStefano Zampini const PetscScalar t1 = gradp[0] * ((C00 + r) * gradp[0] + C01 * gradp[1] + C02 * gradp[2]) + gradp[1] * (C10 * gradp[0] + (C11 + r) * gradp[1] + C12 * gradp[2]) + gradp[2] * (C20 * gradp[0] + C21 * gradp[1] + (C22 + r) * gradp[2]); 659811d88abSStefano Zampini const PetscScalar t2 = alpha / gamma * PetscPowScalar(normC, nexp); 660811d88abSStefano Zampini 661811d88abSStefano Zampini obj[0] = t0 + t1 + t2; 662811d88abSStefano Zampini } 66366edf50cSStefano Zampini } 664811d88abSStefano Zampini 66566edf50cSStefano Zampini /* functionals to be integrated: ellipticity_fail_private -> see below */ 66666edf50cSStefano Zampini static void ellipticity_fail_private(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[], PetscBool add_reg) 66766edf50cSStefano Zampini { 66866edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 66966edf50cSStefano Zampini PetscReal eigs[3]; 67066edf50cSStefano Zampini PetscScalar C00, C01, C02 = 0.0, C11, C12 = 0.0, C22 = 0.0; 67166edf50cSStefano Zampini const PetscReal r = add_reg ? PetscRealPart(constants[R_ID]) : 0.0; 67266edf50cSStefano Zampini 67366edf50cSStefano Zampini if (dim == 2) { 67466edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]] + r; 67566edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 67666edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 2] + r; 67766edf50cSStefano Zampini } else { 67866edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]] + r; 67966edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 68066edf50cSStefano Zampini C02 = u[uOff[C_FIELD_ID] + 2]; 68166edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 3] + r; 68266edf50cSStefano Zampini C12 = u[uOff[C_FIELD_ID] + 4]; 68366edf50cSStefano Zampini C22 = u[uOff[C_FIELD_ID] + 5] + r; 68466edf50cSStefano Zampini } 68566edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 68666edf50cSStefano Zampini if (eigs[0] < 0 || eigs[1] < 0 || eigs[2] < 0) obj[0] = -PetscMin(eigs[0], PetscMin(eigs[1], eigs[2])); 68766edf50cSStefano Zampini else obj[0] = 0.0; 68866edf50cSStefano Zampini #else 68966edf50cSStefano Zampini obj[0] = 0.0; 69066edf50cSStefano Zampini #endif 69166edf50cSStefano Zampini } 69266edf50cSStefano Zampini 69366edf50cSStefano Zampini /* functionals to be integrated: ellipticity_fail -> 0 means C is elliptic at quadrature point, otherwise it returns 1 */ 694811d88abSStefano Zampini static void ellipticity_fail(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]) 695811d88abSStefano Zampini { 69666edf50cSStefano Zampini ellipticity_fail_private(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, t, x, numConstants, constants, obj, PETSC_FALSE); 69766edf50cSStefano Zampini if (PetscAbsScalar(obj[0]) > 0.0) obj[0] = 1.0; 69866edf50cSStefano Zampini } 699811d88abSStefano Zampini 70066edf50cSStefano Zampini /* functionals to be integrated: jacobian_fail -> 0 means C + r is elliptic at quadrature point, otherwise it returns the absolute value of the most negative eigenvalue */ 70166edf50cSStefano Zampini static void jacobian_fail(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar obj[]) 70266edf50cSStefano Zampini { 70366edf50cSStefano Zampini ellipticity_fail_private(dim, Nf, NfAux, uOff, uOff_x, u, u_t, u_x, aOff, aOff_x, a, a_t, a_x, t, x, numConstants, constants, obj, PETSC_TRUE); 704811d88abSStefano Zampini } 705811d88abSStefano Zampini 706811d88abSStefano Zampini /* initial conditions for C: eq. 16 */ 707811d88abSStefano Zampini static PetscErrorCode initial_conditions_C_0(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 708811d88abSStefano Zampini { 70966edf50cSStefano Zampini if (dim == 2) { 710811d88abSStefano Zampini u[0] = 1; 711811d88abSStefano Zampini u[1] = 0; 712811d88abSStefano Zampini u[2] = 1; 71366edf50cSStefano Zampini } else { 71466edf50cSStefano Zampini u[0] = 1; 71566edf50cSStefano Zampini u[1] = 0; 71666edf50cSStefano Zampini u[2] = 0; 71766edf50cSStefano Zampini u[3] = 1; 71866edf50cSStefano Zampini u[4] = 0; 71966edf50cSStefano Zampini u[5] = 1; 72066edf50cSStefano Zampini } 721811d88abSStefano Zampini return PETSC_SUCCESS; 722811d88abSStefano Zampini } 723811d88abSStefano Zampini 724811d88abSStefano Zampini /* initial conditions for C: eq. 17 */ 725811d88abSStefano Zampini static PetscErrorCode initial_conditions_C_1(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 726811d88abSStefano Zampini { 727811d88abSStefano Zampini const PetscReal x = xx[0]; 728811d88abSStefano Zampini const PetscReal y = xx[1]; 729811d88abSStefano Zampini 73066edf50cSStefano Zampini if (dim == 3) return PETSC_ERR_SUP; 731811d88abSStefano Zampini u[0] = (2 - PetscAbsReal(x + y)) * PetscExpReal(-10 * PetscAbsReal(x - y)); 732811d88abSStefano Zampini u[1] = 0; 733811d88abSStefano Zampini u[2] = (2 - PetscAbsReal(x + y)) * PetscExpReal(-10 * PetscAbsReal(x - y)); 734811d88abSStefano Zampini return PETSC_SUCCESS; 735811d88abSStefano Zampini } 736811d88abSStefano Zampini 737811d88abSStefano Zampini /* initial conditions for C: eq. 18 */ 738811d88abSStefano Zampini static PetscErrorCode initial_conditions_C_2(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 739811d88abSStefano Zampini { 740811d88abSStefano Zampini u[0] = 0; 741811d88abSStefano Zampini u[1] = 0; 742811d88abSStefano Zampini u[2] = 0; 74366edf50cSStefano Zampini if (dim == 3) { 74466edf50cSStefano Zampini u[3] = 0; 74566edf50cSStefano Zampini u[4] = 0; 74666edf50cSStefano Zampini u[5] = 0; 74766edf50cSStefano Zampini } 748811d88abSStefano Zampini return PETSC_SUCCESS; 749811d88abSStefano Zampini } 750811d88abSStefano Zampini 75166edf50cSStefano Zampini /* random initial conditions for the diagonal of C */ 75266edf50cSStefano Zampini static PetscErrorCode initial_conditions_C_random(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 753811d88abSStefano Zampini { 75466edf50cSStefano Zampini PetscScalar vals[3]; 75566edf50cSStefano Zampini PetscRandom r = (PetscRandom)ctx; 756811d88abSStefano Zampini 75766edf50cSStefano Zampini PetscCall(PetscRandomGetValues(r, dim, vals)); 75866edf50cSStefano Zampini if (dim == 2) { 75966edf50cSStefano Zampini u[0] = vals[0]; 76066edf50cSStefano Zampini u[1] = 0; 76166edf50cSStefano Zampini u[2] = vals[1]; 76266edf50cSStefano Zampini } else { 76366edf50cSStefano Zampini u[0] = vals[0]; 76466edf50cSStefano Zampini u[1] = 0; 76566edf50cSStefano Zampini u[2] = 0; 76666edf50cSStefano Zampini u[3] = vals[1]; 76766edf50cSStefano Zampini u[4] = 0; 76866edf50cSStefano Zampini u[5] = vals[2]; 769811d88abSStefano Zampini } 77066edf50cSStefano Zampini return PETSC_SUCCESS; 771811d88abSStefano Zampini } 772811d88abSStefano Zampini 773811d88abSStefano Zampini /* functionals to be sampled: zero */ 774811d88abSStefano Zampini static void zero(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]) 775811d88abSStefano Zampini { 776811d88abSStefano Zampini f[0] = 0.0; 777811d88abSStefano Zampini } 778811d88abSStefano Zampini 77966edf50cSStefano Zampini /* functionals to be sampled: - (C + r) * \grad p */ 78066edf50cSStefano Zampini static void flux(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]) 78166edf50cSStefano Zampini { 78266edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 78366edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 78466edf50cSStefano Zampini 78566edf50cSStefano Zampini if (dim == 2) { 78666edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 78766edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 78866edf50cSStefano Zampini const PetscScalar C10 = C01; 78966edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2] + r; 79066edf50cSStefano Zampini 79166edf50cSStefano Zampini f[0] = -C00 * gradp[0] - C01 * gradp[1]; 79266edf50cSStefano Zampini f[1] = -C10 * gradp[0] - C11 * gradp[1]; 79366edf50cSStefano Zampini } else { 79466edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 79566edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 79666edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 79766edf50cSStefano Zampini const PetscScalar C10 = C01; 79866edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 79966edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 80066edf50cSStefano Zampini const PetscScalar C20 = C02; 80166edf50cSStefano Zampini const PetscScalar C21 = C12; 80266edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 80366edf50cSStefano Zampini 80466edf50cSStefano Zampini f[0] = -C00 * gradp[0] - C01 * gradp[1] - C02 * gradp[2]; 80566edf50cSStefano Zampini f[1] = -C10 * gradp[0] - C11 * gradp[1] - C12 * gradp[2]; 80666edf50cSStefano Zampini f[2] = -C20 * gradp[0] - C21 * gradp[1] - C22 * gradp[2]; 80766edf50cSStefano Zampini } 80866edf50cSStefano Zampini } 80966edf50cSStefano Zampini 81066edf50cSStefano Zampini /* functionals to be sampled: ||C|| */ 81166edf50cSStefano Zampini static void normc(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]) 81266edf50cSStefano Zampini { 81366edf50cSStefano Zampini if (dim == 2) { 81466edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 81566edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 81666edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2]; 81766edf50cSStefano Zampini 81866edf50cSStefano Zampini f[0] = PetscSqrtReal(PetscRealPart(NORM2C(C00, C01, C11))); 81966edf50cSStefano Zampini } else { 82066edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 82166edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 82266edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 82366edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3]; 82466edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 82566edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5]; 82666edf50cSStefano Zampini 82766edf50cSStefano Zampini f[0] = PetscSqrtReal(PetscRealPart(NORM2C_3d(C00, C01, C02, C11, C12, C22))); 82866edf50cSStefano Zampini } 82966edf50cSStefano Zampini } 83066edf50cSStefano Zampini 83166edf50cSStefano Zampini /* functionals to be sampled: eigenvalues of C */ 83266edf50cSStefano Zampini static void eigsc(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]) 83366edf50cSStefano Zampini { 83466edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 83566edf50cSStefano Zampini PetscReal eigs[3]; 83666edf50cSStefano Zampini PetscScalar C00, C01, C02 = 0.0, C11, C12 = 0.0, C22 = 0.0; 83766edf50cSStefano Zampini if (dim == 2) { 83866edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]]; 83966edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 84066edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 2]; 84166edf50cSStefano Zampini } else { 84266edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]]; 84366edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 84466edf50cSStefano Zampini C02 = u[uOff[C_FIELD_ID] + 2]; 84566edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 3]; 84666edf50cSStefano Zampini C12 = u[uOff[C_FIELD_ID] + 4]; 84766edf50cSStefano Zampini C22 = u[uOff[C_FIELD_ID] + 5]; 84866edf50cSStefano Zampini } 84966edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 85066edf50cSStefano Zampini PetscCallVoid(PetscSortReal(dim, eigs)); 85166edf50cSStefano Zampini for (PetscInt d = 0; d < dim; d++) f[d] = eigs[d]; 85266edf50cSStefano Zampini #else 85366edf50cSStefano Zampini for (PetscInt d = 0; d < dim; d++) f[d] = 0; 85466edf50cSStefano Zampini #endif 85566edf50cSStefano Zampini } 85666edf50cSStefano Zampini 857811d88abSStefano Zampini /* functions to be sampled: zero function */ 858811d88abSStefano Zampini static PetscErrorCode zerof(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 859811d88abSStefano Zampini { 860811d88abSStefano Zampini for (PetscInt d = 0; d < Nc; ++d) u[d] = 0.0; 861811d88abSStefano Zampini return PETSC_SUCCESS; 862811d88abSStefano Zampini } 863811d88abSStefano Zampini 864811d88abSStefano Zampini /* functions to be sampled: constant function */ 865811d88abSStefano Zampini static PetscErrorCode constantf(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 866811d88abSStefano Zampini { 86766edf50cSStefano Zampini for (PetscInt d = 0; d < Nc; ++d) u[d] = 1.0; 868811d88abSStefano Zampini return PETSC_SUCCESS; 869811d88abSStefano Zampini } 870811d88abSStefano Zampini 871811d88abSStefano Zampini /* application context: customizable parameters */ 872811d88abSStefano Zampini typedef struct { 87366edf50cSStefano Zampini PetscInt dim; 87466edf50cSStefano Zampini PetscBool simplex; 875811d88abSStefano Zampini PetscReal r; 876811d88abSStefano Zampini PetscReal eps; 877811d88abSStefano Zampini PetscReal alpha; 878811d88abSStefano Zampini PetscReal gamma; 879811d88abSStefano Zampini PetscReal D; 88066edf50cSStefano Zampini PetscReal domain_volume; 881811d88abSStefano Zampini PetscInt ic_num; 88266edf50cSStefano Zampini PetscBool split; 883204aa523SStefano Zampini PetscBool lump; 884811d88abSStefano Zampini PetscBool amr; 885811d88abSStefano Zampini PetscBool load; 886811d88abSStefano Zampini char load_filename[PETSC_MAX_PATH_LEN]; 887811d88abSStefano Zampini PetscBool save; 888811d88abSStefano Zampini char save_filename[PETSC_MAX_PATH_LEN]; 889811d88abSStefano Zampini PetscInt save_every; 890811d88abSStefano Zampini PetscBool test_restart; 891204aa523SStefano Zampini PetscInt fix_c; 89266edf50cSStefano Zampini MultiSourceCtx *source_ctx; 89366edf50cSStefano Zampini DM view_dm; 89466edf50cSStefano Zampini TSMonitorVTKCtx view_vtk_ctx; 89566edf50cSStefano Zampini PetscViewerAndFormat *view_hdf5_ctx; 89666edf50cSStefano Zampini PetscInt diagnostic_num; 89766edf50cSStefano Zampini PetscReal view_times[64]; 89866edf50cSStefano Zampini PetscInt view_times_n, view_times_k; 89966edf50cSStefano Zampini PetscReal function_domain_error_tol; 90066edf50cSStefano Zampini VecScatter subsct[NUM_FIELDS]; 90166edf50cSStefano Zampini Vec subvec[NUM_FIELDS]; 90266edf50cSStefano Zampini PetscBool monitor_norms; 90366edf50cSStefano Zampini PetscBool exclude_potential_lte; 90466edf50cSStefano Zampini 90566edf50cSStefano Zampini /* hack: need some more plumbing in the library */ 90666edf50cSStefano Zampini SNES snes; 907811d88abSStefano Zampini } AppCtx; 908811d88abSStefano Zampini 909811d88abSStefano Zampini /* process command line options */ 91066edf50cSStefano Zampini #include <petsc/private/tsimpl.h> /* To access TSMonitorVTKCtx */ 911811d88abSStefano Zampini static PetscErrorCode ProcessOptions(AppCtx *options) 912811d88abSStefano Zampini { 91366edf50cSStefano Zampini char vtkmonfilename[PETSC_MAX_PATH_LEN]; 91466edf50cSStefano Zampini char hdf5monfilename[PETSC_MAX_PATH_LEN]; 91566edf50cSStefano Zampini PetscInt tmp; 91666edf50cSStefano Zampini PetscBool flg; 917811d88abSStefano Zampini 918811d88abSStefano Zampini PetscFunctionBeginUser; 91966edf50cSStefano Zampini options->dim = 2; 920811d88abSStefano Zampini options->r = 1.e-1; 921811d88abSStefano Zampini options->eps = 1.e-3; 922811d88abSStefano Zampini options->alpha = 0.75; 923811d88abSStefano Zampini options->gamma = 0.75; 924811d88abSStefano Zampini options->D = 1.e-2; 925811d88abSStefano Zampini options->ic_num = 0; 92666edf50cSStefano Zampini options->split = PETSC_FALSE; 927204aa523SStefano Zampini options->lump = PETSC_FALSE; 928811d88abSStefano Zampini options->amr = PETSC_FALSE; 929811d88abSStefano Zampini options->load = PETSC_FALSE; 930811d88abSStefano Zampini options->save = PETSC_FALSE; 931811d88abSStefano Zampini options->save_every = -1; 932811d88abSStefano Zampini options->test_restart = PETSC_FALSE; 93366edf50cSStefano Zampini options->fix_c = 1; /* 1 means only Jac, 2 means function and Jac, < 0 means raise SNESFunctionDomainError when C+r is not posdef */ 93466edf50cSStefano Zampini options->view_vtk_ctx = NULL; 93566edf50cSStefano Zampini options->view_hdf5_ctx = NULL; 93666edf50cSStefano Zampini options->view_dm = NULL; 93766edf50cSStefano Zampini options->diagnostic_num = 1; 93866edf50cSStefano Zampini options->function_domain_error_tol = -1; 93966edf50cSStefano Zampini options->monitor_norms = PETSC_FALSE; 94066edf50cSStefano Zampini options->exclude_potential_lte = PETSC_FALSE; 94166edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 94266edf50cSStefano Zampini options->subsct[i] = NULL; 94366edf50cSStefano Zampini options->subvec[i] = NULL; 94466edf50cSStefano Zampini } 94566edf50cSStefano Zampini for (PetscInt i = 0; i < 64; i++) options->view_times[i] = PETSC_MAX_REAL; 946811d88abSStefano Zampini 947811d88abSStefano Zampini PetscOptionsBegin(PETSC_COMM_WORLD, "", __FILE__, "DMPLEX"); 94866edf50cSStefano Zampini PetscCall(PetscOptionsInt("-dim", "space dimension", __FILE__, options->dim, &options->dim, NULL)); 949811d88abSStefano Zampini PetscCall(PetscOptionsReal("-alpha", "alpha", __FILE__, options->alpha, &options->alpha, NULL)); 950811d88abSStefano Zampini PetscCall(PetscOptionsReal("-gamma", "gamma", __FILE__, options->gamma, &options->gamma, NULL)); 951811d88abSStefano Zampini PetscCall(PetscOptionsReal("-d", "D", __FILE__, options->D, &options->D, NULL)); 952811d88abSStefano Zampini PetscCall(PetscOptionsReal("-eps", "eps", __FILE__, options->eps, &options->eps, NULL)); 953811d88abSStefano Zampini PetscCall(PetscOptionsReal("-r", "r", __FILE__, options->r, &options->r, NULL)); 954811d88abSStefano Zampini PetscCall(PetscOptionsInt("-ic_num", "ic_num", __FILE__, options->ic_num, &options->ic_num, NULL)); 95566edf50cSStefano Zampini PetscCall(PetscOptionsBool("-split", "Operator splitting", __FILE__, options->split, &options->split, NULL)); 956204aa523SStefano Zampini PetscCall(PetscOptionsBool("-lump", "use mass lumping", __FILE__, options->lump, &options->lump, NULL)); 95766edf50cSStefano Zampini PetscCall(PetscOptionsInt("-fix_c", "Fix conductivity: shift to always be positive semi-definite or raise domain error", __FILE__, options->fix_c, &options->fix_c, NULL)); 958811d88abSStefano Zampini PetscCall(PetscOptionsBool("-amr", "use adaptive mesh refinement", __FILE__, options->amr, &options->amr, NULL)); 95966edf50cSStefano Zampini PetscCall(PetscOptionsReal("-domain_error_tol", "domain error tolerance", __FILE__, options->function_domain_error_tol, &options->function_domain_error_tol, NULL)); 960811d88abSStefano Zampini PetscCall(PetscOptionsBool("-test_restart", "test restarting files", __FILE__, options->test_restart, &options->test_restart, NULL)); 961811d88abSStefano Zampini if (!options->test_restart) { 962811d88abSStefano Zampini PetscCall(PetscOptionsString("-load", "filename with data to be loaded for restarting", __FILE__, options->load_filename, options->load_filename, PETSC_MAX_PATH_LEN, &options->load)); 963811d88abSStefano Zampini PetscCall(PetscOptionsString("-save", "filename with data to be saved for restarting", __FILE__, options->save_filename, options->save_filename, PETSC_MAX_PATH_LEN, &options->save)); 964811d88abSStefano Zampini if (options->save) PetscCall(PetscOptionsInt("-save_every", "save every n timestep (-1 saves only the last)", __FILE__, options->save_every, &options->save_every, NULL)); 965811d88abSStefano Zampini } 96666edf50cSStefano Zampini PetscCall(PetscOptionsBool("-exclude_potential_lte", "exclude potential from LTE", __FILE__, options->exclude_potential_lte, &options->exclude_potential_lte, NULL)); 96766edf50cSStefano Zampini options->view_times_k = 0; 96866edf50cSStefano Zampini options->view_times_n = 0; 96966edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-monitor_times", "Save at specific times", NULL, options->view_times, (tmp = 64, &tmp), &flg)); 97066edf50cSStefano Zampini if (flg) options->view_times_n = tmp; 97166edf50cSStefano Zampini 97266edf50cSStefano Zampini PetscCall(PetscOptionsString("-monitor_vtk", "Dump VTK file for diagnostic", "TSMonitorSolutionVTK", NULL, vtkmonfilename, sizeof(vtkmonfilename), &flg)); 97366edf50cSStefano Zampini if (flg) { 97466edf50cSStefano Zampini PetscCall(TSMonitorSolutionVTKCtxCreate(vtkmonfilename, &options->view_vtk_ctx)); 97566edf50cSStefano Zampini PetscCall(PetscOptionsInt("-monitor_vtk_interval", "Save every interval time steps", NULL, options->view_vtk_ctx->interval, &options->view_vtk_ctx->interval, NULL)); 97666edf50cSStefano Zampini } 97766edf50cSStefano Zampini PetscCall(PetscOptionsString("-monitor_hdf5", "Dump HDF5 file for diagnostic", "TSMonitorSolution", NULL, hdf5monfilename, sizeof(hdf5monfilename), &flg)); 97866edf50cSStefano Zampini PetscCall(PetscOptionsInt("-monitor_diagnostic_num", "Number of diagnostics to be computed", __FILE__, options->diagnostic_num, &options->diagnostic_num, NULL)); 97966edf50cSStefano Zampini 98066edf50cSStefano Zampini if (flg) { 98166edf50cSStefano Zampini #if defined(PETSC_HAVE_HDF5) 98266edf50cSStefano Zampini PetscViewer viewer; 98366edf50cSStefano Zampini 98466edf50cSStefano Zampini PetscCall(PetscViewerHDF5Open(PETSC_COMM_WORLD, hdf5monfilename, FILE_MODE_WRITE, &viewer)); 98566edf50cSStefano Zampini PetscCall(PetscViewerAndFormatCreate(viewer, PETSC_VIEWER_HDF5_VIZ, &options->view_hdf5_ctx)); 98666edf50cSStefano Zampini options->view_hdf5_ctx->view_interval = 1; 98766edf50cSStefano Zampini PetscCall(PetscOptionsInt("-monitor_hdf5_interval", "Save every interval time steps", NULL, options->view_hdf5_ctx->view_interval, &options->view_hdf5_ctx->view_interval, NULL)); 98866edf50cSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 98966edf50cSStefano Zampini #else 99066edf50cSStefano Zampini SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Needs HDF5 support. Please reconfigure using --download-hdf5"); 99166edf50cSStefano Zampini #endif 99266edf50cSStefano Zampini } 99366edf50cSStefano Zampini PetscCall(PetscOptionsBool("-monitor_norms", "Monitor separate SNES norms", __FILE__, options->monitor_norms, &options->monitor_norms, NULL)); 99466edf50cSStefano Zampini 99566edf50cSStefano Zampini /* source options */ 99666edf50cSStefano Zampini PetscCall(PetscNew(&options->source_ctx)); 99766edf50cSStefano Zampini options->source_ctx->n = 1; 99866edf50cSStefano Zampini 99966edf50cSStefano Zampini PetscCall(PetscOptionsInt("-source_num", "number of sources", __FILE__, options->source_ctx->n, &options->source_ctx->n, NULL)); 100066edf50cSStefano Zampini tmp = options->source_ctx->n; 100166edf50cSStefano Zampini PetscCall(PetscMalloc5(options->dim * tmp, &options->source_ctx->x0, tmp, &options->source_ctx->w, tmp, &options->source_ctx->k, tmp, &options->source_ctx->p, tmp, &options->source_ctx->r)); 100266edf50cSStefano Zampini for (PetscInt i = 0; i < options->source_ctx->n; i++) { 1003ac530a7eSPierre Jolivet for (PetscInt d = 0; d < options->dim; d++) options->source_ctx->x0[options->dim * i + d] = 0.25; 100466edf50cSStefano Zampini options->source_ctx->w[i] = 500; 100566edf50cSStefano Zampini options->source_ctx->k[i] = 0; 100666edf50cSStefano Zampini options->source_ctx->p[i] = 0; 100766edf50cSStefano Zampini options->source_ctx->r[i] = 1; 100866edf50cSStefano Zampini } 100966edf50cSStefano Zampini tmp = options->dim * options->source_ctx->n; 101066edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_x0", "source location", __FILE__, options->source_ctx->x0, &tmp, NULL)); 101166edf50cSStefano Zampini tmp = options->source_ctx->n; 101266edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_w", "source factor", __FILE__, options->source_ctx->w, &tmp, NULL)); 101366edf50cSStefano Zampini tmp = options->source_ctx->n; 101466edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_k", "source frequency", __FILE__, options->source_ctx->k, &tmp, NULL)); 101566edf50cSStefano Zampini tmp = options->source_ctx->n; 101666edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_p", "source phase", __FILE__, options->source_ctx->p, &tmp, NULL)); 101766edf50cSStefano Zampini tmp = options->source_ctx->n; 101866edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_r", "source scaling", __FILE__, options->source_ctx->r, &tmp, NULL)); 1019811d88abSStefano Zampini PetscOptionsEnd(); 1020811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1021811d88abSStefano Zampini } 1022811d88abSStefano Zampini 1023811d88abSStefano Zampini static PetscErrorCode SaveToFile(DM dm, Vec u, const char *filename) 1024811d88abSStefano Zampini { 1025811d88abSStefano Zampini #if defined(PETSC_HAVE_HDF5) 1026811d88abSStefano Zampini PetscViewerFormat format = PETSC_VIEWER_HDF5_PETSC; 1027811d88abSStefano Zampini PetscViewer viewer; 1028811d88abSStefano Zampini DM cdm = dm; 1029811d88abSStefano Zampini PetscInt numlevels = 0; 1030811d88abSStefano Zampini 1031811d88abSStefano Zampini PetscFunctionBeginUser; 1032811d88abSStefano Zampini while (cdm) { 1033811d88abSStefano Zampini numlevels++; 1034811d88abSStefano Zampini PetscCall(DMGetCoarseDM(cdm, &cdm)); 1035811d88abSStefano Zampini } 1036811d88abSStefano Zampini /* Cannot be set programmatically */ 1037811d88abSStefano Zampini PetscCall(PetscOptionsInsertString(NULL, "-dm_plex_view_hdf5_storage_version 3.0.0")); 1038811d88abSStefano Zampini PetscCall(PetscViewerHDF5Open(PetscObjectComm((PetscObject)dm), filename, FILE_MODE_WRITE, &viewer)); 1039811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "numlevels", PETSC_INT, &numlevels)); 1040811d88abSStefano Zampini PetscCall(PetscViewerPushFormat(viewer, format)); 1041811d88abSStefano Zampini for (PetscInt level = numlevels - 1; level >= 0; level--) { 1042811d88abSStefano Zampini PetscInt cc, rr; 1043811d88abSStefano Zampini PetscBool isRegular, isUniform; 1044811d88abSStefano Zampini const char *dmname; 1045811d88abSStefano Zampini char groupname[PETSC_MAX_PATH_LEN]; 1046811d88abSStefano Zampini 1047811d88abSStefano Zampini PetscCall(PetscSNPrintf(groupname, sizeof(groupname), "level_%" PetscInt_FMT, level)); 1048811d88abSStefano Zampini PetscCall(PetscViewerHDF5PushGroup(viewer, groupname)); 1049811d88abSStefano Zampini PetscCall(PetscObjectGetName((PetscObject)dm, &dmname)); 1050811d88abSStefano Zampini PetscCall(DMGetCoarsenLevel(dm, &cc)); 1051811d88abSStefano Zampini PetscCall(DMGetRefineLevel(dm, &rr)); 1052811d88abSStefano Zampini PetscCall(DMPlexGetRegularRefinement(dm, &isRegular)); 1053811d88abSStefano Zampini PetscCall(DMPlexGetRefinementUniform(dm, &isUniform)); 1054811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "meshname", PETSC_STRING, dmname)); 1055811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "refinelevel", PETSC_INT, &rr)); 1056811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "coarsenlevel", PETSC_INT, &cc)); 1057811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "refRegular", PETSC_BOOL, &isRegular)); 1058811d88abSStefano Zampini PetscCall(PetscViewerHDF5WriteAttribute(viewer, NULL, "refUniform", PETSC_BOOL, &isUniform)); 1059811d88abSStefano Zampini PetscCall(DMPlexTopologyView(dm, viewer)); 1060811d88abSStefano Zampini PetscCall(DMPlexLabelsView(dm, viewer)); 1061811d88abSStefano Zampini PetscCall(DMPlexCoordinatesView(dm, viewer)); 1062811d88abSStefano Zampini PetscCall(DMPlexSectionView(dm, viewer, NULL)); 1063811d88abSStefano Zampini if (level == numlevels - 1) { 1064811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)u, "solution_")); 1065811d88abSStefano Zampini PetscCall(DMPlexGlobalVectorView(dm, viewer, NULL, u)); 1066811d88abSStefano Zampini } 1067811d88abSStefano Zampini if (level) { 1068811d88abSStefano Zampini PetscInt cStart, cEnd, ccStart, ccEnd, cpStart; 1069811d88abSStefano Zampini DMPolytopeType ct; 1070811d88abSStefano Zampini DMPlexTransform tr; 1071811d88abSStefano Zampini DM sdm; 1072811d88abSStefano Zampini PetscScalar *array; 1073811d88abSStefano Zampini PetscSection section; 1074811d88abSStefano Zampini Vec map; 1075811d88abSStefano Zampini IS gis; 1076811d88abSStefano Zampini const PetscInt *gidx; 1077811d88abSStefano Zampini 1078811d88abSStefano Zampini PetscCall(DMGetCoarseDM(dm, &cdm)); 1079811d88abSStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1080811d88abSStefano Zampini PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion)); 1081811d88abSStefano Zampini PetscCall(PetscSectionSetChart(section, cStart, cEnd)); 1082811d88abSStefano Zampini for (PetscInt c = cStart; c < cEnd; c++) PetscCall(PetscSectionSetDof(section, c, 1)); 1083811d88abSStefano Zampini PetscCall(PetscSectionSetUp(section)); 1084811d88abSStefano Zampini 1085811d88abSStefano Zampini PetscCall(DMClone(dm, &sdm)); 1086811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sdm, "pdm")); 1087811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)section, "pdm_section")); 1088811d88abSStefano Zampini PetscCall(DMSetLocalSection(sdm, section)); 1089811d88abSStefano Zampini PetscCall(PetscSectionDestroy(§ion)); 1090811d88abSStefano Zampini 1091811d88abSStefano Zampini PetscCall(DMGetLocalVector(sdm, &map)); 1092811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)map, "pdm_map")); 1093811d88abSStefano Zampini PetscCall(VecGetArray(map, &array)); 1094811d88abSStefano Zampini PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &tr)); 1095811d88abSStefano Zampini PetscCall(DMPlexTransformSetType(tr, DMPLEXREFINEREGULAR)); 1096811d88abSStefano Zampini PetscCall(DMPlexTransformSetDM(tr, cdm)); 1097811d88abSStefano Zampini PetscCall(DMPlexTransformSetFromOptions(tr)); 1098811d88abSStefano Zampini PetscCall(DMPlexTransformSetUp(tr)); 1099811d88abSStefano Zampini PetscCall(DMPlexGetHeightStratum(cdm, 0, &ccStart, &ccEnd)); 1100811d88abSStefano Zampini PetscCall(DMPlexGetChart(cdm, &cpStart, NULL)); 1101811d88abSStefano Zampini PetscCall(DMPlexCreatePointNumbering(cdm, &gis)); 1102811d88abSStefano Zampini PetscCall(ISGetIndices(gis, &gidx)); 1103811d88abSStefano Zampini for (PetscInt c = ccStart; c < ccEnd; c++) { 1104811d88abSStefano Zampini PetscInt *rsize, *rcone, *rornt, Nt; 1105811d88abSStefano Zampini DMPolytopeType *rct; 1106811d88abSStefano Zampini PetscInt gnum = gidx[c - cpStart] >= 0 ? gidx[c - cpStart] : -(gidx[c - cpStart] + 1); 1107811d88abSStefano Zampini 1108811d88abSStefano Zampini PetscCall(DMPlexGetCellType(cdm, c, &ct)); 1109811d88abSStefano Zampini PetscCall(DMPlexTransformCellTransform(tr, ct, c, NULL, &Nt, &rct, &rsize, &rcone, &rornt)); 1110811d88abSStefano Zampini for (PetscInt r = 0; r < rsize[Nt - 1]; ++r) { 1111811d88abSStefano Zampini PetscInt pNew; 1112811d88abSStefano Zampini 1113811d88abSStefano Zampini PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[Nt - 1], c, r, &pNew)); 1114811d88abSStefano Zampini array[pNew - cStart] = gnum; 1115811d88abSStefano Zampini } 1116811d88abSStefano Zampini } 1117811d88abSStefano Zampini PetscCall(ISRestoreIndices(gis, &gidx)); 1118811d88abSStefano Zampini PetscCall(ISDestroy(&gis)); 1119811d88abSStefano Zampini PetscCall(VecRestoreArray(map, &array)); 1120811d88abSStefano Zampini PetscCall(DMPlexTransformDestroy(&tr)); 1121811d88abSStefano Zampini PetscCall(DMPlexSectionView(dm, viewer, sdm)); 1122811d88abSStefano Zampini PetscCall(DMPlexLocalVectorView(dm, viewer, sdm, map)); 1123811d88abSStefano Zampini PetscCall(DMRestoreLocalVector(sdm, &map)); 1124811d88abSStefano Zampini PetscCall(DMDestroy(&sdm)); 1125811d88abSStefano Zampini } 1126811d88abSStefano Zampini PetscCall(PetscViewerHDF5PopGroup(viewer)); 1127811d88abSStefano Zampini PetscCall(DMGetCoarseDM(dm, &dm)); 1128811d88abSStefano Zampini } 1129811d88abSStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 1130811d88abSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 1131811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1132811d88abSStefano Zampini #else 1133811d88abSStefano Zampini SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Needs HDF5 support. Please reconfigure using --download-hdf5"); 1134811d88abSStefano Zampini #endif 1135811d88abSStefano Zampini } 1136811d88abSStefano Zampini 1137811d88abSStefano Zampini static PetscErrorCode LoadFromFile(MPI_Comm comm, const char *filename, DM *odm) 1138811d88abSStefano Zampini { 1139811d88abSStefano Zampini #if defined(PETSC_HAVE_HDF5) 1140811d88abSStefano Zampini PetscViewerFormat format = PETSC_VIEWER_HDF5_PETSC; 1141811d88abSStefano Zampini PetscViewer viewer; 1142811d88abSStefano Zampini DM dm, cdm = NULL; 1143811d88abSStefano Zampini PetscSF sfXC = NULL; 1144811d88abSStefano Zampini PetscInt numlevels = -1; 1145811d88abSStefano Zampini 1146811d88abSStefano Zampini PetscFunctionBeginUser; 1147811d88abSStefano Zampini PetscCall(PetscViewerHDF5Open(comm, filename, FILE_MODE_READ, &viewer)); 1148811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "numlevels", PETSC_INT, NULL, &numlevels)); 1149811d88abSStefano Zampini PetscCall(PetscViewerPushFormat(viewer, format)); 1150811d88abSStefano Zampini for (PetscInt level = 0; level < numlevels; level++) { 1151811d88abSStefano Zampini char groupname[PETSC_MAX_PATH_LEN], *dmname; 1152811d88abSStefano Zampini PetscSF sfXB, sfBC, sfG; 1153811d88abSStefano Zampini PetscPartitioner part; 1154811d88abSStefano Zampini PetscInt rr, cc; 1155811d88abSStefano Zampini PetscBool isRegular, isUniform; 1156811d88abSStefano Zampini 1157811d88abSStefano Zampini PetscCall(DMCreate(comm, &dm)); 1158811d88abSStefano Zampini PetscCall(DMSetType(dm, DMPLEX)); 1159811d88abSStefano Zampini PetscCall(PetscSNPrintf(groupname, sizeof(groupname), "level_%" PetscInt_FMT, level)); 1160811d88abSStefano Zampini PetscCall(PetscViewerHDF5PushGroup(viewer, groupname)); 1161811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "meshname", PETSC_STRING, NULL, &dmname)); 1162811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "refinelevel", PETSC_INT, NULL, &rr)); 1163811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "coarsenlevel", PETSC_INT, NULL, &cc)); 1164811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "refRegular", PETSC_BOOL, NULL, &isRegular)); 1165811d88abSStefano Zampini PetscCall(PetscViewerHDF5ReadAttribute(viewer, NULL, "refUniform", PETSC_BOOL, NULL, &isUniform)); 1166811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)dm, dmname)); 1167811d88abSStefano Zampini PetscCall(DMPlexTopologyLoad(dm, viewer, &sfXB)); 1168811d88abSStefano Zampini PetscCall(DMPlexLabelsLoad(dm, viewer, sfXB)); 1169811d88abSStefano Zampini PetscCall(DMPlexCoordinatesLoad(dm, viewer, sfXB)); 1170811d88abSStefano Zampini PetscCall(DMPlexGetPartitioner(dm, &part)); 1171811d88abSStefano Zampini if (!level) { /* partition the coarse level only */ 1172811d88abSStefano Zampini PetscCall(PetscPartitionerSetFromOptions(part)); 1173811d88abSStefano Zampini } else { /* propagate partitioning information from coarser to finer level */ 1174811d88abSStefano Zampini DM sdm; 1175811d88abSStefano Zampini Vec map; 1176811d88abSStefano Zampini PetscSF sf; 1177811d88abSStefano Zampini PetscLayout clayout; 1178811d88abSStefano Zampini PetscScalar *array; 1179811d88abSStefano Zampini PetscInt *cranks_leaf, *cranks_root, *npoints, *points, *ranks, *starts, *gidxs; 1180811d88abSStefano Zampini PetscInt nparts, cStart, cEnd, nr, ccStart, ccEnd, cpStart, cpEnd; 1181811d88abSStefano Zampini PetscMPIInt size, rank; 1182811d88abSStefano Zampini 1183811d88abSStefano Zampini PetscCall(DMClone(dm, &sdm)); 1184811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)sdm, "pdm")); 1185811d88abSStefano Zampini PetscCall(DMPlexSectionLoad(dm, viewer, sdm, sfXB, NULL, &sf)); 1186811d88abSStefano Zampini PetscCall(DMGetLocalVector(sdm, &map)); 1187811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)map, "pdm_map")); 1188811d88abSStefano Zampini PetscCall(DMPlexLocalVectorLoad(dm, viewer, sdm, sf, map)); 1189811d88abSStefano Zampini 1190811d88abSStefano Zampini PetscCallMPI(MPI_Comm_size(comm, &size)); 1191811d88abSStefano Zampini PetscCallMPI(MPI_Comm_rank(comm, &rank)); 1192811d88abSStefano Zampini nparts = size; 1193811d88abSStefano Zampini PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1194811d88abSStefano Zampini PetscCall(DMPlexGetHeightStratum(cdm, 0, &ccStart, &ccEnd)); 1195811d88abSStefano Zampini PetscCall(DMPlexGetChart(cdm, &cpStart, &cpEnd)); 1196811d88abSStefano Zampini PetscCall(PetscCalloc1(nparts, &npoints)); 1197811d88abSStefano Zampini PetscCall(PetscMalloc4(cEnd - cStart, &points, cEnd - cStart, &ranks, nparts + 1, &starts, cEnd - cStart, &gidxs)); 1198811d88abSStefano Zampini PetscCall(PetscSFGetGraph(sfXC, &nr, NULL, NULL, NULL)); 1199811d88abSStefano Zampini PetscCall(PetscMalloc2(cpEnd - cpStart, &cranks_leaf, nr, &cranks_root)); 1200811d88abSStefano Zampini for (PetscInt c = 0; c < cpEnd - cpStart; c++) cranks_leaf[c] = rank; 1201811d88abSStefano Zampini PetscCall(PetscSFReduceBegin(sfXC, MPIU_INT, cranks_leaf, cranks_root, MPI_REPLACE)); 1202811d88abSStefano Zampini PetscCall(PetscSFReduceEnd(sfXC, MPIU_INT, cranks_leaf, cranks_root, MPI_REPLACE)); 1203811d88abSStefano Zampini 1204811d88abSStefano Zampini PetscCall(VecGetArray(map, &array)); 1205811d88abSStefano Zampini for (PetscInt c = 0; c < cEnd - cStart; c++) gidxs[c] = (PetscInt)PetscRealPart(array[c]); 1206811d88abSStefano Zampini PetscCall(VecRestoreArray(map, &array)); 1207811d88abSStefano Zampini 1208811d88abSStefano Zampini PetscCall(PetscLayoutCreate(comm, &clayout)); 1209811d88abSStefano Zampini PetscCall(PetscLayoutSetLocalSize(clayout, nr)); 1210811d88abSStefano Zampini PetscCall(PetscSFSetGraphLayout(sf, clayout, cEnd - cStart, NULL, PETSC_OWN_POINTER, gidxs)); 1211811d88abSStefano Zampini PetscCall(PetscLayoutDestroy(&clayout)); 1212811d88abSStefano Zampini 1213811d88abSStefano Zampini PetscCall(PetscSFBcastBegin(sf, MPIU_INT, cranks_root, ranks, MPI_REPLACE)); 1214811d88abSStefano Zampini PetscCall(PetscSFBcastEnd(sf, MPIU_INT, cranks_root, ranks, MPI_REPLACE)); 1215811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sf)); 1216811d88abSStefano Zampini PetscCall(PetscFree2(cranks_leaf, cranks_root)); 1217811d88abSStefano Zampini for (PetscInt c = 0; c < cEnd - cStart; c++) npoints[ranks[c]]++; 1218811d88abSStefano Zampini 1219811d88abSStefano Zampini starts[0] = 0; 1220811d88abSStefano Zampini for (PetscInt c = 0; c < nparts; c++) starts[c + 1] = starts[c] + npoints[c]; 1221811d88abSStefano Zampini for (PetscInt c = 0; c < cEnd - cStart; c++) points[starts[ranks[c]]++] = c; 1222811d88abSStefano Zampini PetscCall(PetscPartitionerSetType(part, PETSCPARTITIONERSHELL)); 1223811d88abSStefano Zampini PetscCall(PetscPartitionerShellSetPartition(part, nparts, npoints, points)); 1224811d88abSStefano Zampini PetscCall(PetscFree(npoints)); 1225811d88abSStefano Zampini PetscCall(PetscFree4(points, ranks, starts, gidxs)); 1226811d88abSStefano Zampini PetscCall(DMRestoreLocalVector(sdm, &map)); 1227811d88abSStefano Zampini PetscCall(DMDestroy(&sdm)); 1228811d88abSStefano Zampini } 1229811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sfXC)); 1230811d88abSStefano Zampini PetscCall(DMPlexDistribute(dm, 0, &sfBC, odm)); 1231811d88abSStefano Zampini if (*odm) { 1232811d88abSStefano Zampini PetscCall(DMDestroy(&dm)); 1233811d88abSStefano Zampini dm = *odm; 1234811d88abSStefano Zampini *odm = NULL; 1235811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)dm, dmname)); 1236811d88abSStefano Zampini } 1237811d88abSStefano Zampini if (sfBC) PetscCall(PetscSFCompose(sfXB, sfBC, &sfXC)); 1238811d88abSStefano Zampini else { 1239811d88abSStefano Zampini PetscCall(PetscObjectReference((PetscObject)sfXB)); 1240811d88abSStefano Zampini sfXC = sfXB; 1241811d88abSStefano Zampini } 1242811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sfXB)); 1243811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sfBC)); 1244811d88abSStefano Zampini PetscCall(DMSetCoarsenLevel(dm, cc)); 1245811d88abSStefano Zampini PetscCall(DMSetRefineLevel(dm, rr)); 1246811d88abSStefano Zampini PetscCall(DMPlexSetRegularRefinement(dm, isRegular)); 1247811d88abSStefano Zampini PetscCall(DMPlexSetRefinementUniform(dm, isUniform)); 1248811d88abSStefano Zampini PetscCall(DMPlexSectionLoad(dm, viewer, NULL, sfXC, &sfG, NULL)); 1249811d88abSStefano Zampini if (level == numlevels - 1) { 1250811d88abSStefano Zampini Vec u; 1251811d88abSStefano Zampini 1252811d88abSStefano Zampini PetscCall(DMGetNamedGlobalVector(dm, "solution_", &u)); 1253811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)u, "solution_")); 1254811d88abSStefano Zampini PetscCall(DMPlexGlobalVectorLoad(dm, viewer, NULL, sfG, u)); 1255811d88abSStefano Zampini PetscCall(DMRestoreNamedGlobalVector(dm, "solution_", &u)); 1256811d88abSStefano Zampini } 1257811d88abSStefano Zampini PetscCall(PetscFree(dmname)); 1258811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sfG)); 1259811d88abSStefano Zampini PetscCall(DMSetCoarseDM(dm, cdm)); 1260811d88abSStefano Zampini PetscCall(DMDestroy(&cdm)); 1261811d88abSStefano Zampini PetscCall(PetscViewerHDF5PopGroup(viewer)); 1262811d88abSStefano Zampini cdm = dm; 1263811d88abSStefano Zampini } 1264811d88abSStefano Zampini *odm = dm; 1265811d88abSStefano Zampini PetscCall(PetscViewerPopFormat(viewer)); 1266811d88abSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 1267811d88abSStefano Zampini PetscCall(PetscSFDestroy(&sfXC)); 1268811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1269811d88abSStefano Zampini #else 1270811d88abSStefano Zampini SETERRQ(comm, PETSC_ERR_SUP, "Needs HDF5 support. Please reconfigure using --download-hdf5"); 1271811d88abSStefano Zampini #endif 1272811d88abSStefano Zampini } 1273811d88abSStefano Zampini 127466edf50cSStefano Zampini /* 127566edf50cSStefano Zampini Setup AuxDM: 127666edf50cSStefano Zampini - project source function and make it zero-mean 127766edf50cSStefano Zampini - sample frozen fields for operator splitting 127866edf50cSStefano Zampini */ 127966edf50cSStefano Zampini static PetscErrorCode ProjectAuxDM(DM dm, PetscReal time, Vec u, AppCtx *ctx) 1280811d88abSStefano Zampini { 1281811d88abSStefano Zampini DM dmAux; 128266edf50cSStefano Zampini Vec la, a; 128366edf50cSStefano Zampini void *ctxs[NUM_FIELDS + 1]; 128466edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS + 1]; 128566edf50cSStefano Zampini VecScatter sctAux; 1286811d88abSStefano Zampini PetscDS ds; 128766edf50cSStefano Zampini PetscErrorCode (*funcs[NUM_FIELDS + 1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *); 1288811d88abSStefano Zampini 1289811d88abSStefano Zampini PetscFunctionBeginUser; 129066edf50cSStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &la)); 129166edf50cSStefano Zampini if (!la) { 129266edf50cSStefano Zampini PetscFE field; 129366edf50cSStefano Zampini PetscInt fields[NUM_FIELDS]; 129466edf50cSStefano Zampini IS is; 129566edf50cSStefano Zampini Vec tu, ta; 129666edf50cSStefano Zampini PetscInt dim; 129766edf50cSStefano Zampini 129866edf50cSStefano Zampini PetscCall(DMClone(dm, &dmAux)); 129966edf50cSStefano Zampini PetscCall(DMSetNumFields(dmAux, NUM_FIELDS + 1)); 130066edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 130166edf50cSStefano Zampini PetscCall(DMGetField(dm, i, NULL, (PetscObject *)&field)); 130266edf50cSStefano Zampini PetscCall(DMSetField(dmAux, i, NULL, (PetscObject)field)); 130366edf50cSStefano Zampini fields[i] = i; 1304811d88abSStefano Zampini } 130566edf50cSStefano Zampini /* PetscFEDuplicate? */ 130666edf50cSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 130766edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, 1, ctx->simplex, "p_", -1, &field)); 130866edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)field, "source")); 130966edf50cSStefano Zampini PetscCall(DMSetField(dmAux, NUM_FIELDS, NULL, (PetscObject)field)); 131066edf50cSStefano Zampini PetscCall(PetscFEDestroy(&field)); 131166edf50cSStefano Zampini PetscCall(DMCreateDS(dmAux)); 131266edf50cSStefano Zampini PetscCall(DMCreateSubDM(dmAux, NUM_FIELDS, fields, &is, NULL)); 131366edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dm, &tu)); 131466edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dmAux, &ta)); 131566edf50cSStefano Zampini PetscCall(VecScatterCreate(tu, NULL, ta, is, &sctAux)); 131666edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &tu)); 131766edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dmAux, &ta)); 131866edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dmAux, "scatterAux", (PetscObject)sctAux)); 131966edf50cSStefano Zampini PetscCall(VecScatterDestroy(&sctAux)); 132066edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 132166edf50cSStefano Zampini PetscCall(DMCreateLocalVector(dmAux, &la)); 132266edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)la, "auxiliary_")); 132366edf50cSStefano Zampini PetscCall(DMSetAuxiliaryVec(dm, NULL, 0, 0, la)); 132466edf50cSStefano Zampini PetscCall(DMDestroy(&dmAux)); 132566edf50cSStefano Zampini PetscCall(VecDestroy(&la)); 132666edf50cSStefano Zampini } 132766edf50cSStefano Zampini if (time == PETSC_MIN_REAL) PetscFunctionReturn(PETSC_SUCCESS); 132866edf50cSStefano Zampini 132966edf50cSStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &la)); 133066edf50cSStefano Zampini PetscCall(VecGetDM(la, &dmAux)); 133166edf50cSStefano Zampini PetscCall(DMGetDS(dmAux, &ds)); 133266edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dmAux, &a)); 1333811d88abSStefano Zampini funcs[C_FIELD_ID] = zerof; 1334811d88abSStefano Zampini ctxs[C_FIELD_ID] = NULL; 133566edf50cSStefano Zampini funcs[P_FIELD_ID] = zerof; 133666edf50cSStefano Zampini ctxs[P_FIELD_ID] = NULL; 133766edf50cSStefano Zampini funcs[NUM_FIELDS] = source; 133866edf50cSStefano Zampini ctxs[NUM_FIELDS] = ctx->source_ctx; 133966edf50cSStefano Zampini PetscCall(DMProjectFunction(dmAux, time, funcs, ctxs, INSERT_ALL_VALUES, a)); 1340811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 134166edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, zero)); 134266edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, NUM_FIELDS, average)); 134366edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dmAux, a, vals, NULL)); 134466edf50cSStefano Zampini PetscCall(VecShift(a, -vals[NUM_FIELDS] / ctx->domain_volume)); 134566edf50cSStefano Zampini if (u) { 134666edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dmAux, "scatterAux", (PetscObject *)&sctAux)); 134766edf50cSStefano Zampini PetscCheck(sctAux, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing scatterAux"); 134866edf50cSStefano Zampini PetscCall(VecScatterBegin(sctAux, u, a, INSERT_VALUES, SCATTER_FORWARD)); 134966edf50cSStefano Zampini PetscCall(VecScatterEnd(sctAux, u, a, INSERT_VALUES, SCATTER_FORWARD)); 135066edf50cSStefano Zampini } 135166edf50cSStefano Zampini PetscCall(DMGlobalToLocal(dmAux, a, INSERT_VALUES, la)); 135266edf50cSStefano Zampini PetscCall(VecViewFromOptions(la, NULL, "-aux_view")); 135366edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dmAux, &a)); 1354811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1355811d88abSStefano Zampini } 1356811d88abSStefano Zampini 1357811d88abSStefano Zampini /* callback for the creation of the potential null space */ 1358811d88abSStefano Zampini static PetscErrorCode CreatePotentialNullSpace(DM dm, PetscInt ofield, PetscInt nfield, MatNullSpace *nullSpace) 1359811d88abSStefano Zampini { 1360811d88abSStefano Zampini Vec vec; 1361811d88abSStefano Zampini PetscErrorCode (*funcs[NUM_FIELDS])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *) = {zerof}; 1362811d88abSStefano Zampini 1363811d88abSStefano Zampini PetscFunctionBeginUser; 1364811d88abSStefano Zampini funcs[nfield] = constantf; 1365811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &vec)); 1366811d88abSStefano Zampini PetscCall(DMProjectFunction(dm, 0.0, funcs, NULL, INSERT_ALL_VALUES, vec)); 1367811d88abSStefano Zampini PetscCall(VecNormalize(vec, NULL)); 1368811d88abSStefano Zampini PetscCall(MatNullSpaceCreate(PetscObjectComm((PetscObject)dm), PETSC_FALSE, 1, &vec, nullSpace)); 1369811d88abSStefano Zampini /* break ref cycles */ 1370811d88abSStefano Zampini PetscCall(VecSetDM(vec, NULL)); 1371811d88abSStefano Zampini PetscCall(VecDestroy(&vec)); 1372811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1373811d88abSStefano Zampini } 1374811d88abSStefano Zampini 1375204aa523SStefano Zampini static PetscErrorCode DMGetLumpedMass(DM dm, PetscBool local, Vec *lumped_mass) 1376204aa523SStefano Zampini { 1377204aa523SStefano Zampini PetscBool has; 1378204aa523SStefano Zampini 1379204aa523SStefano Zampini PetscFunctionBeginUser; 1380204aa523SStefano Zampini if (local) { 1381204aa523SStefano Zampini PetscCall(DMHasNamedLocalVector(dm, "lumped_mass", &has)); 1382204aa523SStefano Zampini PetscCall(DMGetNamedLocalVector(dm, "lumped_mass", lumped_mass)); 1383204aa523SStefano Zampini } else { 1384204aa523SStefano Zampini PetscCall(DMHasNamedGlobalVector(dm, "lumped_mass", &has)); 1385204aa523SStefano Zampini PetscCall(DMGetNamedGlobalVector(dm, "lumped_mass", lumped_mass)); 1386204aa523SStefano Zampini } 1387204aa523SStefano Zampini if (!has) { 1388204aa523SStefano Zampini Vec w; 1389204aa523SStefano Zampini IS is; 1390204aa523SStefano Zampini 1391204aa523SStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&is)); 139266edf50cSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 1393204aa523SStefano Zampini if (local) { 1394204aa523SStefano Zampini Vec w2, wg; 1395204aa523SStefano Zampini 1396204aa523SStefano Zampini PetscCall(DMCreateMassMatrixLumped(dm, &w, NULL)); 1397204aa523SStefano Zampini PetscCall(DMGetGlobalVector(dm, &wg)); 1398204aa523SStefano Zampini PetscCall(DMGetLocalVector(dm, &w2)); 1399204aa523SStefano Zampini PetscCall(VecSet(w2, 0.0)); 1400204aa523SStefano Zampini PetscCall(VecSet(wg, 1.0)); 1401204aa523SStefano Zampini PetscCall(VecISSet(wg, is, 0.0)); 1402204aa523SStefano Zampini PetscCall(DMGlobalToLocal(dm, wg, INSERT_VALUES, w2)); 1403204aa523SStefano Zampini PetscCall(VecPointwiseMult(w, w, w2)); 1404204aa523SStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &wg)); 1405204aa523SStefano Zampini PetscCall(DMRestoreLocalVector(dm, &w2)); 1406204aa523SStefano Zampini } else { 1407204aa523SStefano Zampini PetscCall(DMCreateMassMatrixLumped(dm, NULL, &w)); 1408204aa523SStefano Zampini PetscCall(VecISSet(w, is, 0.0)); 1409204aa523SStefano Zampini } 1410204aa523SStefano Zampini PetscCall(VecCopy(w, *lumped_mass)); 1411204aa523SStefano Zampini PetscCall(VecDestroy(&w)); 1412204aa523SStefano Zampini } 1413204aa523SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1414204aa523SStefano Zampini } 1415204aa523SStefano Zampini 1416204aa523SStefano Zampini static PetscErrorCode DMRestoreLumpedMass(DM dm, PetscBool local, Vec *lumped_mass) 1417204aa523SStefano Zampini { 1418204aa523SStefano Zampini PetscFunctionBeginUser; 1419204aa523SStefano Zampini if (local) PetscCall(DMRestoreNamedLocalVector(dm, "lumped_mass", lumped_mass)); 1420204aa523SStefano Zampini else PetscCall(DMRestoreNamedGlobalVector(dm, "lumped_mass", lumped_mass)); 1421204aa523SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1422204aa523SStefano Zampini } 1423204aa523SStefano Zampini 142466edf50cSStefano Zampini /* callbacks for residual and Jacobian */ 142566edf50cSStefano Zampini static PetscErrorCode DMPlexTSComputeIFunctionFEM_Private(DM dm, PetscReal time, Vec locX, Vec locX_t, Vec locF, void *user) 1426204aa523SStefano Zampini { 1427204aa523SStefano Zampini Vec work, local_lumped_mass; 142866edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)user; 1429204aa523SStefano Zampini 1430204aa523SStefano Zampini PetscFunctionBeginUser; 143166edf50cSStefano Zampini if (ctx->fix_c < 0) { 143266edf50cSStefano Zampini PetscReal vals[NUM_FIELDS]; 143366edf50cSStefano Zampini PetscDS ds; 143466edf50cSStefano Zampini 143566edf50cSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 143666edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, jacobian_fail)); 143766edf50cSStefano Zampini PetscCall(DMPlexSNESComputeObjectiveFEM(dm, locX, vals, NULL)); 143866edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 143966edf50cSStefano Zampini if (vals[C_FIELD_ID]) PetscCall(SNESSetFunctionDomainError(ctx->snes)); 144066edf50cSStefano Zampini } 144166edf50cSStefano Zampini if (ctx->lump) { 1442204aa523SStefano Zampini PetscCall(DMGetLumpedMass(dm, PETSC_TRUE, &local_lumped_mass)); 1443204aa523SStefano Zampini PetscCall(DMGetLocalVector(dm, &work)); 1444204aa523SStefano Zampini PetscCall(VecSet(work, 0.0)); 1445204aa523SStefano Zampini PetscCall(DMPlexTSComputeIFunctionFEM(dm, time, locX, work, locF, user)); 1446204aa523SStefano Zampini PetscCall(VecPointwiseMult(work, locX_t, local_lumped_mass)); 1447204aa523SStefano Zampini PetscCall(VecAXPY(locF, 1.0, work)); 1448204aa523SStefano Zampini PetscCall(DMRestoreLocalVector(dm, &work)); 1449204aa523SStefano Zampini PetscCall(DMRestoreLumpedMass(dm, PETSC_TRUE, &local_lumped_mass)); 145066edf50cSStefano Zampini } else { 145166edf50cSStefano Zampini PetscCall(DMPlexTSComputeIFunctionFEM(dm, time, locX, locX_t, locF, user)); 145266edf50cSStefano Zampini } 1453204aa523SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1454204aa523SStefano Zampini } 1455204aa523SStefano Zampini 145666edf50cSStefano Zampini static PetscErrorCode DMPlexTSComputeIJacobianFEM_Private(DM dm, PetscReal time, Vec locX, Vec locX_t, PetscReal X_tShift, Mat Jac, Mat JacP, void *user) 1457204aa523SStefano Zampini { 1458204aa523SStefano Zampini Vec lumped_mass, work; 145966edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)user; 1460204aa523SStefano Zampini 1461204aa523SStefano Zampini PetscFunctionBeginUser; 146266edf50cSStefano Zampini if (ctx->lump) { 1463204aa523SStefano Zampini PetscCall(DMGetLumpedMass(dm, PETSC_FALSE, &lumped_mass)); 1464204aa523SStefano Zampini PetscCall(DMPlexTSComputeIJacobianFEM(dm, time, locX, locX_t, 0.0, Jac, JacP, user)); 1465204aa523SStefano Zampini PetscCall(DMGetGlobalVector(dm, &work)); 1466204aa523SStefano Zampini PetscCall(VecAXPBY(work, X_tShift, 0.0, lumped_mass)); 1467204aa523SStefano Zampini PetscCall(MatDiagonalSet(JacP, work, ADD_VALUES)); 1468204aa523SStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &work)); 1469204aa523SStefano Zampini PetscCall(DMRestoreLumpedMass(dm, PETSC_FALSE, &lumped_mass)); 147066edf50cSStefano Zampini } else { 147166edf50cSStefano Zampini PetscCall(DMPlexTSComputeIJacobianFEM(dm, time, locX, locX_t, X_tShift, Jac, JacP, user)); 147266edf50cSStefano Zampini } 1473204aa523SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1474204aa523SStefano Zampini } 1475204aa523SStefano Zampini 1476811d88abSStefano Zampini /* customize residuals and Jacobians */ 1477811d88abSStefano Zampini static PetscErrorCode SetupProblem(DM dm, AppCtx *ctx) 1478811d88abSStefano Zampini { 1479811d88abSStefano Zampini PetscDS ds; 1480811d88abSStefano Zampini PetscInt cdim, dim; 1481811d88abSStefano Zampini PetscScalar constants[NUM_CONSTANTS]; 148266edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS]; 148366edf50cSStefano Zampini PetscInt fields[NUM_FIELDS] = {C_FIELD_ID, P_FIELD_ID}; 148466edf50cSStefano Zampini Vec dummy; 148566edf50cSStefano Zampini IS is; 1486811d88abSStefano Zampini 1487811d88abSStefano Zampini PetscFunctionBeginUser; 1488811d88abSStefano Zampini constants[R_ID] = ctx->r; 1489811d88abSStefano Zampini constants[EPS_ID] = ctx->eps; 1490811d88abSStefano Zampini constants[ALPHA_ID] = ctx->alpha; 1491811d88abSStefano Zampini constants[GAMMA_ID] = ctx->gamma; 1492811d88abSStefano Zampini constants[D_ID] = ctx->D; 1493204aa523SStefano Zampini constants[FIXC_ID] = ctx->fix_c; 149466edf50cSStefano Zampini constants[SPLIT_ID] = ctx->split; 1495811d88abSStefano Zampini 1496811d88abSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 1497811d88abSStefano Zampini PetscCall(DMGetCoordinateDim(dm, &cdim)); 149866edf50cSStefano Zampini PetscCheck(dim == 2 || dim == 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Topological dimension must be 2 or 3"); 149966edf50cSStefano Zampini PetscCheck(dim == ctx->dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Topological dimension mismatch: expected %" PetscInt_FMT ", found %" PetscInt_FMT, dim, ctx->dim); 150066edf50cSStefano Zampini PetscCheck(cdim == ctx->dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Geometrical dimension mismatch: expected %" PetscInt_FMT ", found %" PetscInt_FMT, cdim, ctx->dim); 1501811d88abSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 1502811d88abSStefano Zampini PetscCall(PetscDSSetConstants(ds, NUM_CONSTANTS, constants)); 1503811d88abSStefano Zampini PetscCall(PetscDSSetImplicit(ds, C_FIELD_ID, PETSC_TRUE)); 1504811d88abSStefano Zampini PetscCall(PetscDSSetImplicit(ds, P_FIELD_ID, PETSC_TRUE)); 1505811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 1506811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 150766edf50cSStefano Zampini if (ctx->dim == 2) { 1508811d88abSStefano Zampini PetscCall(PetscDSSetResidual(ds, C_FIELD_ID, C_0, C_1)); 1509811d88abSStefano Zampini PetscCall(PetscDSSetResidual(ds, P_FIELD_ID, P_0, P_1)); 151066edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, C_FIELD_ID, JC_0_c0c0, NULL, NULL, ctx->D > 0 ? JC_1_c1c1 : NULL)); 151166edf50cSStefano Zampini if (!ctx->split) { /* we solve a block diagonal system to mimic operator splitting, jacobians will not be correct */ 1512811d88abSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, P_FIELD_ID, NULL, JC_0_c0p1, NULL, NULL)); 1513811d88abSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, C_FIELD_ID, NULL, NULL, JP_1_p1c0, NULL)); 151466edf50cSStefano Zampini } 1515811d88abSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, P_FIELD_ID, NULL, NULL, NULL, JP_1_p1p1)); 151666edf50cSStefano Zampini } else { 151766edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, C_FIELD_ID, C_0_3d, C_1_3d)); 151866edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, P_FIELD_ID, P_0, P_1_3d)); 151966edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, C_FIELD_ID, JC_0_c0c0_3d, NULL, NULL, ctx->D > 0 ? JC_1_c1c1_3d : NULL)); 152066edf50cSStefano Zampini if (!ctx->split) { 152166edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, P_FIELD_ID, NULL, JC_0_c0p1_3d, NULL, NULL)); 152266edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, C_FIELD_ID, NULL, NULL, JP_1_p1c0_3d, NULL)); 152366edf50cSStefano Zampini } 152466edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, P_FIELD_ID, NULL, NULL, NULL, JP_1_p1p1_3d)); 152566edf50cSStefano Zampini } 1526811d88abSStefano Zampini /* Attach potential nullspace */ 1527811d88abSStefano Zampini PetscCall(DMSetNullSpaceConstructor(dm, P_FIELD_ID, CreatePotentialNullSpace)); 1528811d88abSStefano Zampini 152966edf50cSStefano Zampini /* Compute domain volume */ 153066edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dm, &dummy)); 153166edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, volume)); 153266edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, dummy, vals, NULL)); 153366edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 153466edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &dummy)); 153566edf50cSStefano Zampini ctx->domain_volume = PetscRealPart(vals[P_FIELD_ID]); 153666edf50cSStefano Zampini 153766edf50cSStefano Zampini /* Index sets for potential and conductivities */ 153866edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields, &is, NULL)); 153966edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "IS conductivity", (PetscObject)is)); 154066edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)is, "C")); 154166edf50cSStefano Zampini PetscCall(ISViewFromOptions(is, NULL, "-is_conductivity_view")); 154266edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 154366edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields + 1, &is, NULL)); 154466edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)is, "P")); 154566edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "IS potential", (PetscObject)is)); 154666edf50cSStefano Zampini PetscCall(ISViewFromOptions(is, NULL, "-is_potential_view")); 154766edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 154866edf50cSStefano Zampini 154966edf50cSStefano Zampini /* Create auxiliary DM */ 155066edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, PETSC_MIN_REAL, NULL, ctx)); 1551811d88abSStefano Zampini 1552811d88abSStefano Zampini /* Add callbacks */ 155366edf50cSStefano Zampini PetscCall(DMTSSetIFunctionLocal(dm, DMPlexTSComputeIFunctionFEM_Private, ctx)); 155466edf50cSStefano Zampini PetscCall(DMTSSetIJacobianLocal(dm, DMPlexTSComputeIJacobianFEM_Private, ctx)); 155566edf50cSStefano Zampini /* DMPlexTSComputeBoundary is not needed because we use natural boundary conditions */ 155666edf50cSStefano Zampini PetscCall(DMTSSetBoundaryLocal(dm, NULL, NULL)); 155766edf50cSStefano Zampini 155866edf50cSStefano Zampini /* handle nullspace in residual (move it to TSComputeIFunction_DMLocal?) */ 155966edf50cSStefano Zampini { 156066edf50cSStefano Zampini MatNullSpace nullsp; 156166edf50cSStefano Zampini 156266edf50cSStefano Zampini PetscCall(CreatePotentialNullSpace(dm, P_FIELD_ID, P_FIELD_ID, &nullsp)); 156366edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "__dmtsnullspace", (PetscObject)nullsp)); 156466edf50cSStefano Zampini PetscCall(MatNullSpaceDestroy(&nullsp)); 1565204aa523SStefano Zampini } 1566811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1567811d88abSStefano Zampini } 1568811d88abSStefano Zampini 1569811d88abSStefano Zampini /* setup discrete spaces and residuals */ 1570811d88abSStefano Zampini static PetscErrorCode SetupDiscretization(DM dm, AppCtx *ctx) 1571811d88abSStefano Zampini { 157266edf50cSStefano Zampini DM cdm = dm; 1573811d88abSStefano Zampini PetscFE feC, feP; 1574811d88abSStefano Zampini PetscInt dim; 1575811d88abSStefano Zampini MPI_Comm comm = PetscObjectComm((PetscObject)dm); 1576811d88abSStefano Zampini 1577811d88abSStefano Zampini PetscFunctionBeginUser; 1578811d88abSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 1579811d88abSStefano Zampini 1580204aa523SStefano Zampini /* We model Cij with Cij = Cji -> dim*(dim+1)/2 components */ 158166edf50cSStefano Zampini PetscCall(PetscFECreateDefault(comm, dim, (dim * (dim + 1)) / 2, ctx->simplex, "c_", -1, &feC)); 1582811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feC, "conductivity")); 158366edf50cSStefano Zampini PetscCall(PetscFECreateDefault(comm, dim, 1, ctx->simplex, "p_", -1, &feP)); 1584811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feP, "potential")); 1585204aa523SStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feC)); 158666edf50cSStefano Zampini PetscCall(PetscFEViewFromOptions(feP, NULL, "-view_fe")); 158766edf50cSStefano Zampini PetscCall(PetscFEViewFromOptions(feC, NULL, "-view_fe")); 1588811d88abSStefano Zampini 1589811d88abSStefano Zampini PetscCall(DMSetNumFields(dm, 2)); 1590811d88abSStefano Zampini PetscCall(DMSetField(dm, C_FIELD_ID, NULL, (PetscObject)feC)); 1591811d88abSStefano Zampini PetscCall(DMSetField(dm, P_FIELD_ID, NULL, (PetscObject)feP)); 1592811d88abSStefano Zampini PetscCall(PetscFEDestroy(&feC)); 1593811d88abSStefano Zampini PetscCall(PetscFEDestroy(&feP)); 1594811d88abSStefano Zampini PetscCall(DMCreateDS(dm)); 1595811d88abSStefano Zampini while (cdm) { 1596811d88abSStefano Zampini PetscCall(DMCopyDisc(dm, cdm)); 1597811d88abSStefano Zampini PetscCall(SetupProblem(cdm, ctx)); 1598811d88abSStefano Zampini PetscCall(DMGetCoarseDM(cdm, &cdm)); 1599811d88abSStefano Zampini } 1600811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1601811d88abSStefano Zampini } 1602811d88abSStefano Zampini 1603811d88abSStefano Zampini /* Create mesh by command line options */ 1604811d88abSStefano Zampini static PetscErrorCode CreateMesh(MPI_Comm comm, DM *dm, AppCtx *ctx) 1605811d88abSStefano Zampini { 160666edf50cSStefano Zampini DM plex; 160766edf50cSStefano Zampini 1608811d88abSStefano Zampini PetscFunctionBeginUser; 1609811d88abSStefano Zampini if (ctx->load) { 1610811d88abSStefano Zampini PetscInt refine = 0; 1611811d88abSStefano Zampini PetscBool isHierarchy; 1612811d88abSStefano Zampini DM *dms; 1613811d88abSStefano Zampini char typeName[256]; 1614811d88abSStefano Zampini PetscBool flg; 1615811d88abSStefano Zampini 1616811d88abSStefano Zampini PetscCall(LoadFromFile(comm, ctx->load_filename, dm)); 1617811d88abSStefano Zampini PetscOptionsBegin(comm, "", "Additional mesh options", "DMPLEX"); 1618811d88abSStefano Zampini PetscCall(PetscOptionsFList("-dm_mat_type", "Matrix type used for created matrices", "DMSetMatType", MatList, MATAIJ, typeName, sizeof(typeName), &flg)); 1619811d88abSStefano Zampini if (flg) PetscCall(DMSetMatType(*dm, typeName)); 1620811d88abSStefano Zampini PetscCall(PetscOptionsBoundedInt("-dm_refine", "The number of uniform refinements", "DMCreate", refine, &refine, NULL, 0)); 1621811d88abSStefano Zampini PetscCall(PetscOptionsBoundedInt("-dm_refine_hierarchy", "The number of uniform refinements", "DMCreate", refine, &refine, &isHierarchy, 0)); 1622811d88abSStefano Zampini PetscOptionsEnd(); 1623811d88abSStefano Zampini if (refine) { 1624811d88abSStefano Zampini PetscCall(SetupDiscretization(*dm, ctx)); 1625811d88abSStefano Zampini PetscCall(DMPlexSetRefinementUniform(*dm, PETSC_TRUE)); 1626811d88abSStefano Zampini } 1627811d88abSStefano Zampini PetscCall(PetscCalloc1(refine, &dms)); 1628811d88abSStefano Zampini if (isHierarchy) PetscCall(DMRefineHierarchy(*dm, refine, dms)); 1629811d88abSStefano Zampini for (PetscInt r = 0; r < refine; r++) { 1630811d88abSStefano Zampini Mat M; 1631811d88abSStefano Zampini DM dmr = dms[r]; 1632811d88abSStefano Zampini Vec u, ur; 1633811d88abSStefano Zampini 1634811d88abSStefano Zampini if (!isHierarchy) { 163555bffe1bSPierre Jolivet PetscCall(DMRefine(*dm, PetscObjectComm((PetscObject)*dm), &dmr)); 1636811d88abSStefano Zampini PetscCall(DMSetCoarseDM(dmr, *dm)); 1637811d88abSStefano Zampini } 1638811d88abSStefano Zampini PetscCall(DMCreateInterpolation(*dm, dmr, &M, NULL)); 1639811d88abSStefano Zampini PetscCall(DMGetNamedGlobalVector(*dm, "solution_", &u)); 1640811d88abSStefano Zampini PetscCall(DMGetNamedGlobalVector(dmr, "solution_", &ur)); 1641811d88abSStefano Zampini PetscCall(MatInterpolate(M, u, ur)); 1642811d88abSStefano Zampini PetscCall(DMRestoreNamedGlobalVector(*dm, "solution_", &u)); 1643811d88abSStefano Zampini PetscCall(DMRestoreNamedGlobalVector(dmr, "solution_", &ur)); 1644811d88abSStefano Zampini PetscCall(MatDestroy(&M)); 1645811d88abSStefano Zampini if (!isHierarchy) PetscCall(DMSetCoarseDM(dmr, NULL)); 1646811d88abSStefano Zampini PetscCall(DMDestroy(dm)); 1647811d88abSStefano Zampini *dm = dmr; 1648811d88abSStefano Zampini } 1649811d88abSStefano Zampini if (refine && !isHierarchy) PetscCall(DMSetRefineLevel(*dm, 0)); 1650811d88abSStefano Zampini PetscCall(PetscFree(dms)); 1651811d88abSStefano Zampini } else { 1652811d88abSStefano Zampini PetscCall(DMCreate(comm, dm)); 1653811d88abSStefano Zampini PetscCall(DMSetType(*dm, DMPLEX)); 1654811d88abSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 1655811d88abSStefano Zampini PetscCall(DMLocalizeCoordinates(*dm)); 1656811d88abSStefano Zampini { 1657811d88abSStefano Zampini char convType[256]; 1658811d88abSStefano Zampini PetscBool flg; 1659811d88abSStefano Zampini PetscOptionsBegin(comm, "", "Additional mesh options", "DMPLEX"); 1660811d88abSStefano Zampini PetscCall(PetscOptionsFList("-dm_plex_convert_type", "Convert DMPlex to another format", __FILE__, DMList, DMPLEX, convType, 256, &flg)); 1661811d88abSStefano Zampini PetscOptionsEnd(); 1662811d88abSStefano Zampini if (flg) { 1663811d88abSStefano Zampini DM dmConv; 1664811d88abSStefano Zampini PetscCall(DMConvert(*dm, convType, &dmConv)); 1665811d88abSStefano Zampini if (dmConv) { 1666811d88abSStefano Zampini PetscCall(DMDestroy(dm)); 1667811d88abSStefano Zampini *dm = dmConv; 1668811d88abSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 1669811d88abSStefano Zampini PetscCall(DMSetUp(*dm)); 1670811d88abSStefano Zampini } 1671811d88abSStefano Zampini } 1672811d88abSStefano Zampini } 1673811d88abSStefano Zampini } 167466edf50cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, "ref_")); 167566edf50cSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 167666edf50cSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 167766edf50cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, NULL)); 167866edf50cSStefano Zampini 167966edf50cSStefano Zampini PetscCall(DMConvert(*dm, DMPLEX, &plex)); 168066edf50cSStefano Zampini PetscCall(DMPlexIsSimplex(plex, &ctx->simplex)); 1681*5440e5dcSBarry Smith PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &ctx->simplex, 1, MPI_C_BOOL, MPI_LOR, comm)); 168266edf50cSStefano Zampini PetscCall(DMDestroy(&plex)); 168366edf50cSStefano Zampini 1684811d88abSStefano Zampini PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view")); 1685811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1686811d88abSStefano Zampini } 1687811d88abSStefano Zampini 1688811d88abSStefano Zampini /* Make potential field zero mean */ 168966edf50cSStefano Zampini static PetscErrorCode ZeroMeanPotential(DM dm, Vec u, PetscScalar domain_volume) 1690811d88abSStefano Zampini { 1691811d88abSStefano Zampini PetscScalar vals[NUM_FIELDS]; 1692811d88abSStefano Zampini PetscDS ds; 1693811d88abSStefano Zampini IS is; 1694811d88abSStefano Zampini 1695811d88abSStefano Zampini PetscFunctionBeginUser; 1696811d88abSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&is)); 1697811d88abSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 1698811d88abSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 1699811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, average)); 1700811d88abSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, u, vals, NULL)); 1701811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 170266edf50cSStefano Zampini PetscCall(VecISShift(u, is, -vals[P_FIELD_ID] / domain_volume)); 1703811d88abSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, u, vals, NULL)); 1704811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1705811d88abSStefano Zampini } 1706811d88abSStefano Zampini 1707811d88abSStefano Zampini /* Compute initial conditions and exclude potential from local truncation error 1708811d88abSStefano Zampini Since we are solving a DAE, once the initial conditions for the differential 1709811d88abSStefano Zampini variables are set, we need to compute the corresponding value for the 1710811d88abSStefano Zampini algebraic variables. We do so by creating a subDM for the potential only 1711811d88abSStefano Zampini and solve a static problem with SNES */ 1712811d88abSStefano Zampini static PetscErrorCode SetInitialConditionsAndTolerances(TS ts, PetscInt nv, Vec vecs[], PetscBool valid) 1713811d88abSStefano Zampini { 1714811d88abSStefano Zampini DM dm; 171566edf50cSStefano Zampini Vec u, p, subaux, vatol, vrtol; 1716811d88abSStefano Zampini PetscReal t, atol, rtol; 1717811d88abSStefano Zampini PetscInt fields[NUM_FIELDS] = {C_FIELD_ID, P_FIELD_ID}; 1718811d88abSStefano Zampini IS isp; 1719811d88abSStefano Zampini DM dmp; 1720811d88abSStefano Zampini VecScatter sctp = NULL; 1721811d88abSStefano Zampini PetscDS ds; 1722811d88abSStefano Zampini SNES snes; 1723811d88abSStefano Zampini KSP ksp; 1724811d88abSStefano Zampini PC pc; 1725811d88abSStefano Zampini AppCtx *ctx; 1726811d88abSStefano Zampini 1727811d88abSStefano Zampini PetscFunctionBeginUser; 1728811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 1729811d88abSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 173066edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&isp)); 173166edf50cSStefano Zampini PetscCheck(isp, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 1732204aa523SStefano Zampini if (valid) { 173366edf50cSStefano Zampini if (ctx->exclude_potential_lte) { 1734811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &vatol)); 1735811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &vrtol)); 1736811d88abSStefano Zampini PetscCall(TSGetTolerances(ts, &atol, NULL, &rtol, NULL)); 1737811d88abSStefano Zampini PetscCall(VecSet(vatol, atol)); 1738811d88abSStefano Zampini PetscCall(VecISSet(vatol, isp, -1)); 1739811d88abSStefano Zampini PetscCall(VecSet(vrtol, rtol)); 1740811d88abSStefano Zampini PetscCall(VecISSet(vrtol, isp, -1)); 1741811d88abSStefano Zampini PetscCall(TSSetTolerances(ts, atol, vatol, rtol, vrtol)); 1742811d88abSStefano Zampini PetscCall(VecDestroy(&vatol)); 1743811d88abSStefano Zampini PetscCall(VecDestroy(&vrtol)); 174466edf50cSStefano Zampini } 174566edf50cSStefano Zampini for (PetscInt i = 0; i < nv; i++) PetscCall(ZeroMeanPotential(dm, vecs[i], ctx->domain_volume)); 1746811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1747811d88abSStefano Zampini } 174866edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields + 1, NULL, &dmp)); 1749811d88abSStefano Zampini PetscCall(DMSetMatType(dmp, MATAIJ)); 1750811d88abSStefano Zampini PetscCall(DMGetDS(dmp, &ds)); 175166edf50cSStefano Zampini if (ctx->dim == 2) { 175266edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, 0, P_0_aux, P_1_aux)); 1753811d88abSStefano Zampini PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, JP_1_p1p1_aux)); 175466edf50cSStefano Zampini } else { 175566edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, 0, P_0_aux, P_1_aux_3d)); 175666edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, JP_1_p1p1_aux_3d)); 175766edf50cSStefano Zampini } 1758811d88abSStefano Zampini PetscCall(DMPlexSetSNESLocalFEM(dmp, PETSC_FALSE, NULL)); 1759811d88abSStefano Zampini 1760811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dmp, &p)); 1761811d88abSStefano Zampini 1762811d88abSStefano Zampini PetscCall(SNESCreate(PetscObjectComm((PetscObject)dmp), &snes)); 1763811d88abSStefano Zampini PetscCall(SNESSetDM(snes, dmp)); 1764811d88abSStefano Zampini PetscCall(SNESSetOptionsPrefix(snes, "initial_")); 1765811d88abSStefano Zampini PetscCall(SNESSetErrorIfNotConverged(snes, PETSC_TRUE)); 1766811d88abSStefano Zampini PetscCall(SNESGetKSP(snes, &ksp)); 1767204aa523SStefano Zampini PetscCall(KSPSetType(ksp, KSPFGMRES)); 1768811d88abSStefano Zampini PetscCall(KSPGetPC(ksp, &pc)); 1769811d88abSStefano Zampini PetscCall(PCSetType(pc, PCGAMG)); 1770811d88abSStefano Zampini PetscCall(SNESSetFromOptions(snes)); 1771811d88abSStefano Zampini PetscCall(SNESSetUp(snes)); 1772811d88abSStefano Zampini 1773811d88abSStefano Zampini /* Loop over input vectors and compute corresponding potential */ 1774811d88abSStefano Zampini for (PetscInt i = 0; i < nv; i++) { 1775811d88abSStefano Zampini u = vecs[i]; 1776811d88abSStefano Zampini if (!valid) { /* Assumes entries in u are not valid */ 177766edf50cSStefano Zampini PetscErrorCode (*funcs[NUM_FIELDS])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *); 177866edf50cSStefano Zampini void *ctxs[NUM_FIELDS] = {NULL}; 177966edf50cSStefano Zampini PetscRandom r = NULL; 178066edf50cSStefano Zampini 1781811d88abSStefano Zampini PetscCall(TSGetTime(ts, &t)); 1782811d88abSStefano Zampini switch (ctx->ic_num) { 1783811d88abSStefano Zampini case 0: 1784811d88abSStefano Zampini funcs[C_FIELD_ID] = initial_conditions_C_0; 1785811d88abSStefano Zampini break; 1786811d88abSStefano Zampini case 1: 1787811d88abSStefano Zampini funcs[C_FIELD_ID] = initial_conditions_C_1; 1788811d88abSStefano Zampini break; 1789811d88abSStefano Zampini case 2: 1790811d88abSStefano Zampini funcs[C_FIELD_ID] = initial_conditions_C_2; 1791811d88abSStefano Zampini break; 179266edf50cSStefano Zampini case 3: 179366edf50cSStefano Zampini funcs[C_FIELD_ID] = initial_conditions_C_random; 179466edf50cSStefano Zampini PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)ts), &r)); 179566edf50cSStefano Zampini PetscCall(PetscRandomSetOptionsPrefix(r, "ic_")); 179666edf50cSStefano Zampini PetscCall(PetscRandomSetFromOptions(r)); 179766edf50cSStefano Zampini ctxs[C_FIELD_ID] = r; 179866edf50cSStefano Zampini break; 1799811d88abSStefano Zampini default: 1800d8b4a066SPierre Jolivet SETERRQ(PetscObjectComm((PetscObject)ts), PETSC_ERR_SUP, "Unknown IC"); 1801811d88abSStefano Zampini } 1802811d88abSStefano Zampini funcs[P_FIELD_ID] = zerof; 180366edf50cSStefano Zampini PetscCall(DMProjectFunction(dm, t, funcs, ctxs, INSERT_ALL_VALUES, u)); 180466edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, t, u, ctx)); 180566edf50cSStefano Zampini PetscCall(PetscRandomDestroy(&r)); 1806811d88abSStefano Zampini } 1807811d88abSStefano Zampini 180866edf50cSStefano Zampini /* pass conductivity information via auxiliary data */ 180966edf50cSStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &subaux)); 1810811d88abSStefano Zampini PetscCall(DMSetAuxiliaryVec(dmp, NULL, 0, 0, subaux)); 1811811d88abSStefano Zampini 1812811d88abSStefano Zampini /* solve the subproblem */ 1813811d88abSStefano Zampini if (!sctp) PetscCall(VecScatterCreate(u, isp, p, NULL, &sctp)); 1814811d88abSStefano Zampini PetscCall(VecScatterBegin(sctp, u, p, INSERT_VALUES, SCATTER_FORWARD)); 1815811d88abSStefano Zampini PetscCall(VecScatterEnd(sctp, u, p, INSERT_VALUES, SCATTER_FORWARD)); 1816811d88abSStefano Zampini PetscCall(SNESSolve(snes, NULL, p)); 1817811d88abSStefano Zampini 1818811d88abSStefano Zampini /* scatter from potential only to full space */ 1819811d88abSStefano Zampini PetscCall(VecScatterBegin(sctp, p, u, INSERT_VALUES, SCATTER_REVERSE)); 1820811d88abSStefano Zampini PetscCall(VecScatterEnd(sctp, p, u, INSERT_VALUES, SCATTER_REVERSE)); 182166edf50cSStefano Zampini PetscCall(ZeroMeanPotential(dm, u, ctx->domain_volume)); 1822811d88abSStefano Zampini } 1823811d88abSStefano Zampini PetscCall(VecDestroy(&p)); 1824811d88abSStefano Zampini PetscCall(DMDestroy(&dmp)); 1825811d88abSStefano Zampini PetscCall(SNESDestroy(&snes)); 1826811d88abSStefano Zampini PetscCall(VecScatterDestroy(&sctp)); 1827811d88abSStefano Zampini 1828811d88abSStefano Zampini /* exclude potential from computation of the LTE */ 182966edf50cSStefano Zampini if (ctx->exclude_potential_lte) { 1830811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &vatol)); 1831811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &vrtol)); 1832811d88abSStefano Zampini PetscCall(TSGetTolerances(ts, &atol, NULL, &rtol, NULL)); 1833811d88abSStefano Zampini PetscCall(VecSet(vatol, atol)); 1834811d88abSStefano Zampini PetscCall(VecISSet(vatol, isp, -1)); 1835811d88abSStefano Zampini PetscCall(VecSet(vrtol, rtol)); 1836811d88abSStefano Zampini PetscCall(VecISSet(vrtol, isp, -1)); 1837811d88abSStefano Zampini PetscCall(TSSetTolerances(ts, atol, vatol, rtol, vrtol)); 1838811d88abSStefano Zampini PetscCall(VecDestroy(&vatol)); 1839811d88abSStefano Zampini PetscCall(VecDestroy(&vrtol)); 184066edf50cSStefano Zampini } 1841811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1842811d88abSStefano Zampini } 1843811d88abSStefano Zampini 1844811d88abSStefano Zampini /* mesh adaption context */ 1845811d88abSStefano Zampini typedef struct { 1846811d88abSStefano Zampini VecTagger refineTag; 1847811d88abSStefano Zampini DMLabel adaptLabel; 1848811d88abSStefano Zampini PetscInt cnt; 1849811d88abSStefano Zampini } AdaptCtx; 1850811d88abSStefano Zampini 1851811d88abSStefano Zampini static PetscErrorCode ResizeSetUp(TS ts, PetscInt nstep, PetscReal time, Vec u, PetscBool *resize, void *vctx) 1852811d88abSStefano Zampini { 1853811d88abSStefano Zampini AdaptCtx *ctx = (AdaptCtx *)vctx; 1854811d88abSStefano Zampini Vec ellVecCells, ellVecCellsF; 1855811d88abSStefano Zampini DM dm, plex; 1856811d88abSStefano Zampini PetscDS ds; 1857811d88abSStefano Zampini PetscReal norm; 1858811d88abSStefano Zampini PetscInt cStart, cEnd; 1859811d88abSStefano Zampini 1860811d88abSStefano Zampini PetscFunctionBeginUser; 1861811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 1862811d88abSStefano Zampini PetscCall(DMConvert(dm, DMPLEX, &plex)); 1863811d88abSStefano Zampini PetscCall(DMPlexGetHeightStratum(plex, 0, &cStart, &cEnd)); 1864811d88abSStefano Zampini PetscCall(DMDestroy(&plex)); 1865811d88abSStefano Zampini PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)ts), NUM_FIELDS * (cEnd - cStart), PETSC_DECIDE, &ellVecCellsF)); 1866811d88abSStefano Zampini PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)ts), cEnd - cStart, PETSC_DECIDE, &ellVecCells)); 1867811d88abSStefano Zampini PetscCall(VecSetBlockSize(ellVecCellsF, NUM_FIELDS)); 1868811d88abSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 1869811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, ellipticity_fail)); 1870811d88abSStefano Zampini PetscCall(DMPlexComputeCellwiseIntegralFEM(dm, u, ellVecCellsF, NULL)); 1871811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 1872811d88abSStefano Zampini PetscCall(VecStrideGather(ellVecCellsF, C_FIELD_ID, ellVecCells, INSERT_VALUES)); 1873811d88abSStefano Zampini PetscCall(VecDestroy(&ellVecCellsF)); 1874811d88abSStefano Zampini PetscCall(VecNorm(ellVecCells, NORM_1, &norm)); 1875811d88abSStefano Zampini PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), "STEP %d norm %g\n", (int)nstep, (double)norm)); 1876811d88abSStefano Zampini if (norm && !ctx->cnt) { 1877811d88abSStefano Zampini IS refineIS; 1878811d88abSStefano Zampini 1879811d88abSStefano Zampini *resize = PETSC_TRUE; 1880811d88abSStefano Zampini if (!ctx->refineTag) { 1881811d88abSStefano Zampini VecTaggerBox refineBox; 1882811d88abSStefano Zampini refineBox.min = PETSC_MACHINE_EPSILON; 1883811d88abSStefano Zampini refineBox.max = PETSC_MAX_REAL; 1884811d88abSStefano Zampini 1885811d88abSStefano Zampini PetscCall(VecTaggerCreate(PETSC_COMM_SELF, &ctx->refineTag)); 1886811d88abSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ctx->refineTag, "refine_")); 1887811d88abSStefano Zampini PetscCall(VecTaggerSetType(ctx->refineTag, VECTAGGERABSOLUTE)); 1888811d88abSStefano Zampini PetscCall(VecTaggerAbsoluteSetBox(ctx->refineTag, &refineBox)); 1889811d88abSStefano Zampini PetscCall(VecTaggerSetFromOptions(ctx->refineTag)); 1890811d88abSStefano Zampini PetscCall(VecTaggerSetUp(ctx->refineTag)); 1891811d88abSStefano Zampini PetscCall(PetscObjectViewFromOptions((PetscObject)ctx->refineTag, NULL, "-tag_view")); 1892811d88abSStefano Zampini } 1893811d88abSStefano Zampini PetscCall(DMLabelDestroy(&ctx->adaptLabel)); 1894811d88abSStefano Zampini PetscCall(DMLabelCreate(PetscObjectComm((PetscObject)ts), "adapt", &ctx->adaptLabel)); 1895811d88abSStefano Zampini PetscCall(VecTaggerComputeIS(ctx->refineTag, ellVecCells, &refineIS, NULL)); 1896811d88abSStefano Zampini PetscCall(DMLabelSetStratumIS(ctx->adaptLabel, DM_ADAPT_REFINE, refineIS)); 1897811d88abSStefano Zampini PetscCall(ISDestroy(&refineIS)); 1898811d88abSStefano Zampini #if 0 1899811d88abSStefano Zampini void (*funcs[NUM_FIELDS])(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]); 1900811d88abSStefano Zampini Vec ellVec; 1901811d88abSStefano Zampini 1902811d88abSStefano Zampini funcs[P_FIELD_ID] = ellipticity_fail; 1903811d88abSStefano Zampini funcs[C_FIELD_ID] = NULL; 1904811d88abSStefano Zampini 1905811d88abSStefano Zampini PetscCall(DMGetGlobalVector(dm, &ellVec)); 1906811d88abSStefano Zampini PetscCall(DMProjectField(dm, 0, u, funcs, INSERT_VALUES, ellVec)); 1907811d88abSStefano Zampini PetscCall(VecViewFromOptions(ellVec,NULL,"-view_amr_ell")); 1908811d88abSStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &ellVec)); 1909811d88abSStefano Zampini #endif 1910811d88abSStefano Zampini ctx->cnt++; 1911811d88abSStefano Zampini } else { 1912811d88abSStefano Zampini ctx->cnt = 0; 1913811d88abSStefano Zampini } 1914811d88abSStefano Zampini PetscCall(VecDestroy(&ellVecCells)); 1915811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1916811d88abSStefano Zampini } 1917811d88abSStefano Zampini 1918811d88abSStefano Zampini static PetscErrorCode ResizeTransfer(TS ts, PetscInt nv, Vec vecsin[], Vec vecsout[], void *vctx) 1919811d88abSStefano Zampini { 1920811d88abSStefano Zampini AdaptCtx *actx = (AdaptCtx *)vctx; 1921811d88abSStefano Zampini AppCtx *ctx; 1922811d88abSStefano Zampini DM dm, adm; 1923811d88abSStefano Zampini PetscReal time; 192466edf50cSStefano Zampini PetscInt fields[NUM_FIELDS] = {C_FIELD_ID, P_FIELD_ID}; 192566edf50cSStefano Zampini IS is; 1926811d88abSStefano Zampini 1927811d88abSStefano Zampini PetscFunctionBeginUser; 1928811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 1929811d88abSStefano Zampini PetscCheck(actx->adaptLabel, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Missing adaptLabel"); 1930811d88abSStefano Zampini PetscCall(DMAdaptLabel(dm, actx->adaptLabel, &adm)); 1931811d88abSStefano Zampini PetscCheck(adm, PetscObjectComm((PetscObject)ts), PETSC_ERR_ARG_WRONGSTATE, "Missing adapted DM"); 1932811d88abSStefano Zampini PetscCall(TSGetTime(ts, &time)); 1933811d88abSStefano Zampini PetscCall(DMLabelDestroy(&actx->adaptLabel)); 1934811d88abSStefano Zampini for (PetscInt i = 0; i < nv; i++) { 1935811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(adm, &vecsout[i])); 1936811d88abSStefano Zampini PetscCall(DMForestTransferVec(dm, vecsin[i], adm, vecsout[i], PETSC_TRUE, time)); 1937811d88abSStefano Zampini } 1938811d88abSStefano Zampini PetscCall(DMForestSetAdaptivityForest(adm, NULL)); 1939811d88abSStefano Zampini PetscCall(DMSetCoarseDM(adm, NULL)); 1940811d88abSStefano Zampini PetscCall(DMSetLocalSection(adm, NULL)); 1941811d88abSStefano Zampini PetscCall(TSSetDM(ts, adm)); 1942811d88abSStefano Zampini PetscCall(TSGetTime(ts, &time)); 1943811d88abSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 1944204aa523SStefano Zampini PetscCall(DMSetNullSpaceConstructor(adm, P_FIELD_ID, CreatePotentialNullSpace)); 194566edf50cSStefano Zampini PetscCall(DMCreateSubDM(adm, 1, fields, &is, NULL)); 194666edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "IS conductivity", (PetscObject)is)); 194766edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 194866edf50cSStefano Zampini PetscCall(DMCreateSubDM(adm, 1, fields + 1, &is, NULL)); 194966edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "IS potential", (PetscObject)is)); 195066edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 195166edf50cSStefano Zampini PetscCall(ProjectAuxDM(adm, time, NULL, ctx)); 195266edf50cSStefano Zampini { 195366edf50cSStefano Zampini MatNullSpace nullsp; 195466edf50cSStefano Zampini 195566edf50cSStefano Zampini PetscCall(CreatePotentialNullSpace(adm, P_FIELD_ID, P_FIELD_ID, &nullsp)); 195666edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "__dmtsnullspace", (PetscObject)nullsp)); 195766edf50cSStefano Zampini PetscCall(MatNullSpaceDestroy(&nullsp)); 195866edf50cSStefano Zampini } 1959811d88abSStefano Zampini PetscCall(SetInitialConditionsAndTolerances(ts, nv, vecsout, PETSC_TRUE)); 196066edf50cSStefano Zampini PetscCall(DMDestroy(&ctx->view_dm)); 196166edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 196266edf50cSStefano Zampini PetscCall(VecScatterDestroy(&ctx->subsct[i])); 196366edf50cSStefano Zampini PetscCall(VecDestroy(&ctx->subvec[i])); 196466edf50cSStefano Zampini } 1965811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1966811d88abSStefano Zampini } 1967811d88abSStefano Zampini 196866edf50cSStefano Zampini static PetscErrorCode ComputeDiagnostic(Vec u, AppCtx *ctx, Vec *out) 1969811d88abSStefano Zampini { 197066edf50cSStefano Zampini DM dm; 197166edf50cSStefano Zampini PetscInt dim; 197266edf50cSStefano Zampini PetscFE feFluxC, feNormC, feEigsC; 197366edf50cSStefano Zampini 197466edf50cSStefano Zampini void (*funcs[])(PetscInt dim, PetscInt Nf, PetscInt NfAux, const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], PetscReal t, const PetscReal x[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f[]) = {normc, eigsc, flux}; 197566edf50cSStefano Zampini 1976811d88abSStefano Zampini PetscFunctionBeginUser; 197766edf50cSStefano Zampini if (!ctx->view_dm) { 197866edf50cSStefano Zampini PetscFE feP; 197966edf50cSStefano Zampini PetscInt nf = PetscMax(PetscMin(ctx->diagnostic_num, 3), 1); 198066edf50cSStefano Zampini 198166edf50cSStefano Zampini PetscCall(VecGetDM(u, &dm)); 198266edf50cSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 198366edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, 1, ctx->simplex, "normc_", -1, &feNormC)); 198466edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dim, ctx->simplex, "eigsc_", -1, &feEigsC)); 198566edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dim, ctx->simplex, "flux_", -1, &feFluxC)); 198666edf50cSStefano Zampini PetscCall(DMGetField(dm, P_FIELD_ID, NULL, (PetscObject *)&feP)); 198766edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feNormC)); 198866edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feEigsC)); 198966edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feFluxC)); 199066edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feNormC, "normC")); 199166edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feEigsC, "eigsC")); 199266edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feFluxC, "flux")); 199366edf50cSStefano Zampini 199466edf50cSStefano Zampini PetscCall(DMClone(dm, &ctx->view_dm)); 199566edf50cSStefano Zampini PetscCall(DMSetNumFields(ctx->view_dm, nf)); 199666edf50cSStefano Zampini PetscCall(DMSetField(ctx->view_dm, 0, NULL, (PetscObject)feNormC)); 199766edf50cSStefano Zampini if (nf > 1) PetscCall(DMSetField(ctx->view_dm, 1, NULL, (PetscObject)feEigsC)); 199866edf50cSStefano Zampini if (nf > 2) PetscCall(DMSetField(ctx->view_dm, 2, NULL, (PetscObject)feFluxC)); 199966edf50cSStefano Zampini PetscCall(DMCreateDS(ctx->view_dm)); 200066edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feFluxC)); 200166edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feNormC)); 200266edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feEigsC)); 200366edf50cSStefano Zampini } 200466edf50cSStefano Zampini PetscCall(DMCreateGlobalVector(ctx->view_dm, out)); 200566edf50cSStefano Zampini PetscCall(DMProjectField(ctx->view_dm, 0.0, u, funcs, INSERT_VALUES, *out)); 200666edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 200766edf50cSStefano Zampini } 200866edf50cSStefano Zampini 200966edf50cSStefano Zampini static PetscErrorCode MakeScatterAndVec(Vec X, IS is, Vec *Y, VecScatter *sct) 201066edf50cSStefano Zampini { 201166edf50cSStefano Zampini PetscInt n; 201266edf50cSStefano Zampini 201366edf50cSStefano Zampini PetscFunctionBeginUser; 201466edf50cSStefano Zampini PetscCall(ISGetLocalSize(is, &n)); 201566edf50cSStefano Zampini PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)X), n, PETSC_DECIDE, Y)); 201666edf50cSStefano Zampini PetscCall(VecScatterCreate(X, is, *Y, NULL, sct)); 201766edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 201866edf50cSStefano Zampini } 201966edf50cSStefano Zampini 202066edf50cSStefano Zampini static PetscErrorCode FunctionDomainError(TS ts, PetscReal time, Vec X, PetscBool *accept) 202166edf50cSStefano Zampini { 202266edf50cSStefano Zampini AppCtx *ctx; 202366edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS]; 202466edf50cSStefano Zampini DM dm; 202566edf50cSStefano Zampini PetscDS ds; 202666edf50cSStefano Zampini 202766edf50cSStefano Zampini PetscFunctionBeginUser; 202866edf50cSStefano Zampini *accept = PETSC_TRUE; 202966edf50cSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 203066edf50cSStefano Zampini if (ctx->function_domain_error_tol < 0) PetscFunctionReturn(PETSC_SUCCESS); 203166edf50cSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 203266edf50cSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 203366edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, ellipticity_fail)); 203466edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, X, vals, NULL)); 203566edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 203666edf50cSStefano Zampini if (PetscAbsScalar(vals[C_FIELD_ID]) > ctx->function_domain_error_tol) *accept = PETSC_FALSE; 203766edf50cSStefano Zampini if (!*accept) PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), "Domain error value %g > %g\n", (double)PetscAbsScalar(vals[C_FIELD_ID]), (double)ctx->function_domain_error_tol)); 2038811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2039811d88abSStefano Zampini } 2040811d88abSStefano Zampini 2041811d88abSStefano Zampini /* Monitor relevant functionals */ 2042811d88abSStefano Zampini static PetscErrorCode Monitor(TS ts, PetscInt stepnum, PetscReal time, Vec u, void *vctx) 2043811d88abSStefano Zampini { 2044811d88abSStefano Zampini PetscScalar vals[2 * NUM_FIELDS]; 2045811d88abSStefano Zampini DM dm; 2046811d88abSStefano Zampini PetscDS ds; 2047811d88abSStefano Zampini AppCtx *ctx; 204866edf50cSStefano Zampini PetscBool need_hdf5, need_vtk; 2049811d88abSStefano Zampini 2050811d88abSStefano Zampini PetscFunctionBeginUser; 2051811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 2052811d88abSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 2053811d88abSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 2054811d88abSStefano Zampini 2055811d88abSStefano Zampini /* monitor energy and potential average */ 2056811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, average)); 2057811d88abSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, u, vals, NULL)); 2058811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 2059811d88abSStefano Zampini 2060811d88abSStefano Zampini /* monitor ellipticity_fail */ 2061811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, ellipticity_fail)); 2062811d88abSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, u, vals + NUM_FIELDS, NULL)); 2063811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 206466edf50cSStefano Zampini vals[C_FIELD_ID] /= ctx->domain_volume; 2065811d88abSStefano Zampini 2066811d88abSStefano Zampini PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), "%4" PetscInt_FMT " TS: time %g, energy %g, intp %g, ell %g\n", stepnum, (double)time, (double)PetscRealPart(vals[C_FIELD_ID]), (double)PetscRealPart(vals[P_FIELD_ID]), (double)PetscRealPart(vals[NUM_FIELDS + C_FIELD_ID]))); 206766edf50cSStefano Zampini 206866edf50cSStefano Zampini /* monitor diagnostic */ 206966edf50cSStefano Zampini need_hdf5 = (PetscBool)(ctx->view_hdf5_ctx && ((ctx->view_hdf5_ctx->view_interval > 0 && !(stepnum % ctx->view_hdf5_ctx->view_interval)) || (ctx->view_hdf5_ctx->view_interval && ts->reason))); 207066edf50cSStefano Zampini need_vtk = (PetscBool)(ctx->view_vtk_ctx && ((ctx->view_vtk_ctx->interval > 0 && !(stepnum % ctx->view_vtk_ctx->interval)) || (ctx->view_vtk_ctx->interval && ts->reason))); 207166edf50cSStefano Zampini if (ctx->view_times_k < ctx->view_times_n && time >= ctx->view_times[ctx->view_times_k] && time < ctx->view_times[ctx->view_times_k + 1]) { 207266edf50cSStefano Zampini if (ctx->view_hdf5_ctx) need_hdf5 = PETSC_TRUE; 207366edf50cSStefano Zampini if (ctx->view_vtk_ctx) need_vtk = PETSC_TRUE; 207466edf50cSStefano Zampini ctx->view_times_k++; 207566edf50cSStefano Zampini } 207666edf50cSStefano Zampini if (need_vtk || need_hdf5) { 207766edf50cSStefano Zampini Vec diagnostic; 207866edf50cSStefano Zampini PetscBool dump_dm = (PetscBool)(!!ctx->view_dm); 207966edf50cSStefano Zampini 208066edf50cSStefano Zampini PetscCall(ComputeDiagnostic(u, ctx, &diagnostic)); 208166edf50cSStefano Zampini if (need_vtk) { 208266edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)diagnostic, "")); 208366edf50cSStefano Zampini PetscCall(TSMonitorSolutionVTK(ts, stepnum, time, diagnostic, ctx->view_vtk_ctx)); 208466edf50cSStefano Zampini } 208566edf50cSStefano Zampini if (need_hdf5) { 208666edf50cSStefano Zampini DM vdm; 208766edf50cSStefano Zampini PetscInt seqnum; 208866edf50cSStefano Zampini 208966edf50cSStefano Zampini PetscCall(VecGetDM(diagnostic, &vdm)); 209066edf50cSStefano Zampini if (!dump_dm) { 209166edf50cSStefano Zampini PetscCall(PetscViewerPushFormat(ctx->view_hdf5_ctx->viewer, ctx->view_hdf5_ctx->format)); 209266edf50cSStefano Zampini PetscCall(DMView(vdm, ctx->view_hdf5_ctx->viewer)); 209366edf50cSStefano Zampini PetscCall(PetscViewerPopFormat(ctx->view_hdf5_ctx->viewer)); 209466edf50cSStefano Zampini } 209566edf50cSStefano Zampini PetscCall(DMGetOutputSequenceNumber(vdm, &seqnum, NULL)); 209666edf50cSStefano Zampini PetscCall(DMSetOutputSequenceNumber(vdm, seqnum + 1, time)); 209766edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)diagnostic, "diagnostic")); 209866edf50cSStefano Zampini PetscCall(PetscViewerPushFormat(ctx->view_hdf5_ctx->viewer, ctx->view_hdf5_ctx->format)); 209966edf50cSStefano Zampini PetscCall(VecView(diagnostic, ctx->view_hdf5_ctx->viewer)); 210066edf50cSStefano Zampini if (ctx->diagnostic_num > 3 || ctx->diagnostic_num < 0) { 210166edf50cSStefano Zampini PetscCall(DMSetOutputSequenceNumber(dm, seqnum + 1, time)); 210266edf50cSStefano Zampini PetscCall(VecView(u, ctx->view_hdf5_ctx->viewer)); 210366edf50cSStefano Zampini } 210466edf50cSStefano Zampini PetscCall(PetscViewerPopFormat(ctx->view_hdf5_ctx->viewer)); 210566edf50cSStefano Zampini } 210666edf50cSStefano Zampini PetscCall(VecDestroy(&diagnostic)); 210766edf50cSStefano Zampini } 2108811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2109811d88abSStefano Zampini } 2110811d88abSStefano Zampini 2111811d88abSStefano Zampini /* Save restart information */ 2112811d88abSStefano Zampini static PetscErrorCode MonitorSave(TS ts, PetscInt steps, PetscReal time, Vec u, void *vctx) 2113811d88abSStefano Zampini { 2114811d88abSStefano Zampini DM dm; 2115811d88abSStefano Zampini AppCtx *ctx = (AppCtx *)vctx; 2116811d88abSStefano Zampini PetscInt save_every = ctx->save_every; 2117811d88abSStefano Zampini TSConvergedReason reason; 2118811d88abSStefano Zampini 2119811d88abSStefano Zampini PetscFunctionBeginUser; 2120811d88abSStefano Zampini if (!ctx->save) PetscFunctionReturn(PETSC_SUCCESS); 2121811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 2122811d88abSStefano Zampini PetscCall(TSGetConvergedReason(ts, &reason)); 2123811d88abSStefano Zampini if ((save_every > 0 && steps % save_every == 0) || (save_every == -1 && reason) || save_every < -1) PetscCall(SaveToFile(dm, u, ctx->save_filename)); 2124811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2125811d88abSStefano Zampini } 2126811d88abSStefano Zampini 212766edf50cSStefano Zampini /* Resample source if time dependent */ 212866edf50cSStefano Zampini static PetscErrorCode PreStage(TS ts, PetscReal stagetime) 212966edf50cSStefano Zampini { 213066edf50cSStefano Zampini AppCtx *ctx; 213166edf50cSStefano Zampini PetscBool resample, ismatis; 213266edf50cSStefano Zampini Mat A, P; 213366edf50cSStefano Zampini 213466edf50cSStefano Zampini PetscFunctionBeginUser; 213566edf50cSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 213666edf50cSStefano Zampini /* in case we need to call SNESSetFunctionDomainError */ 213766edf50cSStefano Zampini PetscCall(TSGetSNES(ts, &ctx->snes)); 213866edf50cSStefano Zampini 213966edf50cSStefano Zampini resample = ctx->split ? PETSC_TRUE : PETSC_FALSE; 214066edf50cSStefano Zampini for (PetscInt i = 0; i < ctx->source_ctx->n; i++) { 214166edf50cSStefano Zampini if (ctx->source_ctx->k[i] != 0.0) { 214266edf50cSStefano Zampini resample = PETSC_TRUE; 214366edf50cSStefano Zampini break; 214466edf50cSStefano Zampini } 214566edf50cSStefano Zampini } 214666edf50cSStefano Zampini if (resample) { 214766edf50cSStefano Zampini DM dm; 214866edf50cSStefano Zampini Vec u = NULL; 214966edf50cSStefano Zampini 215066edf50cSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 215166edf50cSStefano Zampini /* In case of a multistage method, we always use the frozen values at the previous time-step */ 215266edf50cSStefano Zampini if (ctx->split) PetscCall(TSGetSolution(ts, &u)); 215366edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, stagetime, u, ctx)); 215466edf50cSStefano Zampini } 215566edf50cSStefano Zampini 215666edf50cSStefano Zampini /* element matrices are sparse, ignore zero entries */ 215766edf50cSStefano Zampini PetscCall(TSGetIJacobian(ts, &A, &P, NULL, NULL)); 215866edf50cSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 215966edf50cSStefano Zampini if (!ismatis) PetscCall(MatSetOption(A, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 216066edf50cSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)P, MATIS, &ismatis)); 216166edf50cSStefano Zampini if (!ismatis) PetscCall(MatSetOption(P, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 216266edf50cSStefano Zampini 216366edf50cSStefano Zampini /* Set symmetric flag */ 216466edf50cSStefano Zampini PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE)); 216566edf50cSStefano Zampini PetscCall(MatSetOption(P, MAT_SYMMETRIC, PETSC_TRUE)); 216666edf50cSStefano Zampini PetscCall(MatSetOption(A, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 216766edf50cSStefano Zampini PetscCall(MatSetOption(P, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 216866edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 216966edf50cSStefano Zampini } 217066edf50cSStefano Zampini 2171811d88abSStefano Zampini /* Make potential zero mean after SNES solve */ 2172811d88abSStefano Zampini static PetscErrorCode PostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y) 2173811d88abSStefano Zampini { 2174811d88abSStefano Zampini DM dm; 2175811d88abSStefano Zampini Vec u = Y[stageindex]; 2176204aa523SStefano Zampini SNES snes; 2177204aa523SStefano Zampini PetscInt nits, lits, stepnum; 2178204aa523SStefano Zampini AppCtx *ctx; 2179811d88abSStefano Zampini 2180811d88abSStefano Zampini PetscFunctionBeginUser; 2181811d88abSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 2182204aa523SStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 218366edf50cSStefano Zampini 218466edf50cSStefano Zampini PetscCall(ZeroMeanPotential(dm, u, ctx->domain_volume)); 218566edf50cSStefano Zampini 2186204aa523SStefano Zampini if (ctx->test_restart) PetscFunctionReturn(PETSC_SUCCESS); 2187204aa523SStefano Zampini 2188204aa523SStefano Zampini /* monitor linear and nonlinear iterations */ 2189204aa523SStefano Zampini PetscCall(TSGetStepNumber(ts, &stepnum)); 2190204aa523SStefano Zampini PetscCall(TSGetSNES(ts, &snes)); 2191204aa523SStefano Zampini PetscCall(SNESGetIterationNumber(snes, &nits)); 2192204aa523SStefano Zampini PetscCall(SNESGetLinearSolveIterations(snes, &lits)); 2193204aa523SStefano Zampini 2194204aa523SStefano Zampini /* if function evals in TSDIRK are zero in the first stage, it is FSAL */ 2195204aa523SStefano Zampini if (stageindex == 0) { 2196204aa523SStefano Zampini PetscBool dirk; 2197204aa523SStefano Zampini PetscInt nf; 2198204aa523SStefano Zampini 2199204aa523SStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)ts, TSDIRK, &dirk)); 2200204aa523SStefano Zampini PetscCall(SNESGetNumberFunctionEvals(snes, &nf)); 2201204aa523SStefano Zampini if (dirk && nf == 0) nits = 0; 2202204aa523SStefano Zampini } 2203204aa523SStefano Zampini PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), " step %" PetscInt_FMT " stage %" PetscInt_FMT " nonlinear its %" PetscInt_FMT ", linear its %" PetscInt_FMT "\n", stepnum, stageindex, nits, lits)); 2204811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2205811d88abSStefano Zampini } 2206811d88abSStefano Zampini 220766edf50cSStefano Zampini PetscErrorCode MonitorNorms(SNES snes, PetscInt its, PetscReal f, void *vctx) 2208811d88abSStefano Zampini { 220966edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)vctx; 221066edf50cSStefano Zampini Vec F; 221166edf50cSStefano Zampini DM dm; 221266edf50cSStefano Zampini PetscReal subnorm[NUM_FIELDS]; 2213811d88abSStefano Zampini 2214811d88abSStefano Zampini PetscFunctionBeginUser; 221566edf50cSStefano Zampini PetscCall(SNESGetDM(snes, &dm)); 221666edf50cSStefano Zampini PetscCall(SNESGetFunction(snes, &F, NULL, NULL)); 221766edf50cSStefano Zampini if (!ctx->subsct[C_FIELD_ID]) { 221866edf50cSStefano Zampini IS is; 2219811d88abSStefano Zampini 222066edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS conductivity", (PetscObject *)&is)); 222166edf50cSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing conductivity IS"); 222266edf50cSStefano Zampini PetscCall(MakeScatterAndVec(F, is, &ctx->subvec[C_FIELD_ID], &ctx->subsct[C_FIELD_ID])); 222366edf50cSStefano Zampini } 222466edf50cSStefano Zampini if (!ctx->subsct[P_FIELD_ID]) { 222566edf50cSStefano Zampini IS is; 222666edf50cSStefano Zampini 222766edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&is)); 222866edf50cSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 222966edf50cSStefano Zampini PetscCall(MakeScatterAndVec(F, is, &ctx->subvec[P_FIELD_ID], &ctx->subsct[P_FIELD_ID])); 223066edf50cSStefano Zampini } 223166edf50cSStefano Zampini PetscCall(VecScatterBegin(ctx->subsct[C_FIELD_ID], F, ctx->subvec[C_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 223266edf50cSStefano Zampini PetscCall(VecScatterEnd(ctx->subsct[C_FIELD_ID], F, ctx->subvec[C_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 223366edf50cSStefano Zampini PetscCall(VecScatterBegin(ctx->subsct[P_FIELD_ID], F, ctx->subvec[P_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 223466edf50cSStefano Zampini PetscCall(VecScatterEnd(ctx->subsct[P_FIELD_ID], F, ctx->subvec[P_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 223566edf50cSStefano Zampini PetscCall(VecNorm(ctx->subvec[C_FIELD_ID], NORM_2, &subnorm[C_FIELD_ID])); 223666edf50cSStefano Zampini PetscCall(VecNorm(ctx->subvec[P_FIELD_ID], NORM_2, &subnorm[P_FIELD_ID])); 223766edf50cSStefano Zampini PetscCall(PetscPrintf(PetscObjectComm((PetscObject)dm), " %3" PetscInt_FMT " SNES Function norms %14.12e, %14.12e\n", its, (double)subnorm[C_FIELD_ID], (double)subnorm[P_FIELD_ID])); 2238811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2239811d88abSStefano Zampini } 2240811d88abSStefano Zampini 2241811d88abSStefano Zampini static PetscErrorCode Run(MPI_Comm comm, AppCtx *ctx) 2242811d88abSStefano Zampini { 2243811d88abSStefano Zampini DM dm; 2244811d88abSStefano Zampini TS ts; 2245811d88abSStefano Zampini Vec u; 2246811d88abSStefano Zampini AdaptCtx *actx; 2247811d88abSStefano Zampini PetscBool flg; 2248811d88abSStefano Zampini 2249811d88abSStefano Zampini PetscFunctionBeginUser; 2250811d88abSStefano Zampini if (ctx->test_restart) { 2251811d88abSStefano Zampini PetscViewer subviewer; 2252811d88abSStefano Zampini PetscMPIInt rank; 2253811d88abSStefano Zampini 2254811d88abSStefano Zampini PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 2255811d88abSStefano Zampini PetscCall(PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD, comm, &subviewer)); 2256811d88abSStefano Zampini if (ctx->load) PetscCall(PetscViewerASCIIPrintf(subviewer, "rank %d loading from %s\n", rank, ctx->load_filename)); 2257811d88abSStefano Zampini if (ctx->save) PetscCall(PetscViewerASCIIPrintf(subviewer, "rank %d saving to %s\n", rank, ctx->save_filename)); 2258811d88abSStefano Zampini PetscCall(PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD, comm, &subviewer)); 2259811d88abSStefano Zampini PetscCall(PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD)); 2260811d88abSStefano Zampini } else { 2261811d88abSStefano Zampini PetscCall(PetscPrintf(comm, "----------------------------\n")); 2262811d88abSStefano Zampini PetscCall(PetscPrintf(comm, "Simulation parameters:\n")); 226366edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " dim : %" PetscInt_FMT "\n", ctx->dim)); 2264811d88abSStefano Zampini PetscCall(PetscPrintf(comm, " r : %g\n", (double)ctx->r)); 2265811d88abSStefano Zampini PetscCall(PetscPrintf(comm, " eps : %g\n", (double)ctx->eps)); 2266811d88abSStefano Zampini PetscCall(PetscPrintf(comm, " alpha: %g\n", (double)ctx->alpha)); 2267811d88abSStefano Zampini PetscCall(PetscPrintf(comm, " gamma: %g\n", (double)ctx->gamma)); 2268811d88abSStefano Zampini PetscCall(PetscPrintf(comm, " D : %g\n", (double)ctx->D)); 2269811d88abSStefano Zampini if (ctx->load) PetscCall(PetscPrintf(comm, " load : %s\n", ctx->load_filename)); 2270811d88abSStefano Zampini else PetscCall(PetscPrintf(comm, " IC : %" PetscInt_FMT "\n", ctx->ic_num)); 227166edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " snum : %" PetscInt_FMT "\n", ctx->source_ctx->n)); 227266edf50cSStefano Zampini for (PetscInt i = 0; i < ctx->source_ctx->n; i++) { 227366edf50cSStefano Zampini const PetscReal *x0 = ctx->source_ctx->x0 + ctx->dim * i; 227466edf50cSStefano Zampini const PetscReal w = ctx->source_ctx->w[i]; 227566edf50cSStefano Zampini const PetscReal k = ctx->source_ctx->k[i]; 227666edf50cSStefano Zampini const PetscReal p = ctx->source_ctx->p[i]; 227766edf50cSStefano Zampini const PetscReal r = ctx->source_ctx->r[i]; 227866edf50cSStefano Zampini 227966edf50cSStefano Zampini if (ctx->dim == 2) { 228066edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " x0 : (%g,%g)\n", (double)x0[0], (double)x0[1])); 228166edf50cSStefano Zampini } else { 228266edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " x0 : (%g,%g,%g)\n", (double)x0[0], (double)x0[1], (double)x0[2])); 228366edf50cSStefano Zampini } 228466edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " scals: (%g,%g,%g,%g)\n", (double)w, (double)k, (double)p, (double)r)); 228566edf50cSStefano Zampini } 2286811d88abSStefano Zampini PetscCall(PetscPrintf(comm, "----------------------------\n")); 2287811d88abSStefano Zampini } 2288811d88abSStefano Zampini 2289811d88abSStefano Zampini if (!ctx->test_restart) PetscCall(PetscLogStagePush(SetupStage)); 2290811d88abSStefano Zampini PetscCall(CreateMesh(comm, &dm, ctx)); 2291811d88abSStefano Zampini PetscCall(SetupDiscretization(dm, ctx)); 2292811d88abSStefano Zampini 2293811d88abSStefano Zampini PetscCall(TSCreate(comm, &ts)); 2294811d88abSStefano Zampini PetscCall(TSSetApplicationContext(ts, ctx)); 2295811d88abSStefano Zampini 2296811d88abSStefano Zampini PetscCall(TSSetDM(ts, dm)); 2297811d88abSStefano Zampini if (ctx->test_restart) { 2298811d88abSStefano Zampini PetscViewer subviewer; 2299811d88abSStefano Zampini PetscMPIInt rank; 2300811d88abSStefano Zampini PetscInt level; 2301811d88abSStefano Zampini 2302811d88abSStefano Zampini PetscCall(DMGetRefineLevel(dm, &level)); 2303811d88abSStefano Zampini PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 2304811d88abSStefano Zampini PetscCall(PetscViewerGetSubViewer(PETSC_VIEWER_STDOUT_WORLD, comm, &subviewer)); 2305811d88abSStefano Zampini PetscCall(PetscViewerASCIIPrintf(subviewer, "rank %d DM refinement level %" PetscInt_FMT "\n", rank, level)); 2306811d88abSStefano Zampini PetscCall(PetscViewerRestoreSubViewer(PETSC_VIEWER_STDOUT_WORLD, comm, &subviewer)); 2307811d88abSStefano Zampini PetscCall(PetscViewerFlush(PETSC_VIEWER_STDOUT_WORLD)); 2308811d88abSStefano Zampini } 2309811d88abSStefano Zampini 2310811d88abSStefano Zampini if (ctx->test_restart) PetscCall(TSSetMaxSteps(ts, 1)); 2311811d88abSStefano Zampini PetscCall(TSSetMaxTime(ts, 10.0)); 2312811d88abSStefano Zampini PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER)); 2313811d88abSStefano Zampini if (!ctx->test_restart) PetscCall(TSMonitorSet(ts, Monitor, NULL, NULL)); 2314811d88abSStefano Zampini PetscCall(TSMonitorSet(ts, MonitorSave, ctx, NULL)); 2315811d88abSStefano Zampini PetscCall(PetscNew(&actx)); 2316811d88abSStefano Zampini if (ctx->amr) PetscCall(TSSetResize(ts, PETSC_TRUE, ResizeSetUp, ResizeTransfer, actx)); 231766edf50cSStefano Zampini PetscCall(TSSetPreStage(ts, PreStage)); 2318811d88abSStefano Zampini PetscCall(TSSetPostStage(ts, PostStage)); 2319811d88abSStefano Zampini PetscCall(TSSetMaxSNESFailures(ts, -1)); 232066edf50cSStefano Zampini PetscCall(TSSetFunctionDomainError(ts, FunctionDomainError)); 2321811d88abSStefano Zampini PetscCall(TSSetFromOptions(ts)); 232266edf50cSStefano Zampini if (ctx->monitor_norms) { 232366edf50cSStefano Zampini SNES snes; 232466edf50cSStefano Zampini 232566edf50cSStefano Zampini PetscCall(TSGetSNES(ts, &snes)); 232666edf50cSStefano Zampini PetscCall(SNESMonitorSet(snes, MonitorNorms, ctx, NULL)); 232766edf50cSStefano Zampini } 2328811d88abSStefano Zampini 2329811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &u)); 2330811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)u, "solution_")); 2331811d88abSStefano Zampini PetscCall(DMHasNamedGlobalVector(dm, "solution_", &flg)); 233266edf50cSStefano Zampini if (flg) { /* load from restart file */ 2333811d88abSStefano Zampini Vec ru; 2334811d88abSStefano Zampini 2335811d88abSStefano Zampini PetscCall(DMGetNamedGlobalVector(dm, "solution_", &ru)); 2336811d88abSStefano Zampini PetscCall(VecCopy(ru, u)); 2337811d88abSStefano Zampini PetscCall(DMRestoreNamedGlobalVector(dm, "solution_", &ru)); 2338811d88abSStefano Zampini } 233966edf50cSStefano Zampini PetscCall(SetInitialConditionsAndTolerances(ts, 1, &u, flg)); 2340811d88abSStefano Zampini PetscCall(TSSetSolution(ts, u)); 2341811d88abSStefano Zampini PetscCall(VecDestroy(&u)); 2342811d88abSStefano Zampini PetscCall(DMDestroy(&dm)); 2343811d88abSStefano Zampini if (!ctx->test_restart) PetscCall(PetscLogStagePop()); 2344811d88abSStefano Zampini 2345811d88abSStefano Zampini if (!ctx->test_restart) PetscCall(PetscLogStagePush(SolveStage)); 2346811d88abSStefano Zampini PetscCall(TSSolve(ts, NULL)); 2347811d88abSStefano Zampini if (!ctx->test_restart) PetscCall(PetscLogStagePop()); 234866edf50cSStefano Zampini if (ctx->view_vtk_ctx) PetscCall(TSMonitorSolutionVTKDestroy(&ctx->view_vtk_ctx)); 234966edf50cSStefano Zampini if (ctx->view_hdf5_ctx) PetscCall(PetscViewerAndFormatDestroy(&ctx->view_hdf5_ctx)); 235066edf50cSStefano Zampini PetscCall(DMDestroy(&ctx->view_dm)); 235166edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 235266edf50cSStefano Zampini PetscCall(VecScatterDestroy(&ctx->subsct[i])); 235366edf50cSStefano Zampini PetscCall(VecDestroy(&ctx->subvec[i])); 235466edf50cSStefano Zampini } 2355811d88abSStefano Zampini 2356811d88abSStefano Zampini PetscCall(TSDestroy(&ts)); 2357811d88abSStefano Zampini PetscCall(VecTaggerDestroy(&actx->refineTag)); 2358811d88abSStefano Zampini PetscCall(PetscFree(actx)); 2359811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2360811d88abSStefano Zampini } 2361811d88abSStefano Zampini 2362811d88abSStefano Zampini int main(int argc, char **argv) 2363811d88abSStefano Zampini { 2364811d88abSStefano Zampini AppCtx ctx; 2365811d88abSStefano Zampini 2366811d88abSStefano Zampini PetscFunctionBeginUser; 2367811d88abSStefano Zampini PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 2368811d88abSStefano Zampini PetscCall(ProcessOptions(&ctx)); 2369811d88abSStefano Zampini PetscCall(PetscLogStageRegister("Setup", &SetupStage)); 2370811d88abSStefano Zampini PetscCall(PetscLogStageRegister("Solve", &SolveStage)); 2371811d88abSStefano Zampini if (ctx.test_restart) { /* Test sequences of save and loads */ 2372811d88abSStefano Zampini PetscMPIInt rank; 2373811d88abSStefano Zampini 2374811d88abSStefano Zampini PetscCallMPI(MPI_Comm_rank(PETSC_COMM_WORLD, &rank)); 2375811d88abSStefano Zampini 2376811d88abSStefano Zampini /* test saving */ 2377811d88abSStefano Zampini ctx.load = PETSC_FALSE; 2378811d88abSStefano Zampini ctx.save = PETSC_TRUE; 2379811d88abSStefano Zampini /* sequential save */ 2380811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test sequential save\n")); 2381811d88abSStefano Zampini PetscCall(PetscSNPrintf(ctx.save_filename, sizeof(ctx.save_filename), "test_ex30_seq_%d.h5", rank)); 2382811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_SELF, &ctx)); 2383811d88abSStefano Zampini /* parallel save */ 2384811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test parallel save\n")); 2385811d88abSStefano Zampini PetscCall(PetscSNPrintf(ctx.save_filename, sizeof(ctx.save_filename), "test_ex30_par.h5")); 2386811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_WORLD, &ctx)); 2387811d88abSStefano Zampini 2388811d88abSStefano Zampini /* test loading */ 2389811d88abSStefano Zampini ctx.load = PETSC_TRUE; 2390811d88abSStefano Zampini ctx.save = PETSC_FALSE; 2391811d88abSStefano Zampini /* sequential and parallel runs from sequential save */ 2392811d88abSStefano Zampini PetscCall(PetscSNPrintf(ctx.load_filename, sizeof(ctx.load_filename), "test_ex30_seq_0.h5")); 2393811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test sequential load from sequential save\n")); 2394811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_SELF, &ctx)); 2395811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test parallel load from sequential save\n")); 2396811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_WORLD, &ctx)); 2397811d88abSStefano Zampini /* sequential and parallel runs from parallel save */ 2398811d88abSStefano Zampini PetscCall(PetscSNPrintf(ctx.load_filename, sizeof(ctx.load_filename), "test_ex30_par.h5")); 2399811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test sequential load from parallel save\n")); 2400811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_SELF, &ctx)); 2401811d88abSStefano Zampini PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Test parallel load from parallel save\n")); 2402811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_WORLD, &ctx)); 2403811d88abSStefano Zampini } else { /* Run the simulation */ 2404811d88abSStefano Zampini PetscCall(Run(PETSC_COMM_WORLD, &ctx)); 2405811d88abSStefano Zampini } 240666edf50cSStefano Zampini PetscCall(PetscFree5(ctx.source_ctx->x0, ctx.source_ctx->w, ctx.source_ctx->k, ctx.source_ctx->p, ctx.source_ctx->r)); 240766edf50cSStefano Zampini PetscCall(PetscFree(ctx.source_ctx)); 2408811d88abSStefano Zampini PetscCall(PetscFinalize()); 2409811d88abSStefano Zampini return 0; 2410811d88abSStefano Zampini } 2411811d88abSStefano Zampini 2412811d88abSStefano Zampini /*TEST 2413811d88abSStefano Zampini 2414811d88abSStefano Zampini testset: 241566edf50cSStefano Zampini args: -dm_plex_box_faces 3,3 -ksp_type preonly -pc_type svd -c_petscspace_degree 1 -p_petscspace_degree 1 -ts_max_steps 1 -initial_snes_test_jacobian -snes_test_jacobian -initial_snes_type ksponly -snes_type ksponly -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -ic_num 3 2416811d88abSStefano Zampini 2417811d88abSStefano Zampini test: 2418811d88abSStefano Zampini suffix: 0 2419811d88abSStefano Zampini nsize: {{1 2}} 242066edf50cSStefano Zampini args: -dm_refine 1 -lump {{0 1}} -exclude_potential_lte 242166edf50cSStefano Zampini 242266edf50cSStefano Zampini test: 242366edf50cSStefano Zampini suffix: 0_split 242466edf50cSStefano Zampini nsize: {{1 2}} 242566edf50cSStefano Zampini args: -dm_refine 1 -split 242666edf50cSStefano Zampini 242766edf50cSStefano Zampini test: 242866edf50cSStefano Zampini suffix: 0_3d 242966edf50cSStefano Zampini nsize: {{1 2}} 243066edf50cSStefano Zampini args: -dm_plex_box_faces 3,3,3 -dim 3 -dm_plex_dim 3 -lump {{0 1}} 2431811d88abSStefano Zampini 2432811d88abSStefano Zampini test: 2433811d88abSStefano Zampini suffix: 0_dirk 2434811d88abSStefano Zampini nsize: {{1 2}} 2435811d88abSStefano Zampini args: -dm_refine 1 -ts_type dirk 2436811d88abSStefano Zampini 2437811d88abSStefano Zampini test: 2438811d88abSStefano Zampini suffix: 0_dirk_mg 2439811d88abSStefano Zampini nsize: {{1 2}} 2440204aa523SStefano Zampini args: -dm_refine_hierarchy 1 -ts_type dirk -pc_type mg -mg_levels_pc_type bjacobi -mg_levels_sub_pc_factor_levels 2 -mg_levels_sub_pc_factor_mat_ordering_type rcm -mg_levels_sub_pc_factor_reuse_ordering -mg_coarse_pc_type svd -lump {{0 1}} 2441204aa523SStefano Zampini 2442204aa523SStefano Zampini test: 2443204aa523SStefano Zampini suffix: 0_dirk_fieldsplit 2444204aa523SStefano Zampini nsize: {{1 2}} 2445204aa523SStefano Zampini args: -dm_refine 1 -ts_type dirk -pc_type fieldsplit -pc_fieldsplit_type multiplicative -lump {{0 1}} 2446811d88abSStefano Zampini 2447811d88abSStefano Zampini test: 2448811d88abSStefano Zampini requires: p4est 2449811d88abSStefano Zampini suffix: 0_p4est 2450811d88abSStefano Zampini nsize: {{1 2}} 2451204aa523SStefano Zampini args: -dm_refine 1 -dm_plex_convert_type p4est -lump 0 2452811d88abSStefano Zampini 2453811d88abSStefano Zampini test: 2454811d88abSStefano Zampini suffix: 0_periodic 2455811d88abSStefano Zampini nsize: {{1 2}} 2456204aa523SStefano Zampini args: -dm_plex_box_bd periodic,periodic -dm_refine_pre 1 -lump {{0 1}} 2457811d88abSStefano Zampini 2458811d88abSStefano Zampini test: 2459811d88abSStefano Zampini requires: p4est 2460811d88abSStefano Zampini suffix: 0_p4est_periodic 2461811d88abSStefano Zampini nsize: {{1 2}} 2462204aa523SStefano Zampini args: -dm_plex_box_bd periodic,periodic -dm_refine_pre 1 -dm_plex_convert_type p4est -lump 0 2463811d88abSStefano Zampini 2464811d88abSStefano Zampini test: 2465811d88abSStefano Zampini requires: p4est 2466811d88abSStefano Zampini suffix: 0_p4est_mg 2467811d88abSStefano Zampini nsize: {{1 2}} 2468204aa523SStefano Zampini args: -dm_forest_minimum_refinement 0 -dm_forest_initial_refinement 2 -dm_plex_convert_type p4est -pc_type mg -mg_coarse_pc_type svd -mg_levels_pc_type svd -lump 0 2469811d88abSStefano Zampini 2470811d88abSStefano Zampini testset: 2471811d88abSStefano Zampini requires: hdf5 2472811d88abSStefano Zampini args: -test_restart -dm_plex_box_faces 3,3 -ksp_type preonly -pc_type mg -mg_levels_pc_type svd -c_petscspace_degree 1 -p_petscspace_degree 1 -petscpartitioner_type simple -test_restart 2473811d88abSStefano Zampini 2474811d88abSStefano Zampini test: 2475910b42cbSStefano Zampini requires: !single 2476811d88abSStefano Zampini suffix: restart 2477811d88abSStefano Zampini nsize: {{1 2}separate output} 2478811d88abSStefano Zampini args: -dm_refine_hierarchy {{0 1}separate output} -dm_plex_simplex 0 2479811d88abSStefano Zampini 2480811d88abSStefano Zampini test: 2481811d88abSStefano Zampini requires: triangle 2482811d88abSStefano Zampini suffix: restart_simplex 2483811d88abSStefano Zampini nsize: {{1 2}separate output} 2484811d88abSStefano Zampini args: -dm_refine_hierarchy {{0 1}separate output} -dm_plex_simplex 1 2485811d88abSStefano Zampini 2486811d88abSStefano Zampini test: 2487910b42cbSStefano Zampini requires: !single 2488811d88abSStefano Zampini suffix: restart_refonly 2489811d88abSStefano Zampini nsize: {{1 2}separate output} 2490811d88abSStefano Zampini args: -dm_refine 1 -dm_plex_simplex 0 2491811d88abSStefano Zampini 2492811d88abSStefano Zampini test: 2493811d88abSStefano Zampini requires: triangle 2494811d88abSStefano Zampini suffix: restart_simplex_refonly 2495811d88abSStefano Zampini nsize: {{1 2}separate output} 2496811d88abSStefano Zampini args: -dm_refine 1 -dm_plex_simplex 1 2497811d88abSStefano Zampini 249866edf50cSStefano Zampini test: 249966edf50cSStefano Zampini suffix: annulus 250066edf50cSStefano Zampini requires: exodusii 250166edf50cSStefano Zampini args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo -ksp_type preonly -pc_type none -c_petscspace_degree 1 -p_petscspace_degree 1 -ts_max_steps 2 -initial_snes_type ksponly -snes_type ksponly -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -source_num 2 -source_k 1,2 250266edf50cSStefano Zampini 250366edf50cSStefano Zampini test: 250466edf50cSStefano Zampini suffix: hdf5_diagnostic 250566edf50cSStefano Zampini requires: hdf5 exodusii 250666edf50cSStefano Zampini args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo -ksp_type preonly -pc_type none -c_petscspace_degree 1 -p_petscspace_degree 1 -ts_max_steps 2 -initial_snes_type ksponly -snes_type ksponly -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -source_num 2 -source_k 1,2 -monitor_hdf5 diagnostic.h5 -ic_num 3 250766edf50cSStefano Zampini 250866edf50cSStefano Zampini test: 250966edf50cSStefano Zampini suffix: vtk_diagnostic 251066edf50cSStefano Zampini requires: exodusii 251166edf50cSStefano Zampini args: -dm_plex_filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/annulus-20.exo -ksp_type preonly -pc_type none -c_petscspace_degree 1 -p_petscspace_degree 1 -ts_max_steps 2 -initial_snes_type ksponly -snes_type ksponly -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -source_num 2 -source_k 1,2 -monitor_vtk 'diagnostic-%03d.vtu' -ic_num 3 251266edf50cSStefano Zampini 251366edf50cSStefano Zampini test: 251466edf50cSStefano Zampini suffix: full_cdisc 251566edf50cSStefano Zampini args: -dm_plex_box_faces 3,3 -c_petscspace_degree 0 -p_petscspace_degree 1 -ts_max_steps 1 -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -ic_num 0 -dm_refine 1 -ts_type beuler -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_precondition selfp -fieldsplit_conductivity_pc_type pbjacobi -fieldsplit_potential_mat_schur_complement_ainv_type blockdiag -fieldsplit_potential_ksp_type preonly -fieldsplit_potential_pc_type svd 251666edf50cSStefano Zampini 251766edf50cSStefano Zampini test: 251866edf50cSStefano Zampini suffix: full_cdisc_split 251966edf50cSStefano Zampini args: -dm_plex_box_faces 3,3 -c_petscspace_degree 0 -p_petscspace_degree 1 -ts_max_steps 1 -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -ic_num 0 -dm_refine 1 -ts_type beuler -pc_type fieldsplit -pc_fieldsplit_type additive -fieldsplit_conductivity_pc_type pbjacobi -fieldsplit_potential_pc_type gamg -split -monitor_norms 252066edf50cSStefano Zampini 252166edf50cSStefano Zampini test: 252266edf50cSStefano Zampini suffix: full_cdisc_minres 252366edf50cSStefano Zampini args: -dm_plex_box_faces 3,3 -c_petscspace_degree 0 -p_petscspace_degree 1 -ts_max_steps 1 -petscpartitioner_type simple -dm_plex_simplex 0 -ts_adapt_type none -ic_num 0 -dm_refine 1 -ts_type beuler -pc_type fieldsplit -pc_fieldsplit_type schur -pc_fieldsplit_schur_fact_type diag -pc_fieldsplit_schur_precondition selfp -fieldsplit_conductivity_pc_type pbjacobi -fieldsplit_potential_mat_schur_complement_ainv_type blockdiag -fieldsplit_potential_ksp_type preonly -fieldsplit_potential_pc_type svd -ksp_type minres 252466edf50cSStefano Zampini 2525811d88abSStefano Zampini TEST*/ 2526