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 /* 12*66edf50cSStefano Zampini Here we solve the system of PDEs on \Omega \in R^d: 13811d88abSStefano Zampini 14*66edf50cSStefano 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: 18*66edf50cSStefano 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. 33*66edf50cSStefano 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, 49*66edf50cSStefano Zampini SPLIT_ID, 50811d88abSStefano Zampini NUM_CONSTANTS 51811d88abSStefano Zampini } ConstantIdx; 52811d88abSStefano Zampini 53811d88abSStefano Zampini PetscLogStage SetupStage, SolveStage; 54811d88abSStefano Zampini 55*66edf50cSStefano Zampini #define NORM2C(c00, c01, c11) (PetscSqr(c00) + 2 * PetscSqr(c01) + PetscSqr(c11)) 56*66edf50cSStefano 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)) 57*66edf50cSStefano Zampini 58*66edf50cSStefano Zampini /* Eigenvalues real 3x3 symmetric matrix https://onlinelibrary.wiley.com/doi/full/10.1002/nme.7153 */ 59*66edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 60*66edf50cSStefano Zampini static inline void Eigenvalues_Sym3x3(PetscReal a11, PetscReal a12, PetscReal a13, PetscReal a22, PetscReal a23, PetscReal a33, PetscReal x[3]) 61*66edf50cSStefano Zampini { 62*66edf50cSStefano Zampini const PetscBool td = (PetscBool)(a13 == 0 && a23 == 0); 63*66edf50cSStefano Zampini if (td) { /* two-dimensional case */ 64*66edf50cSStefano Zampini PetscReal a12_2 = PetscSqr(a12); 65*66edf50cSStefano Zampini PetscReal delta = PetscSqr(a11 - a22) + 4 * a12_2; 66*66edf50cSStefano Zampini PetscReal b = -(a11 + a22); 67*66edf50cSStefano Zampini PetscReal c = a11 * a22 - a12_2; 68*66edf50cSStefano Zampini PetscReal temp = -0.5 * (b + PetscCopysignReal(1.0, b) * PetscSqrtReal(delta)); 69*66edf50cSStefano Zampini 70*66edf50cSStefano Zampini x[0] = temp; 71*66edf50cSStefano Zampini x[1] = c / temp; 72*66edf50cSStefano Zampini x[2] = a33; 73*66edf50cSStefano Zampini } else { 74*66edf50cSStefano Zampini const PetscReal I1 = a11 + a22 + a33; 75*66edf50cSStefano Zampini const PetscReal J2 = (PetscSqr(a11 - a22) + PetscSqr(a22 - a33) + PetscSqr(a33 - a11)) / 6 + PetscSqr(a12) + PetscSqr(a23) + PetscSqr(a13); 76*66edf50cSStefano Zampini const PetscReal s = PetscSqrtReal(J2 / 3); 77*66edf50cSStefano Zampini const PetscReal tol = PETSC_MACHINE_EPSILON; 78*66edf50cSStefano Zampini 79*66edf50cSStefano Zampini if (s < tol) { 80*66edf50cSStefano Zampini x[0] = x[1] = x[2] = 0.0; 81*66edf50cSStefano Zampini } else { 82*66edf50cSStefano Zampini const PetscReal S[] = {a11 - I1 / 3, a12, a13, a22 - I1 / 3, a23, a33 - I1 / 3}; 83*66edf50cSStefano Zampini 84*66edf50cSStefano Zampini /* T = S^2 */ 85*66edf50cSStefano Zampini PetscReal T[6]; 86*66edf50cSStefano Zampini T[0] = S[0] * S[0] + S[1] * S[1] + S[2] * S[2]; 87*66edf50cSStefano Zampini T[1] = S[0] * S[1] + S[1] * S[3] + S[2] * S[4]; 88*66edf50cSStefano Zampini T[2] = S[0] * S[2] + S[1] * S[4] + S[2] * S[5]; 89*66edf50cSStefano Zampini T[3] = S[1] * S[1] + S[3] * S[3] + S[4] * S[4]; 90*66edf50cSStefano Zampini T[4] = S[1] * S[2] + S[3] * S[4] + S[4] * S[5]; 91*66edf50cSStefano Zampini T[5] = S[2] * S[2] + S[4] * S[4] + S[5] * S[5]; 92*66edf50cSStefano Zampini 93*66edf50cSStefano Zampini T[0] = T[0] - 2.0 * J2 / 3.0; 94*66edf50cSStefano Zampini T[3] = T[3] - 2.0 * J2 / 3.0; 95*66edf50cSStefano Zampini T[5] = T[5] - 2.0 * J2 / 3.0; 96*66edf50cSStefano Zampini 97*66edf50cSStefano 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]); 98*66edf50cSStefano 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]); 99*66edf50cSStefano Zampini const PetscReal d = PetscSqrtReal(aa / bb); 100*66edf50cSStefano Zampini const PetscBool sj = (PetscBool)(1.0 - d > 0.0); 101*66edf50cSStefano Zampini 102*66edf50cSStefano Zampini if (PetscAbsReal(1 - d) < tol) { 103*66edf50cSStefano Zampini x[0] = -PetscSqrtReal(J2); 104*66edf50cSStefano Zampini x[1] = 0.0; 105*66edf50cSStefano Zampini x[2] = PetscSqrtReal(J2); 106*66edf50cSStefano Zampini } else { 107*66edf50cSStefano Zampini const PetscReal sjn = sj ? 1.0 : -1.0; 108*66edf50cSStefano Zampini //const PetscReal atanarg = sj ? d : 1.0 / d; 109*66edf50cSStefano Zampini //const PetscReal alpha = 2.0 * PetscAtanReal(atanarg) / 3.0; 110*66edf50cSStefano Zampini const PetscReal atanval = d > tol ? 2.0 * PetscAtanReal(sj ? d : 1.0 / d) : (sj ? 0.0 : PETSC_PI); 111*66edf50cSStefano Zampini const PetscReal alpha = atanval / 3.0; 112*66edf50cSStefano Zampini const PetscReal cd = s * PetscCosReal(alpha) * sjn; 113*66edf50cSStefano Zampini const PetscReal sd = PetscSqrtReal(J2) * PetscSinReal(alpha); 114*66edf50cSStefano Zampini 115*66edf50cSStefano Zampini x[0] = 2 * cd; 116*66edf50cSStefano Zampini x[1] = -cd + sd; 117*66edf50cSStefano Zampini x[2] = -cd - sd; 118*66edf50cSStefano Zampini } 119*66edf50cSStefano Zampini } 120*66edf50cSStefano Zampini x[0] += I1 / 3.0; 121*66edf50cSStefano Zampini x[1] += I1 / 3.0; 122*66edf50cSStefano Zampini x[2] += I1 / 3.0; 123*66edf50cSStefano Zampini } 124*66edf50cSStefano Zampini } 125*66edf50cSStefano Zampini #endif 126*66edf50cSStefano Zampini 127*66edf50cSStefano Zampini /* compute shift to make C positive definite */ 128*66edf50cSStefano Zampini static inline PetscReal FIX_C_3d(PetscScalar C00, PetscScalar C01, PetscScalar C02, PetscScalar C11, PetscScalar C12, PetscScalar C22) 129*66edf50cSStefano Zampini { 130*66edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 131*66edf50cSStefano Zampini PetscReal eigs[3], s = 0.0; 132*66edf50cSStefano Zampini PetscBool twod = (PetscBool)(C02 == 0 && C12 == 0 && C22 == 0); 133*66edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 134*66edf50cSStefano Zampini if (twod) eigs[2] = 1.0; 135*66edf50cSStefano Zampini if (eigs[0] <= 0 || eigs[1] <= 0 || eigs[2] <= 0) s = -PetscMin(eigs[0], PetscMin(eigs[1], eigs[2])) + PETSC_SMALL; 136*66edf50cSStefano Zampini return s; 137*66edf50cSStefano Zampini #else 138*66edf50cSStefano Zampini return 0.0; 139*66edf50cSStefano Zampini #endif 140*66edf50cSStefano Zampini } 141*66edf50cSStefano Zampini 142*66edf50cSStefano Zampini static inline PetscReal FIX_C(PetscScalar C00, PetscScalar C01, PetscScalar C11) 143*66edf50cSStefano Zampini { 144*66edf50cSStefano Zampini return FIX_C_3d(C00, C01, 0, C11, 0, 0); 145*66edf50cSStefano 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]); 153*66edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 154*66edf50cSStefano Zampini const PetscScalar *gradp = split ? a_x + aOff_x[P_FIELD_ID] : u_x + uOff_x[P_FIELD_ID]; 155*66edf50cSStefano Zampini const PetscScalar outerp[] = {gradp[0] * gradp[0], gradp[0] * gradp[1], gradp[1] * gradp[1]}; 156*66edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 157*66edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 158*66edf50cSStefano 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); 162*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; /* equations rescaling for a symmetric Jacobian */ 163811d88abSStefano Zampini 164*66edf50cSStefano 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]); 165*66edf50cSStefano Zampini } 166*66edf50cSStefano Zampini 167*66edf50cSStefano Zampini /* 3D version */ 168*66edf50cSStefano 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[]) 169*66edf50cSStefano Zampini { 170*66edf50cSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 171*66edf50cSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 172*66edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 173*66edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 174*66edf50cSStefano Zampini const PetscScalar *gradp = split ? a_x + aOff_x[P_FIELD_ID] : u_x + uOff_x[P_FIELD_ID]; 175*66edf50cSStefano 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]}; 176*66edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 177*66edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 178*66edf50cSStefano Zampini const PetscScalar C02 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 179*66edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 3] : u[uOff[C_FIELD_ID] + 3]; 180*66edf50cSStefano Zampini const PetscScalar C12 = split ? a[aOff[C_FIELD_ID] + 4] : u[uOff[C_FIELD_ID] + 4]; 181*66edf50cSStefano Zampini const PetscScalar C22 = split ? a[aOff[C_FIELD_ID] + 5] : u[uOff[C_FIELD_ID] + 5]; 182*66edf50cSStefano Zampini const PetscScalar norm = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 183*66edf50cSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 184*66edf50cSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 185*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 186*66edf50cSStefano Zampini 187*66edf50cSStefano 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]); 196*66edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 197*66edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 198*66edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 199*66edf50cSStefano 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}; 205*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; 206811d88abSStefano Zampini 207811d88abSStefano Zampini for (PetscInt k = 0; k < 3; k++) { 208*66edf50cSStefano Zampini if (!split) { 209*66edf50cSStefano Zampini for (PetscInt j = 0; j < 3; j++) J[k * 3 + j] = eqss[k] * (alpha * dfnorm * dC[j] * u[uOff[C_FIELD_ID] + k]); 210*66edf50cSStefano Zampini } 211*66edf50cSStefano Zampini J[k * 3 + k] += eqss[k] * (alpha * fnorm + u_tShift); 212*66edf50cSStefano Zampini } 213*66edf50cSStefano Zampini } 214*66edf50cSStefano Zampini 215*66edf50cSStefano 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[]) 216*66edf50cSStefano Zampini { 217*66edf50cSStefano Zampini const PetscReal alpha = PetscRealPart(constants[ALPHA_ID]); 218*66edf50cSStefano Zampini const PetscReal gamma = PetscRealPart(constants[GAMMA_ID]); 219*66edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 220*66edf50cSStefano Zampini const PetscBool split = (PetscBool)(PetscRealPart(constants[SPLIT_ID]) != 0.0); 221*66edf50cSStefano Zampini const PetscScalar C00 = split ? a[aOff[C_FIELD_ID]] : u[uOff[C_FIELD_ID]]; 222*66edf50cSStefano Zampini const PetscScalar C01 = split ? a[aOff[C_FIELD_ID] + 1] : u[uOff[C_FIELD_ID] + 1]; 223*66edf50cSStefano Zampini const PetscScalar C02 = split ? a[aOff[C_FIELD_ID] + 2] : u[uOff[C_FIELD_ID] + 2]; 224*66edf50cSStefano Zampini const PetscScalar C11 = split ? a[aOff[C_FIELD_ID] + 3] : u[uOff[C_FIELD_ID] + 3]; 225*66edf50cSStefano Zampini const PetscScalar C12 = split ? a[aOff[C_FIELD_ID] + 4] : u[uOff[C_FIELD_ID] + 4]; 226*66edf50cSStefano Zampini const PetscScalar C22 = split ? a[aOff[C_FIELD_ID] + 5] : u[uOff[C_FIELD_ID] + 5]; 227*66edf50cSStefano Zampini const PetscScalar norm = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 228*66edf50cSStefano Zampini const PetscScalar nexp = (gamma - 2.0) / 2.0; 229*66edf50cSStefano Zampini const PetscScalar fnorm = PetscPowScalar(norm, nexp); 230*66edf50cSStefano Zampini const PetscScalar dfnorm = nexp * PetscPowScalar(norm, nexp - 1.0); 231*66edf50cSStefano Zampini const PetscScalar dC[] = {2 * C00, 4 * C01, 4 * C02, 2 * C11, 4 * C12, 2 * C22}; 232*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 233*66edf50cSStefano Zampini 234*66edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) { 235*66edf50cSStefano Zampini if (!split) { 236*66edf50cSStefano Zampini for (PetscInt j = 0; j < 6; j++) J[k * 6 + j] = eqss[k] * (alpha * dfnorm * dC[j] * u[uOff[C_FIELD_ID] + k]); 237*66edf50cSStefano Zampini } 238*66edf50cSStefano 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 { 245*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 246*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 0.5}; 247811d88abSStefano Zampini 248*66edf50cSStefano Zampini J[0] = -2 * gradp[0] * eqss[0]; 249811d88abSStefano Zampini J[1] = 0.0; 250*66edf50cSStefano Zampini 251*66edf50cSStefano Zampini J[2] = -gradp[1] * eqss[1]; 252*66edf50cSStefano Zampini J[3] = -gradp[0] * eqss[1]; 253*66edf50cSStefano Zampini 254811d88abSStefano Zampini J[4] = 0.0; 255*66edf50cSStefano Zampini J[5] = -2 * gradp[1] * eqss[2]; 256*66edf50cSStefano Zampini } 257*66edf50cSStefano Zampini 258*66edf50cSStefano 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[]) 259*66edf50cSStefano Zampini { 260*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 261*66edf50cSStefano Zampini const PetscScalar eqss[] = {0.5, 1., 1., 0.5, 1., 0.5}; 262*66edf50cSStefano Zampini 263*66edf50cSStefano Zampini J[0] = -2 * gradp[0] * eqss[0]; 264*66edf50cSStefano Zampini J[1] = 0.0; 265*66edf50cSStefano Zampini J[2] = 0.0; 266*66edf50cSStefano Zampini 267*66edf50cSStefano Zampini J[3] = -gradp[1] * eqss[1]; 268*66edf50cSStefano Zampini J[4] = -gradp[0] * eqss[1]; 269*66edf50cSStefano Zampini J[5] = 0.0; 270*66edf50cSStefano Zampini 271*66edf50cSStefano Zampini J[6] = -gradp[2] * eqss[2]; 272*66edf50cSStefano Zampini J[7] = 0.0; 273*66edf50cSStefano Zampini J[8] = -gradp[0] * eqss[2]; 274*66edf50cSStefano Zampini 275*66edf50cSStefano Zampini J[9] = 0.0; 276*66edf50cSStefano Zampini J[10] = -2 * gradp[1] * eqss[3]; 277*66edf50cSStefano Zampini J[11] = 0.0; 278*66edf50cSStefano Zampini 279*66edf50cSStefano Zampini J[12] = 0.0; 280*66edf50cSStefano Zampini J[13] = -gradp[2] * eqss[4]; 281*66edf50cSStefano Zampini J[14] = -gradp[1] * eqss[4]; 282*66edf50cSStefano Zampini 283*66edf50cSStefano Zampini J[15] = 0.0; 284*66edf50cSStefano Zampini J[16] = 0.0; 285*66edf50cSStefano 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 296*66edf50cSStefano 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[]) 297*66edf50cSStefano Zampini { 298*66edf50cSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 299*66edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) 300*66edf50cSStefano Zampini for (PetscInt d = 0; d < 3; d++) f1[k * 3 + d] = PetscSqr(D) * u_x[uOff_x[C_FIELD_ID] + k * 3 + d]; 301*66edf50cSStefano Zampini } 302*66edf50cSStefano 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 311*66edf50cSStefano 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 { 313*66edf50cSStefano Zampini const PetscReal D = PetscRealPart(constants[D_ID]); 314*66edf50cSStefano Zampini for (PetscInt k = 0; k < 6; k++) 315*66edf50cSStefano Zampini for (PetscInt d = 0; d < 3; d++) J[k * (6 + 1) * 3 * 3 + d * 3 + d] = PetscSqr(D); 316811d88abSStefano Zampini } 317811d88abSStefano Zampini 318*66edf50cSStefano Zampini /* residual for P when tested against basis functions. 319*66edf50cSStefano Zampini The source term always comes from the auxiliary data because it must be zero mean (algebraically) */ 320*66edf50cSStefano 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 { 322*66edf50cSStefano Zampini PetscScalar S = a[aOff[NUM_FIELDS]]; 323204aa523SStefano Zampini 324*66edf50cSStefano Zampini f0[0] = S; 325*66edf50cSStefano Zampini } 326*66edf50cSStefano Zampini 327*66edf50cSStefano Zampini /* residual for P when tested against basis functions for the initial condition problem 328*66edf50cSStefano Zampini here we don't impose symmetry, and we thus flip the sign of the source function */ 329*66edf50cSStefano 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[]) 330*66edf50cSStefano Zampini { 331*66edf50cSStefano Zampini PetscScalar S = a[aOff[NUM_FIELDS]]; 332*66edf50cSStefano Zampini 333*66edf50cSStefano 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; 344*66edf50cSStefano 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 348*66edf50cSStefano Zampini f1[0] = -((C00 + s) * gradp[0] + C01 * gradp[1]); 349*66edf50cSStefano Zampini f1[1] = -(C10 * gradp[0] + (C11 + s) * gradp[1]); 350811d88abSStefano Zampini } 351811d88abSStefano Zampini 352*66edf50cSStefano 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[]) 353*66edf50cSStefano Zampini { 354*66edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 355*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 356*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 357*66edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 358*66edf50cSStefano Zampini const PetscScalar C10 = C01; 359*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 360*66edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 361*66edf50cSStefano Zampini const PetscScalar C20 = C02; 362*66edf50cSStefano Zampini const PetscScalar C21 = C12; 363*66edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 364*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 365*66edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 366*66edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 367*66edf50cSStefano Zampini 368*66edf50cSStefano Zampini f1[0] = -((C00 + s) * gradp[0] + C01 * gradp[1] + C02 * gradp[2]); 369*66edf50cSStefano Zampini f1[1] = -(C10 * gradp[0] + (C11 + s) * gradp[1] + C12 * gradp[2]); 370*66edf50cSStefano Zampini f1[2] = -(C20 * gradp[0] + C21 * gradp[1] + (C22 + s) * gradp[2]); 371*66edf50cSStefano Zampini } 372*66edf50cSStefano Zampini 373*66edf50cSStefano 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; 381*66edf50cSStefano 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 389*66edf50cSStefano 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[]) 390*66edf50cSStefano Zampini { 391*66edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 392*66edf50cSStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 393*66edf50cSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 394*66edf50cSStefano Zampini const PetscScalar C02 = a[aOff[C_FIELD_ID] + 2]; 395*66edf50cSStefano Zampini const PetscScalar C10 = C01; 396*66edf50cSStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 3] + r; 397*66edf50cSStefano Zampini const PetscScalar C12 = a[aOff[C_FIELD_ID] + 4]; 398*66edf50cSStefano Zampini const PetscScalar C20 = C02; 399*66edf50cSStefano Zampini const PetscScalar C21 = C12; 400*66edf50cSStefano Zampini const PetscScalar C22 = a[aOff[C_FIELD_ID] + 5] + r; 401*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[Nf > 1 ? P_FIELD_ID : 0]; 402*66edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 1.0); 403*66edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 404*66edf50cSStefano Zampini 405*66edf50cSStefano Zampini f1[0] = (C00 + s) * gradp[0] + C01 * gradp[1] + C02 * gradp[2]; 406*66edf50cSStefano Zampini f1[1] = C10 * gradp[0] + (C11 + s) * gradp[1] + C12 * gradp[2]; 407*66edf50cSStefano Zampini f1[2] = C20 * gradp[0] + C21 * gradp[1] + (C22 + s) * gradp[2]; 408*66edf50cSStefano Zampini } 409*66edf50cSStefano 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 421*66edf50cSStefano Zampini J[0] = -(C00 + s); 422*66edf50cSStefano Zampini J[1] = -C01; 423*66edf50cSStefano Zampini J[2] = -C10; 424*66edf50cSStefano Zampini J[3] = -(C11 + s); 425811d88abSStefano Zampini } 426811d88abSStefano Zampini 427*66edf50cSStefano 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[]) 428*66edf50cSStefano Zampini { 429*66edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 430*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 431*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 432*66edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 433*66edf50cSStefano Zampini const PetscScalar C10 = C01; 434*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 435*66edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 436*66edf50cSStefano Zampini const PetscScalar C20 = C02; 437*66edf50cSStefano Zampini const PetscScalar C21 = C12; 438*66edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 439*66edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 440*66edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 441*66edf50cSStefano Zampini 442*66edf50cSStefano Zampini J[0] = -(C00 + s); 443*66edf50cSStefano Zampini J[1] = -C01; 444*66edf50cSStefano Zampini J[2] = -C02; 445*66edf50cSStefano Zampini J[3] = -C10; 446*66edf50cSStefano Zampini J[4] = -(C11 + s); 447*66edf50cSStefano Zampini J[5] = -C12; 448*66edf50cSStefano Zampini J[6] = -C20; 449*66edf50cSStefano Zampini J[7] = -C21; 450*66edf50cSStefano Zampini J[8] = -(C22 + s); 451*66edf50cSStefano Zampini } 452*66edf50cSStefano 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 469*66edf50cSStefano 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[]) 470*66edf50cSStefano Zampini { 471*66edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 472*66edf50cSStefano Zampini const PetscScalar C00 = a[aOff[C_FIELD_ID]] + r; 473*66edf50cSStefano Zampini const PetscScalar C01 = a[aOff[C_FIELD_ID] + 1]; 474*66edf50cSStefano Zampini const PetscScalar C02 = a[aOff[C_FIELD_ID] + 2]; 475*66edf50cSStefano Zampini const PetscScalar C10 = C01; 476*66edf50cSStefano Zampini const PetscScalar C11 = a[aOff[C_FIELD_ID] + 3] + r; 477*66edf50cSStefano Zampini const PetscScalar C12 = a[aOff[C_FIELD_ID] + 4]; 478*66edf50cSStefano Zampini const PetscScalar C20 = C02; 479*66edf50cSStefano Zampini const PetscScalar C21 = C12; 480*66edf50cSStefano Zampini const PetscScalar C22 = a[aOff[C_FIELD_ID] + 5] + r; 481*66edf50cSStefano Zampini const PetscBool fix_c = (PetscBool)(PetscRealPart(constants[FIXC_ID]) > 0.0); 482*66edf50cSStefano Zampini const PetscScalar s = fix_c ? FIX_C_3d(C00, C01, C02, C11, C12, C22) : 0.0; 483*66edf50cSStefano Zampini 484*66edf50cSStefano Zampini J[0] = C00 + s; 485*66edf50cSStefano Zampini J[1] = C01; 486*66edf50cSStefano Zampini J[2] = C02; 487*66edf50cSStefano Zampini J[3] = C10; 488*66edf50cSStefano Zampini J[4] = C11 + s; 489*66edf50cSStefano Zampini J[5] = C12; 490*66edf50cSStefano Zampini J[6] = C20; 491*66edf50cSStefano Zampini J[7] = C21; 492*66edf50cSStefano Zampini J[8] = C22 + s; 493*66edf50cSStefano Zampini } 494*66edf50cSStefano 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 { 498*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 499811d88abSStefano Zampini 500*66edf50cSStefano Zampini J[0] = -gradp[0]; 501811d88abSStefano Zampini J[1] = 0; 502*66edf50cSStefano Zampini 503*66edf50cSStefano Zampini J[2] = -gradp[1]; 504*66edf50cSStefano Zampini J[3] = -gradp[0]; 505*66edf50cSStefano Zampini 506811d88abSStefano Zampini J[4] = 0; 507*66edf50cSStefano Zampini J[5] = -gradp[1]; 508811d88abSStefano Zampini } 509811d88abSStefano Zampini 510*66edf50cSStefano 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 { 512*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 513*66edf50cSStefano Zampini 514*66edf50cSStefano Zampini J[0] = -gradp[0]; 515*66edf50cSStefano Zampini J[1] = 0; 516*66edf50cSStefano Zampini J[2] = 0; 517*66edf50cSStefano Zampini 518*66edf50cSStefano Zampini J[3] = -gradp[1]; 519*66edf50cSStefano Zampini J[4] = -gradp[0]; 520*66edf50cSStefano Zampini J[5] = 0; 521*66edf50cSStefano Zampini 522*66edf50cSStefano Zampini J[6] = -gradp[2]; 523*66edf50cSStefano Zampini J[7] = 0; 524*66edf50cSStefano Zampini J[8] = -gradp[0]; 525*66edf50cSStefano Zampini 526*66edf50cSStefano Zampini J[9] = 0; 527*66edf50cSStefano Zampini J[10] = -gradp[1]; 528*66edf50cSStefano Zampini J[11] = 0; 529*66edf50cSStefano Zampini 530*66edf50cSStefano Zampini J[12] = 0; 531*66edf50cSStefano Zampini J[13] = -gradp[2]; 532*66edf50cSStefano Zampini J[14] = -gradp[1]; 533*66edf50cSStefano Zampini 534*66edf50cSStefano Zampini J[15] = 0; 535*66edf50cSStefano Zampini J[16] = 0; 536*66edf50cSStefano Zampini J[17] = -gradp[2]; 537*66edf50cSStefano Zampini } 538*66edf50cSStefano Zampini 539*66edf50cSStefano Zampini /* a collection of gaussian, Dirac-like, source term S(x) = scale * cos(2*pi*(frequency*t + phase)) * exp(-w*||x - x0||^2) */ 540*66edf50cSStefano Zampini typedef struct { 541*66edf50cSStefano Zampini PetscInt n; 542*66edf50cSStefano Zampini PetscReal *x0; 543*66edf50cSStefano Zampini PetscReal *w; 544*66edf50cSStefano Zampini PetscReal *k; 545*66edf50cSStefano Zampini PetscReal *p; 546*66edf50cSStefano Zampini PetscReal *r; 547*66edf50cSStefano Zampini } MultiSourceCtx; 548*66edf50cSStefano Zampini 549*66edf50cSStefano Zampini typedef struct { 550*66edf50cSStefano Zampini PetscReal x0[3]; 551*66edf50cSStefano Zampini PetscReal w; 552*66edf50cSStefano Zampini PetscReal k; 553*66edf50cSStefano Zampini PetscReal p; 554*66edf50cSStefano Zampini PetscReal r; 555*66edf50cSStefano Zampini } SingleSourceCtx; 556*66edf50cSStefano Zampini 557*66edf50cSStefano Zampini static PetscErrorCode gaussian(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx) 558*66edf50cSStefano Zampini { 559*66edf50cSStefano Zampini SingleSourceCtx *s = (SingleSourceCtx *)ctx; 560*66edf50cSStefano Zampini const PetscReal *x0 = s->x0; 561*66edf50cSStefano Zampini const PetscReal w = s->w; 562*66edf50cSStefano Zampini const PetscReal k = s->k; /* frequency */ 563*66edf50cSStefano Zampini const PetscReal p = s->p; /* phase */ 564*66edf50cSStefano 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]); 568*66edf50cSStefano Zampini u[0] = r * PetscCosReal(2 * PETSC_PI * (k * time + p)) * PetscExpReal(-w * n); 569811d88abSStefano Zampini return PETSC_SUCCESS; 570811d88abSStefano Zampini } 571811d88abSStefano Zampini 572*66edf50cSStefano Zampini static PetscErrorCode source(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nf, PetscScalar *u, void *ctx) 573811d88abSStefano Zampini { 574*66edf50cSStefano Zampini MultiSourceCtx *s = (MultiSourceCtx *)ctx; 575811d88abSStefano Zampini 576*66edf50cSStefano Zampini u[0] = 0.0; 577*66edf50cSStefano Zampini for (PetscInt i = 0; i < s->n; i++) { 578*66edf50cSStefano Zampini SingleSourceCtx sctx; 579*66edf50cSStefano Zampini PetscScalar ut[1]; 580*66edf50cSStefano Zampini 581*66edf50cSStefano Zampini sctx.x0[0] = s->x0[dim * i]; 582*66edf50cSStefano Zampini sctx.x0[1] = s->x0[dim * i + 1]; 583*66edf50cSStefano Zampini sctx.x0[2] = dim > 2 ? s->x0[dim * i + 2] : 0.0; 584*66edf50cSStefano Zampini sctx.w = s->w[i]; 585*66edf50cSStefano Zampini sctx.k = s->k[i]; 586*66edf50cSStefano Zampini sctx.p = s->p[i]; 587*66edf50cSStefano Zampini sctx.r = s->r[i]; 588*66edf50cSStefano Zampini 589*66edf50cSStefano Zampini PetscCall(gaussian(dim, time, x, Nf, ut, &sctx)); 590*66edf50cSStefano Zampini 591811d88abSStefano Zampini u[0] += ut[0]; 592*66edf50cSStefano 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 { 599*66edf50cSStefano Zampini const PetscInt fid = (PetscInt)PetscRealPart(constants[numConstants]); 600*66edf50cSStefano Zampini obj[0] = u[uOff[fid]]; 601811d88abSStefano Zampini } 602811d88abSStefano Zampini 603*66edf50cSStefano Zampini /* functionals to be integrated: volume -> \int_\Omega dx */ 604*66edf50cSStefano 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 { 606*66edf50cSStefano 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]); 616*66edf50cSStefano Zampini const PetscReal eps = PetscRealPart(constants[EPS_ID]); 617*66edf50cSStefano Zampini 618*66edf50cSStefano 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]; 623*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 624*66edf50cSStefano Zampini const PetscScalar *gradC00 = u_x + uOff_x[C_FIELD_ID]; 625*66edf50cSStefano Zampini const PetscScalar *gradC01 = u_x + uOff_x[C_FIELD_ID] + 2; 626*66edf50cSStefano Zampini const PetscScalar *gradC11 = u_x + uOff_x[C_FIELD_ID] + 4; 627*66edf50cSStefano 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; 632*66edf50cSStefano Zampini const PetscScalar t1 = gradp[0] * ((C00 + r) * gradp[0] + C01 * gradp[1]) + gradp[1] * (C10 * gradp[0] + (C11 + r) * gradp[1]); 633*66edf50cSStefano Zampini const PetscScalar t2 = alpha / gamma * PetscPowScalar(normC, nexp); 634*66edf50cSStefano Zampini 635*66edf50cSStefano Zampini obj[0] = t0 + t1 + t2; 636*66edf50cSStefano Zampini } else { 637*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 638*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 639*66edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 640*66edf50cSStefano Zampini const PetscScalar C10 = C01; 641*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3]; 642*66edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 643*66edf50cSStefano Zampini const PetscScalar C20 = C02; 644*66edf50cSStefano Zampini const PetscScalar C21 = C12; 645*66edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5]; 646*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 647*66edf50cSStefano Zampini const PetscScalar *gradC00 = u_x + uOff_x[C_FIELD_ID]; 648*66edf50cSStefano Zampini const PetscScalar *gradC01 = u_x + uOff_x[C_FIELD_ID] + 3; 649*66edf50cSStefano Zampini const PetscScalar *gradC02 = u_x + uOff_x[C_FIELD_ID] + 6; 650*66edf50cSStefano Zampini const PetscScalar *gradC11 = u_x + uOff_x[C_FIELD_ID] + 9; 651*66edf50cSStefano Zampini const PetscScalar *gradC12 = u_x + uOff_x[C_FIELD_ID] + 12; 652*66edf50cSStefano Zampini const PetscScalar *gradC22 = u_x + uOff_x[C_FIELD_ID] + 15; 653*66edf50cSStefano Zampini const PetscScalar normC = NORM2C_3d(C00, C01, C02, C11, C12, C22) + eps; 654*66edf50cSStefano 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]); 655*66edf50cSStefano Zampini const PetscScalar nexp = gamma / 2.0; 656*66edf50cSStefano Zampini 657*66edf50cSStefano Zampini const PetscScalar t0 = PetscSqr(D) / 2.0 * normgradC; 658*66edf50cSStefano 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 } 663*66edf50cSStefano Zampini } 664811d88abSStefano Zampini 665*66edf50cSStefano Zampini /* functionals to be integrated: ellipticity_fail_private -> see below */ 666*66edf50cSStefano 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) 667*66edf50cSStefano Zampini { 668*66edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 669*66edf50cSStefano Zampini PetscReal eigs[3]; 670*66edf50cSStefano Zampini PetscScalar C00, C01, C02 = 0.0, C11, C12 = 0.0, C22 = 0.0; 671*66edf50cSStefano Zampini const PetscReal r = add_reg ? PetscRealPart(constants[R_ID]) : 0.0; 672*66edf50cSStefano Zampini 673*66edf50cSStefano Zampini if (dim == 2) { 674*66edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]] + r; 675*66edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 676*66edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 2] + r; 677*66edf50cSStefano Zampini } else { 678*66edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]] + r; 679*66edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 680*66edf50cSStefano Zampini C02 = u[uOff[C_FIELD_ID] + 2]; 681*66edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 3] + r; 682*66edf50cSStefano Zampini C12 = u[uOff[C_FIELD_ID] + 4]; 683*66edf50cSStefano Zampini C22 = u[uOff[C_FIELD_ID] + 5] + r; 684*66edf50cSStefano Zampini } 685*66edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 686*66edf50cSStefano Zampini if (eigs[0] < 0 || eigs[1] < 0 || eigs[2] < 0) obj[0] = -PetscMin(eigs[0], PetscMin(eigs[1], eigs[2])); 687*66edf50cSStefano Zampini else obj[0] = 0.0; 688*66edf50cSStefano Zampini #else 689*66edf50cSStefano Zampini obj[0] = 0.0; 690*66edf50cSStefano Zampini #endif 691*66edf50cSStefano Zampini } 692*66edf50cSStefano Zampini 693*66edf50cSStefano 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 { 696*66edf50cSStefano 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); 697*66edf50cSStefano Zampini if (PetscAbsScalar(obj[0]) > 0.0) obj[0] = 1.0; 698*66edf50cSStefano Zampini } 699811d88abSStefano Zampini 700*66edf50cSStefano 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 */ 701*66edf50cSStefano 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[]) 702*66edf50cSStefano Zampini { 703*66edf50cSStefano 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 { 709*66edf50cSStefano Zampini if (dim == 2) { 710811d88abSStefano Zampini u[0] = 1; 711811d88abSStefano Zampini u[1] = 0; 712811d88abSStefano Zampini u[2] = 1; 713*66edf50cSStefano Zampini } else { 714*66edf50cSStefano Zampini u[0] = 1; 715*66edf50cSStefano Zampini u[1] = 0; 716*66edf50cSStefano Zampini u[2] = 0; 717*66edf50cSStefano Zampini u[3] = 1; 718*66edf50cSStefano Zampini u[4] = 0; 719*66edf50cSStefano Zampini u[5] = 1; 720*66edf50cSStefano 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 730*66edf50cSStefano 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; 743*66edf50cSStefano Zampini if (dim == 3) { 744*66edf50cSStefano Zampini u[3] = 0; 745*66edf50cSStefano Zampini u[4] = 0; 746*66edf50cSStefano Zampini u[5] = 0; 747*66edf50cSStefano Zampini } 748811d88abSStefano Zampini return PETSC_SUCCESS; 749811d88abSStefano Zampini } 750811d88abSStefano Zampini 751*66edf50cSStefano Zampini /* random initial conditions for the diagonal of C */ 752*66edf50cSStefano Zampini static PetscErrorCode initial_conditions_C_random(PetscInt dim, PetscReal time, const PetscReal xx[], PetscInt Nc, PetscScalar *u, void *ctx) 753811d88abSStefano Zampini { 754*66edf50cSStefano Zampini PetscScalar vals[3]; 755*66edf50cSStefano Zampini PetscRandom r = (PetscRandom)ctx; 756811d88abSStefano Zampini 757*66edf50cSStefano Zampini PetscCall(PetscRandomGetValues(r, dim, vals)); 758*66edf50cSStefano Zampini if (dim == 2) { 759*66edf50cSStefano Zampini u[0] = vals[0]; 760*66edf50cSStefano Zampini u[1] = 0; 761*66edf50cSStefano Zampini u[2] = vals[1]; 762*66edf50cSStefano Zampini } else { 763*66edf50cSStefano Zampini u[0] = vals[0]; 764*66edf50cSStefano Zampini u[1] = 0; 765*66edf50cSStefano Zampini u[2] = 0; 766*66edf50cSStefano Zampini u[3] = vals[1]; 767*66edf50cSStefano Zampini u[4] = 0; 768*66edf50cSStefano Zampini u[5] = vals[2]; 769811d88abSStefano Zampini } 770*66edf50cSStefano 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 779*66edf50cSStefano Zampini /* functionals to be sampled: - (C + r) * \grad p */ 780*66edf50cSStefano 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[]) 781*66edf50cSStefano Zampini { 782*66edf50cSStefano Zampini const PetscReal r = PetscRealPart(constants[R_ID]); 783*66edf50cSStefano Zampini const PetscScalar *gradp = u_x + uOff_x[P_FIELD_ID]; 784*66edf50cSStefano Zampini 785*66edf50cSStefano Zampini if (dim == 2) { 786*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 787*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 788*66edf50cSStefano Zampini const PetscScalar C10 = C01; 789*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2] + r; 790*66edf50cSStefano Zampini 791*66edf50cSStefano Zampini f[0] = -C00 * gradp[0] - C01 * gradp[1]; 792*66edf50cSStefano Zampini f[1] = -C10 * gradp[0] - C11 * gradp[1]; 793*66edf50cSStefano Zampini } else { 794*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]] + r; 795*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 796*66edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 797*66edf50cSStefano Zampini const PetscScalar C10 = C01; 798*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3] + r; 799*66edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 800*66edf50cSStefano Zampini const PetscScalar C20 = C02; 801*66edf50cSStefano Zampini const PetscScalar C21 = C12; 802*66edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5] + r; 803*66edf50cSStefano Zampini 804*66edf50cSStefano Zampini f[0] = -C00 * gradp[0] - C01 * gradp[1] - C02 * gradp[2]; 805*66edf50cSStefano Zampini f[1] = -C10 * gradp[0] - C11 * gradp[1] - C12 * gradp[2]; 806*66edf50cSStefano Zampini f[2] = -C20 * gradp[0] - C21 * gradp[1] - C22 * gradp[2]; 807*66edf50cSStefano Zampini } 808*66edf50cSStefano Zampini } 809*66edf50cSStefano Zampini 810*66edf50cSStefano Zampini /* functionals to be sampled: ||C|| */ 811*66edf50cSStefano 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[]) 812*66edf50cSStefano Zampini { 813*66edf50cSStefano Zampini if (dim == 2) { 814*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 815*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 816*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 2]; 817*66edf50cSStefano Zampini 818*66edf50cSStefano Zampini f[0] = PetscSqrtReal(PetscRealPart(NORM2C(C00, C01, C11))); 819*66edf50cSStefano Zampini } else { 820*66edf50cSStefano Zampini const PetscScalar C00 = u[uOff[C_FIELD_ID]]; 821*66edf50cSStefano Zampini const PetscScalar C01 = u[uOff[C_FIELD_ID] + 1]; 822*66edf50cSStefano Zampini const PetscScalar C02 = u[uOff[C_FIELD_ID] + 2]; 823*66edf50cSStefano Zampini const PetscScalar C11 = u[uOff[C_FIELD_ID] + 3]; 824*66edf50cSStefano Zampini const PetscScalar C12 = u[uOff[C_FIELD_ID] + 4]; 825*66edf50cSStefano Zampini const PetscScalar C22 = u[uOff[C_FIELD_ID] + 5]; 826*66edf50cSStefano Zampini 827*66edf50cSStefano Zampini f[0] = PetscSqrtReal(PetscRealPart(NORM2C_3d(C00, C01, C02, C11, C12, C22))); 828*66edf50cSStefano Zampini } 829*66edf50cSStefano Zampini } 830*66edf50cSStefano Zampini 831*66edf50cSStefano Zampini /* functionals to be sampled: eigenvalues of C */ 832*66edf50cSStefano 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[]) 833*66edf50cSStefano Zampini { 834*66edf50cSStefano Zampini #if !PetscDefined(USE_COMPLEX) 835*66edf50cSStefano Zampini PetscReal eigs[3]; 836*66edf50cSStefano Zampini PetscScalar C00, C01, C02 = 0.0, C11, C12 = 0.0, C22 = 0.0; 837*66edf50cSStefano Zampini if (dim == 2) { 838*66edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]]; 839*66edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 840*66edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 2]; 841*66edf50cSStefano Zampini } else { 842*66edf50cSStefano Zampini C00 = u[uOff[C_FIELD_ID]]; 843*66edf50cSStefano Zampini C01 = u[uOff[C_FIELD_ID] + 1]; 844*66edf50cSStefano Zampini C02 = u[uOff[C_FIELD_ID] + 2]; 845*66edf50cSStefano Zampini C11 = u[uOff[C_FIELD_ID] + 3]; 846*66edf50cSStefano Zampini C12 = u[uOff[C_FIELD_ID] + 4]; 847*66edf50cSStefano Zampini C22 = u[uOff[C_FIELD_ID] + 5]; 848*66edf50cSStefano Zampini } 849*66edf50cSStefano Zampini Eigenvalues_Sym3x3(C00, C01, C02, C11, C12, C22, eigs); 850*66edf50cSStefano Zampini PetscCallVoid(PetscSortReal(dim, eigs)); 851*66edf50cSStefano Zampini for (PetscInt d = 0; d < dim; d++) f[d] = eigs[d]; 852*66edf50cSStefano Zampini #else 853*66edf50cSStefano Zampini for (PetscInt d = 0; d < dim; d++) f[d] = 0; 854*66edf50cSStefano Zampini #endif 855*66edf50cSStefano Zampini } 856*66edf50cSStefano 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 { 867*66edf50cSStefano 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 { 873*66edf50cSStefano Zampini PetscInt dim; 874*66edf50cSStefano Zampini PetscBool simplex; 875811d88abSStefano Zampini PetscReal r; 876811d88abSStefano Zampini PetscReal eps; 877811d88abSStefano Zampini PetscReal alpha; 878811d88abSStefano Zampini PetscReal gamma; 879811d88abSStefano Zampini PetscReal D; 880*66edf50cSStefano Zampini PetscReal domain_volume; 881811d88abSStefano Zampini PetscInt ic_num; 882*66edf50cSStefano 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; 892*66edf50cSStefano Zampini MultiSourceCtx *source_ctx; 893*66edf50cSStefano Zampini DM view_dm; 894*66edf50cSStefano Zampini TSMonitorVTKCtx view_vtk_ctx; 895*66edf50cSStefano Zampini PetscViewerAndFormat *view_hdf5_ctx; 896*66edf50cSStefano Zampini PetscInt diagnostic_num; 897*66edf50cSStefano Zampini PetscReal view_times[64]; 898*66edf50cSStefano Zampini PetscInt view_times_n, view_times_k; 899*66edf50cSStefano Zampini PetscReal function_domain_error_tol; 900*66edf50cSStefano Zampini VecScatter subsct[NUM_FIELDS]; 901*66edf50cSStefano Zampini Vec subvec[NUM_FIELDS]; 902*66edf50cSStefano Zampini PetscBool monitor_norms; 903*66edf50cSStefano Zampini PetscBool exclude_potential_lte; 904*66edf50cSStefano Zampini 905*66edf50cSStefano Zampini /* hack: need some more plumbing in the library */ 906*66edf50cSStefano Zampini SNES snes; 907811d88abSStefano Zampini } AppCtx; 908811d88abSStefano Zampini 909811d88abSStefano Zampini /* process command line options */ 910*66edf50cSStefano Zampini #include <petsc/private/tsimpl.h> /* To access TSMonitorVTKCtx */ 911811d88abSStefano Zampini static PetscErrorCode ProcessOptions(AppCtx *options) 912811d88abSStefano Zampini { 913*66edf50cSStefano Zampini char vtkmonfilename[PETSC_MAX_PATH_LEN]; 914*66edf50cSStefano Zampini char hdf5monfilename[PETSC_MAX_PATH_LEN]; 915*66edf50cSStefano Zampini PetscInt tmp; 916*66edf50cSStefano Zampini PetscBool flg; 917811d88abSStefano Zampini 918811d88abSStefano Zampini PetscFunctionBeginUser; 919*66edf50cSStefano 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; 926*66edf50cSStefano 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; 933*66edf50cSStefano Zampini options->fix_c = 1; /* 1 means only Jac, 2 means function and Jac, < 0 means raise SNESFunctionDomainError when C+r is not posdef */ 934*66edf50cSStefano Zampini options->view_vtk_ctx = NULL; 935*66edf50cSStefano Zampini options->view_hdf5_ctx = NULL; 936*66edf50cSStefano Zampini options->view_dm = NULL; 937*66edf50cSStefano Zampini options->diagnostic_num = 1; 938*66edf50cSStefano Zampini options->function_domain_error_tol = -1; 939*66edf50cSStefano Zampini options->monitor_norms = PETSC_FALSE; 940*66edf50cSStefano Zampini options->exclude_potential_lte = PETSC_FALSE; 941*66edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 942*66edf50cSStefano Zampini options->subsct[i] = NULL; 943*66edf50cSStefano Zampini options->subvec[i] = NULL; 944*66edf50cSStefano Zampini } 945*66edf50cSStefano 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"); 948*66edf50cSStefano 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)); 955*66edf50cSStefano 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)); 957*66edf50cSStefano 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)); 959*66edf50cSStefano 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 } 966*66edf50cSStefano Zampini PetscCall(PetscOptionsBool("-exclude_potential_lte", "exclude potential from LTE", __FILE__, options->exclude_potential_lte, &options->exclude_potential_lte, NULL)); 967*66edf50cSStefano Zampini options->view_times_k = 0; 968*66edf50cSStefano Zampini options->view_times_n = 0; 969*66edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-monitor_times", "Save at specific times", NULL, options->view_times, (tmp = 64, &tmp), &flg)); 970*66edf50cSStefano Zampini if (flg) options->view_times_n = tmp; 971*66edf50cSStefano Zampini 972*66edf50cSStefano Zampini PetscCall(PetscOptionsString("-monitor_vtk", "Dump VTK file for diagnostic", "TSMonitorSolutionVTK", NULL, vtkmonfilename, sizeof(vtkmonfilename), &flg)); 973*66edf50cSStefano Zampini if (flg) { 974*66edf50cSStefano Zampini PetscCall(TSMonitorSolutionVTKCtxCreate(vtkmonfilename, &options->view_vtk_ctx)); 975*66edf50cSStefano Zampini PetscCall(PetscOptionsInt("-monitor_vtk_interval", "Save every interval time steps", NULL, options->view_vtk_ctx->interval, &options->view_vtk_ctx->interval, NULL)); 976*66edf50cSStefano Zampini } 977*66edf50cSStefano Zampini PetscCall(PetscOptionsString("-monitor_hdf5", "Dump HDF5 file for diagnostic", "TSMonitorSolution", NULL, hdf5monfilename, sizeof(hdf5monfilename), &flg)); 978*66edf50cSStefano Zampini PetscCall(PetscOptionsInt("-monitor_diagnostic_num", "Number of diagnostics to be computed", __FILE__, options->diagnostic_num, &options->diagnostic_num, NULL)); 979*66edf50cSStefano Zampini 980*66edf50cSStefano Zampini if (flg) { 981*66edf50cSStefano Zampini #if defined(PETSC_HAVE_HDF5) 982*66edf50cSStefano Zampini PetscViewer viewer; 983*66edf50cSStefano Zampini 984*66edf50cSStefano Zampini PetscCall(PetscViewerHDF5Open(PETSC_COMM_WORLD, hdf5monfilename, FILE_MODE_WRITE, &viewer)); 985*66edf50cSStefano Zampini PetscCall(PetscViewerAndFormatCreate(viewer, PETSC_VIEWER_HDF5_VIZ, &options->view_hdf5_ctx)); 986*66edf50cSStefano Zampini options->view_hdf5_ctx->view_interval = 1; 987*66edf50cSStefano 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)); 988*66edf50cSStefano Zampini PetscCall(PetscViewerDestroy(&viewer)); 989*66edf50cSStefano Zampini #else 990*66edf50cSStefano Zampini SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_SUP, "Needs HDF5 support. Please reconfigure using --download-hdf5"); 991*66edf50cSStefano Zampini #endif 992*66edf50cSStefano Zampini } 993*66edf50cSStefano Zampini PetscCall(PetscOptionsBool("-monitor_norms", "Monitor separate SNES norms", __FILE__, options->monitor_norms, &options->monitor_norms, NULL)); 994*66edf50cSStefano Zampini 995*66edf50cSStefano Zampini /* source options */ 996*66edf50cSStefano Zampini PetscCall(PetscNew(&options->source_ctx)); 997*66edf50cSStefano Zampini options->source_ctx->n = 1; 998*66edf50cSStefano Zampini 999*66edf50cSStefano Zampini PetscCall(PetscOptionsInt("-source_num", "number of sources", __FILE__, options->source_ctx->n, &options->source_ctx->n, NULL)); 1000*66edf50cSStefano Zampini tmp = options->source_ctx->n; 1001*66edf50cSStefano 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)); 1002*66edf50cSStefano Zampini for (PetscInt i = 0; i < options->source_ctx->n; i++) { 1003*66edf50cSStefano Zampini for (PetscInt d = 0; d < options->dim; d++) { options->source_ctx->x0[options->dim * i + d] = 0.25; } 1004*66edf50cSStefano Zampini options->source_ctx->w[i] = 500; 1005*66edf50cSStefano Zampini options->source_ctx->k[i] = 0; 1006*66edf50cSStefano Zampini options->source_ctx->p[i] = 0; 1007*66edf50cSStefano Zampini options->source_ctx->r[i] = 1; 1008*66edf50cSStefano Zampini } 1009*66edf50cSStefano Zampini tmp = options->dim * options->source_ctx->n; 1010*66edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_x0", "source location", __FILE__, options->source_ctx->x0, &tmp, NULL)); 1011*66edf50cSStefano Zampini tmp = options->source_ctx->n; 1012*66edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_w", "source factor", __FILE__, options->source_ctx->w, &tmp, NULL)); 1013*66edf50cSStefano Zampini tmp = options->source_ctx->n; 1014*66edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_k", "source frequency", __FILE__, options->source_ctx->k, &tmp, NULL)); 1015*66edf50cSStefano Zampini tmp = options->source_ctx->n; 1016*66edf50cSStefano Zampini PetscCall(PetscOptionsRealArray("-source_p", "source phase", __FILE__, options->source_ctx->p, &tmp, NULL)); 1017*66edf50cSStefano Zampini tmp = options->source_ctx->n; 1018*66edf50cSStefano 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 1274*66edf50cSStefano Zampini /* 1275*66edf50cSStefano Zampini Setup AuxDM: 1276*66edf50cSStefano Zampini - project source function and make it zero-mean 1277*66edf50cSStefano Zampini - sample frozen fields for operator splitting 1278*66edf50cSStefano Zampini */ 1279*66edf50cSStefano Zampini static PetscErrorCode ProjectAuxDM(DM dm, PetscReal time, Vec u, AppCtx *ctx) 1280811d88abSStefano Zampini { 1281811d88abSStefano Zampini DM dmAux; 1282*66edf50cSStefano Zampini Vec la, a; 1283*66edf50cSStefano Zampini void *ctxs[NUM_FIELDS + 1]; 1284*66edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS + 1]; 1285*66edf50cSStefano Zampini VecScatter sctAux; 1286811d88abSStefano Zampini PetscDS ds; 1287*66edf50cSStefano Zampini PetscErrorCode (*funcs[NUM_FIELDS + 1])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *); 1288811d88abSStefano Zampini 1289811d88abSStefano Zampini PetscFunctionBeginUser; 1290*66edf50cSStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &la)); 1291*66edf50cSStefano Zampini if (!la) { 1292*66edf50cSStefano Zampini PetscFE field; 1293*66edf50cSStefano Zampini PetscInt fields[NUM_FIELDS]; 1294*66edf50cSStefano Zampini IS is; 1295*66edf50cSStefano Zampini Vec tu, ta; 1296*66edf50cSStefano Zampini PetscInt dim; 1297*66edf50cSStefano Zampini 1298*66edf50cSStefano Zampini PetscCall(DMClone(dm, &dmAux)); 1299*66edf50cSStefano Zampini PetscCall(DMSetNumFields(dmAux, NUM_FIELDS + 1)); 1300*66edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 1301*66edf50cSStefano Zampini PetscCall(DMGetField(dm, i, NULL, (PetscObject *)&field)); 1302*66edf50cSStefano Zampini PetscCall(DMSetField(dmAux, i, NULL, (PetscObject)field)); 1303*66edf50cSStefano Zampini fields[i] = i; 1304811d88abSStefano Zampini } 1305*66edf50cSStefano Zampini /* PetscFEDuplicate? */ 1306*66edf50cSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 1307*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, 1, ctx->simplex, "p_", -1, &field)); 1308*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)field, "source")); 1309*66edf50cSStefano Zampini PetscCall(DMSetField(dmAux, NUM_FIELDS, NULL, (PetscObject)field)); 1310*66edf50cSStefano Zampini PetscCall(PetscFEDestroy(&field)); 1311*66edf50cSStefano Zampini PetscCall(DMCreateDS(dmAux)); 1312*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(dmAux, NUM_FIELDS, fields, &is, NULL)); 1313*66edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dm, &tu)); 1314*66edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dmAux, &ta)); 1315*66edf50cSStefano Zampini PetscCall(VecScatterCreate(tu, NULL, ta, is, &sctAux)); 1316*66edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &tu)); 1317*66edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dmAux, &ta)); 1318*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dmAux, "scatterAux", (PetscObject)sctAux)); 1319*66edf50cSStefano Zampini PetscCall(VecScatterDestroy(&sctAux)); 1320*66edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 1321*66edf50cSStefano Zampini PetscCall(DMCreateLocalVector(dmAux, &la)); 1322*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)la, "auxiliary_")); 1323*66edf50cSStefano Zampini PetscCall(DMSetAuxiliaryVec(dm, NULL, 0, 0, la)); 1324*66edf50cSStefano Zampini PetscCall(DMDestroy(&dmAux)); 1325*66edf50cSStefano Zampini PetscCall(VecDestroy(&la)); 1326*66edf50cSStefano Zampini } 1327*66edf50cSStefano Zampini if (time == PETSC_MIN_REAL) PetscFunctionReturn(PETSC_SUCCESS); 1328*66edf50cSStefano Zampini 1329*66edf50cSStefano Zampini PetscCall(DMGetAuxiliaryVec(dm, NULL, 0, 0, &la)); 1330*66edf50cSStefano Zampini PetscCall(VecGetDM(la, &dmAux)); 1331*66edf50cSStefano Zampini PetscCall(DMGetDS(dmAux, &ds)); 1332*66edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dmAux, &a)); 1333811d88abSStefano Zampini funcs[C_FIELD_ID] = zerof; 1334811d88abSStefano Zampini ctxs[C_FIELD_ID] = NULL; 1335*66edf50cSStefano Zampini funcs[P_FIELD_ID] = zerof; 1336*66edf50cSStefano Zampini ctxs[P_FIELD_ID] = NULL; 1337*66edf50cSStefano Zampini funcs[NUM_FIELDS] = source; 1338*66edf50cSStefano Zampini ctxs[NUM_FIELDS] = ctx->source_ctx; 1339*66edf50cSStefano Zampini PetscCall(DMProjectFunction(dmAux, time, funcs, ctxs, INSERT_ALL_VALUES, a)); 1340811d88abSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 1341*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, zero)); 1342*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, NUM_FIELDS, average)); 1343*66edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dmAux, a, vals, NULL)); 1344*66edf50cSStefano Zampini PetscCall(VecShift(a, -vals[NUM_FIELDS] / ctx->domain_volume)); 1345*66edf50cSStefano Zampini if (u) { 1346*66edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dmAux, "scatterAux", (PetscObject *)&sctAux)); 1347*66edf50cSStefano Zampini PetscCheck(sctAux, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing scatterAux"); 1348*66edf50cSStefano Zampini PetscCall(VecScatterBegin(sctAux, u, a, INSERT_VALUES, SCATTER_FORWARD)); 1349*66edf50cSStefano Zampini PetscCall(VecScatterEnd(sctAux, u, a, INSERT_VALUES, SCATTER_FORWARD)); 1350*66edf50cSStefano Zampini } 1351*66edf50cSStefano Zampini PetscCall(DMGlobalToLocal(dmAux, a, INSERT_VALUES, la)); 1352*66edf50cSStefano Zampini PetscCall(VecViewFromOptions(la, NULL, "-aux_view")); 1353*66edf50cSStefano 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)); 1392*66edf50cSStefano 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 1424*66edf50cSStefano Zampini /* callbacks for residual and Jacobian */ 1425*66edf50cSStefano 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; 1428*66edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)user; 1429204aa523SStefano Zampini 1430204aa523SStefano Zampini PetscFunctionBeginUser; 1431*66edf50cSStefano Zampini if (ctx->fix_c < 0) { 1432*66edf50cSStefano Zampini PetscReal vals[NUM_FIELDS]; 1433*66edf50cSStefano Zampini PetscDS ds; 1434*66edf50cSStefano Zampini 1435*66edf50cSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 1436*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, jacobian_fail)); 1437*66edf50cSStefano Zampini PetscCall(DMPlexSNESComputeObjectiveFEM(dm, locX, vals, NULL)); 1438*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 1439*66edf50cSStefano Zampini if (vals[C_FIELD_ID]) PetscCall(SNESSetFunctionDomainError(ctx->snes)); 1440*66edf50cSStefano Zampini } 1441*66edf50cSStefano 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)); 1450*66edf50cSStefano Zampini } else { 1451*66edf50cSStefano Zampini PetscCall(DMPlexTSComputeIFunctionFEM(dm, time, locX, locX_t, locF, user)); 1452*66edf50cSStefano Zampini } 1453204aa523SStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1454204aa523SStefano Zampini } 1455204aa523SStefano Zampini 1456*66edf50cSStefano 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; 1459*66edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)user; 1460204aa523SStefano Zampini 1461204aa523SStefano Zampini PetscFunctionBeginUser; 1462*66edf50cSStefano 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)); 1470*66edf50cSStefano Zampini } else { 1471*66edf50cSStefano Zampini PetscCall(DMPlexTSComputeIJacobianFEM(dm, time, locX, locX_t, X_tShift, Jac, JacP, user)); 1472*66edf50cSStefano 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]; 1482*66edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS]; 1483*66edf50cSStefano Zampini PetscInt fields[NUM_FIELDS] = {C_FIELD_ID, P_FIELD_ID}; 1484*66edf50cSStefano Zampini Vec dummy; 1485*66edf50cSStefano 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; 1494*66edf50cSStefano Zampini constants[SPLIT_ID] = ctx->split; 1495811d88abSStefano Zampini 1496811d88abSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 1497811d88abSStefano Zampini PetscCall(DMGetCoordinateDim(dm, &cdim)); 1498*66edf50cSStefano Zampini PetscCheck(dim == 2 || dim == 3, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Topological dimension must be 2 or 3"); 1499*66edf50cSStefano Zampini PetscCheck(dim == ctx->dim, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Topological dimension mismatch: expected %" PetscInt_FMT ", found %" PetscInt_FMT, dim, ctx->dim); 1500*66edf50cSStefano 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)); 1507*66edf50cSStefano 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)); 1510*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, C_FIELD_ID, JC_0_c0c0, NULL, NULL, ctx->D > 0 ? JC_1_c1c1 : NULL)); 1511*66edf50cSStefano 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)); 1514*66edf50cSStefano Zampini } 1515811d88abSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, P_FIELD_ID, NULL, NULL, NULL, JP_1_p1p1)); 1516*66edf50cSStefano Zampini } else { 1517*66edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, C_FIELD_ID, C_0_3d, C_1_3d)); 1518*66edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, P_FIELD_ID, P_0, P_1_3d)); 1519*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, C_FIELD_ID, JC_0_c0c0_3d, NULL, NULL, ctx->D > 0 ? JC_1_c1c1_3d : NULL)); 1520*66edf50cSStefano Zampini if (!ctx->split) { 1521*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, C_FIELD_ID, P_FIELD_ID, NULL, JC_0_c0p1_3d, NULL, NULL)); 1522*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, C_FIELD_ID, NULL, NULL, JP_1_p1c0_3d, NULL)); 1523*66edf50cSStefano Zampini } 1524*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, P_FIELD_ID, P_FIELD_ID, NULL, NULL, NULL, JP_1_p1p1_3d)); 1525*66edf50cSStefano Zampini } 1526811d88abSStefano Zampini /* Attach potential nullspace */ 1527811d88abSStefano Zampini PetscCall(DMSetNullSpaceConstructor(dm, P_FIELD_ID, CreatePotentialNullSpace)); 1528811d88abSStefano Zampini 1529*66edf50cSStefano Zampini /* Compute domain volume */ 1530*66edf50cSStefano Zampini PetscCall(DMGetGlobalVector(dm, &dummy)); 1531*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, volume)); 1532*66edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, dummy, vals, NULL)); 1533*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, P_FIELD_ID, zero)); 1534*66edf50cSStefano Zampini PetscCall(DMRestoreGlobalVector(dm, &dummy)); 1535*66edf50cSStefano Zampini ctx->domain_volume = PetscRealPart(vals[P_FIELD_ID]); 1536*66edf50cSStefano Zampini 1537*66edf50cSStefano Zampini /* Index sets for potential and conductivities */ 1538*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields, &is, NULL)); 1539*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "IS conductivity", (PetscObject)is)); 1540*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)is, "C")); 1541*66edf50cSStefano Zampini PetscCall(ISViewFromOptions(is, NULL, "-is_conductivity_view")); 1542*66edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 1543*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields + 1, &is, NULL)); 1544*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)is, "P")); 1545*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "IS potential", (PetscObject)is)); 1546*66edf50cSStefano Zampini PetscCall(ISViewFromOptions(is, NULL, "-is_potential_view")); 1547*66edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 1548*66edf50cSStefano Zampini 1549*66edf50cSStefano Zampini /* Create auxiliary DM */ 1550*66edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, PETSC_MIN_REAL, NULL, ctx)); 1551811d88abSStefano Zampini 1552811d88abSStefano Zampini /* Add callbacks */ 1553*66edf50cSStefano Zampini PetscCall(DMTSSetIFunctionLocal(dm, DMPlexTSComputeIFunctionFEM_Private, ctx)); 1554*66edf50cSStefano Zampini PetscCall(DMTSSetIJacobianLocal(dm, DMPlexTSComputeIJacobianFEM_Private, ctx)); 1555*66edf50cSStefano Zampini /* DMPlexTSComputeBoundary is not needed because we use natural boundary conditions */ 1556*66edf50cSStefano Zampini PetscCall(DMTSSetBoundaryLocal(dm, NULL, NULL)); 1557*66edf50cSStefano Zampini 1558*66edf50cSStefano Zampini /* handle nullspace in residual (move it to TSComputeIFunction_DMLocal?) */ 1559*66edf50cSStefano Zampini { 1560*66edf50cSStefano Zampini MatNullSpace nullsp; 1561*66edf50cSStefano Zampini 1562*66edf50cSStefano Zampini PetscCall(CreatePotentialNullSpace(dm, P_FIELD_ID, P_FIELD_ID, &nullsp)); 1563*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)dm, "__dmtsnullspace", (PetscObject)nullsp)); 1564*66edf50cSStefano 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 { 1572*66edf50cSStefano 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 */ 1581*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(comm, dim, (dim * (dim + 1)) / 2, ctx->simplex, "c_", -1, &feC)); 1582811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feC, "conductivity")); 1583*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(comm, dim, 1, ctx->simplex, "p_", -1, &feP)); 1584811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feP, "potential")); 1585204aa523SStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feC)); 1586*66edf50cSStefano Zampini PetscCall(PetscFEViewFromOptions(feP, NULL, "-view_fe")); 1587*66edf50cSStefano 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 { 1606*66edf50cSStefano Zampini DM plex; 1607*66edf50cSStefano 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 } 1674*66edf50cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, "ref_")); 1675*66edf50cSStefano Zampini PetscCall(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 1676*66edf50cSStefano Zampini PetscCall(DMSetFromOptions(*dm)); 1677*66edf50cSStefano Zampini PetscCall(PetscObjectSetOptionsPrefix((PetscObject)*dm, NULL)); 1678*66edf50cSStefano Zampini 1679*66edf50cSStefano Zampini PetscCall(DMConvert(*dm, DMPLEX, &plex)); 1680*66edf50cSStefano Zampini PetscCall(DMPlexIsSimplex(plex, &ctx->simplex)); 1681*66edf50cSStefano Zampini PetscCallMPI(MPIU_Allreduce(MPI_IN_PLACE, &ctx->simplex, 1, MPIU_BOOL, MPI_LOR, comm)); 1682*66edf50cSStefano Zampini PetscCall(DMDestroy(&plex)); 1683*66edf50cSStefano 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 */ 1689*66edf50cSStefano 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)); 1702*66edf50cSStefano 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; 1715*66edf50cSStefano 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)); 1730*66edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&isp)); 1731*66edf50cSStefano Zampini PetscCheck(isp, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 1732204aa523SStefano Zampini if (valid) { 1733*66edf50cSStefano 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)); 1744*66edf50cSStefano Zampini } 1745*66edf50cSStefano Zampini for (PetscInt i = 0; i < nv; i++) PetscCall(ZeroMeanPotential(dm, vecs[i], ctx->domain_volume)); 1746811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1747811d88abSStefano Zampini } 1748*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(dm, 1, fields + 1, NULL, &dmp)); 1749811d88abSStefano Zampini PetscCall(DMSetMatType(dmp, MATAIJ)); 1750811d88abSStefano Zampini PetscCall(DMGetDS(dmp, &ds)); 1751*66edf50cSStefano Zampini if (ctx->dim == 2) { 1752*66edf50cSStefano 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)); 1754*66edf50cSStefano Zampini } else { 1755*66edf50cSStefano Zampini PetscCall(PetscDSSetResidual(ds, 0, P_0_aux, P_1_aux_3d)); 1756*66edf50cSStefano Zampini PetscCall(PetscDSSetJacobian(ds, 0, 0, NULL, NULL, NULL, JP_1_p1p1_aux_3d)); 1757*66edf50cSStefano 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 */ 1777*66edf50cSStefano Zampini PetscErrorCode (*funcs[NUM_FIELDS])(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar *, void *); 1778*66edf50cSStefano Zampini void *ctxs[NUM_FIELDS] = {NULL}; 1779*66edf50cSStefano Zampini PetscRandom r = NULL; 1780*66edf50cSStefano 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; 1792*66edf50cSStefano Zampini case 3: 1793*66edf50cSStefano Zampini funcs[C_FIELD_ID] = initial_conditions_C_random; 1794*66edf50cSStefano Zampini PetscCall(PetscRandomCreate(PetscObjectComm((PetscObject)ts), &r)); 1795*66edf50cSStefano Zampini PetscCall(PetscRandomSetOptionsPrefix(r, "ic_")); 1796*66edf50cSStefano Zampini PetscCall(PetscRandomSetFromOptions(r)); 1797*66edf50cSStefano Zampini ctxs[C_FIELD_ID] = r; 1798*66edf50cSStefano 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; 1803*66edf50cSStefano Zampini PetscCall(DMProjectFunction(dm, t, funcs, ctxs, INSERT_ALL_VALUES, u)); 1804*66edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, t, u, ctx)); 1805*66edf50cSStefano Zampini PetscCall(PetscRandomDestroy(&r)); 1806811d88abSStefano Zampini } 1807811d88abSStefano Zampini 1808*66edf50cSStefano Zampini /* pass conductivity information via auxiliary data */ 1809*66edf50cSStefano 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)); 1821*66edf50cSStefano 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 */ 1829*66edf50cSStefano 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)); 1840*66edf50cSStefano 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; 1924*66edf50cSStefano Zampini PetscInt fields[NUM_FIELDS] = {C_FIELD_ID, P_FIELD_ID}; 1925*66edf50cSStefano 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)); 1945*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(adm, 1, fields, &is, NULL)); 1946*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "IS conductivity", (PetscObject)is)); 1947*66edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 1948*66edf50cSStefano Zampini PetscCall(DMCreateSubDM(adm, 1, fields + 1, &is, NULL)); 1949*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "IS potential", (PetscObject)is)); 1950*66edf50cSStefano Zampini PetscCall(ISDestroy(&is)); 1951*66edf50cSStefano Zampini PetscCall(ProjectAuxDM(adm, time, NULL, ctx)); 1952*66edf50cSStefano Zampini { 1953*66edf50cSStefano Zampini MatNullSpace nullsp; 1954*66edf50cSStefano Zampini 1955*66edf50cSStefano Zampini PetscCall(CreatePotentialNullSpace(adm, P_FIELD_ID, P_FIELD_ID, &nullsp)); 1956*66edf50cSStefano Zampini PetscCall(PetscObjectCompose((PetscObject)adm, "__dmtsnullspace", (PetscObject)nullsp)); 1957*66edf50cSStefano Zampini PetscCall(MatNullSpaceDestroy(&nullsp)); 1958*66edf50cSStefano Zampini } 1959811d88abSStefano Zampini PetscCall(SetInitialConditionsAndTolerances(ts, nv, vecsout, PETSC_TRUE)); 1960*66edf50cSStefano Zampini PetscCall(DMDestroy(&ctx->view_dm)); 1961*66edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 1962*66edf50cSStefano Zampini PetscCall(VecScatterDestroy(&ctx->subsct[i])); 1963*66edf50cSStefano Zampini PetscCall(VecDestroy(&ctx->subvec[i])); 1964*66edf50cSStefano Zampini } 1965811d88abSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 1966811d88abSStefano Zampini } 1967811d88abSStefano Zampini 1968*66edf50cSStefano Zampini static PetscErrorCode ComputeDiagnostic(Vec u, AppCtx *ctx, Vec *out) 1969811d88abSStefano Zampini { 1970*66edf50cSStefano Zampini DM dm; 1971*66edf50cSStefano Zampini PetscInt dim; 1972*66edf50cSStefano Zampini PetscFE feFluxC, feNormC, feEigsC; 1973*66edf50cSStefano Zampini 1974*66edf50cSStefano 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}; 1975*66edf50cSStefano Zampini 1976811d88abSStefano Zampini PetscFunctionBeginUser; 1977*66edf50cSStefano Zampini if (!ctx->view_dm) { 1978*66edf50cSStefano Zampini PetscFE feP; 1979*66edf50cSStefano Zampini PetscInt nf = PetscMax(PetscMin(ctx->diagnostic_num, 3), 1); 1980*66edf50cSStefano Zampini 1981*66edf50cSStefano Zampini PetscCall(VecGetDM(u, &dm)); 1982*66edf50cSStefano Zampini PetscCall(DMGetDimension(dm, &dim)); 1983*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, 1, ctx->simplex, "normc_", -1, &feNormC)); 1984*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dim, ctx->simplex, "eigsc_", -1, &feEigsC)); 1985*66edf50cSStefano Zampini PetscCall(PetscFECreateDefault(PetscObjectComm((PetscObject)dm), dim, dim, ctx->simplex, "flux_", -1, &feFluxC)); 1986*66edf50cSStefano Zampini PetscCall(DMGetField(dm, P_FIELD_ID, NULL, (PetscObject *)&feP)); 1987*66edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feNormC)); 1988*66edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feEigsC)); 1989*66edf50cSStefano Zampini PetscCall(PetscFECopyQuadrature(feP, feFluxC)); 1990*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feNormC, "normC")); 1991*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feEigsC, "eigsC")); 1992*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)feFluxC, "flux")); 1993*66edf50cSStefano Zampini 1994*66edf50cSStefano Zampini PetscCall(DMClone(dm, &ctx->view_dm)); 1995*66edf50cSStefano Zampini PetscCall(DMSetNumFields(ctx->view_dm, nf)); 1996*66edf50cSStefano Zampini PetscCall(DMSetField(ctx->view_dm, 0, NULL, (PetscObject)feNormC)); 1997*66edf50cSStefano Zampini if (nf > 1) PetscCall(DMSetField(ctx->view_dm, 1, NULL, (PetscObject)feEigsC)); 1998*66edf50cSStefano Zampini if (nf > 2) PetscCall(DMSetField(ctx->view_dm, 2, NULL, (PetscObject)feFluxC)); 1999*66edf50cSStefano Zampini PetscCall(DMCreateDS(ctx->view_dm)); 2000*66edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feFluxC)); 2001*66edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feNormC)); 2002*66edf50cSStefano Zampini PetscCall(PetscFEDestroy(&feEigsC)); 2003*66edf50cSStefano Zampini } 2004*66edf50cSStefano Zampini PetscCall(DMCreateGlobalVector(ctx->view_dm, out)); 2005*66edf50cSStefano Zampini PetscCall(DMProjectField(ctx->view_dm, 0.0, u, funcs, INSERT_VALUES, *out)); 2006*66edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2007*66edf50cSStefano Zampini } 2008*66edf50cSStefano Zampini 2009*66edf50cSStefano Zampini static PetscErrorCode MakeScatterAndVec(Vec X, IS is, Vec *Y, VecScatter *sct) 2010*66edf50cSStefano Zampini { 2011*66edf50cSStefano Zampini PetscInt n; 2012*66edf50cSStefano Zampini 2013*66edf50cSStefano Zampini PetscFunctionBeginUser; 2014*66edf50cSStefano Zampini PetscCall(ISGetLocalSize(is, &n)); 2015*66edf50cSStefano Zampini PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)X), n, PETSC_DECIDE, Y)); 2016*66edf50cSStefano Zampini PetscCall(VecScatterCreate(X, is, *Y, NULL, sct)); 2017*66edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2018*66edf50cSStefano Zampini } 2019*66edf50cSStefano Zampini 2020*66edf50cSStefano Zampini static PetscErrorCode FunctionDomainError(TS ts, PetscReal time, Vec X, PetscBool *accept) 2021*66edf50cSStefano Zampini { 2022*66edf50cSStefano Zampini AppCtx *ctx; 2023*66edf50cSStefano Zampini PetscScalar vals[NUM_FIELDS]; 2024*66edf50cSStefano Zampini DM dm; 2025*66edf50cSStefano Zampini PetscDS ds; 2026*66edf50cSStefano Zampini 2027*66edf50cSStefano Zampini PetscFunctionBeginUser; 2028*66edf50cSStefano Zampini *accept = PETSC_TRUE; 2029*66edf50cSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 2030*66edf50cSStefano Zampini if (ctx->function_domain_error_tol < 0) PetscFunctionReturn(PETSC_SUCCESS); 2031*66edf50cSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 2032*66edf50cSStefano Zampini PetscCall(DMGetDS(dm, &ds)); 2033*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, ellipticity_fail)); 2034*66edf50cSStefano Zampini PetscCall(DMPlexComputeIntegralFEM(dm, X, vals, NULL)); 2035*66edf50cSStefano Zampini PetscCall(PetscDSSetObjective(ds, C_FIELD_ID, energy)); 2036*66edf50cSStefano Zampini if (PetscAbsScalar(vals[C_FIELD_ID]) > ctx->function_domain_error_tol) *accept = PETSC_FALSE; 2037*66edf50cSStefano 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; 2048*66edf50cSStefano 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)); 2064*66edf50cSStefano 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]))); 2067*66edf50cSStefano Zampini 2068*66edf50cSStefano Zampini /* monitor diagnostic */ 2069*66edf50cSStefano 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))); 2070*66edf50cSStefano 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))); 2071*66edf50cSStefano 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]) { 2072*66edf50cSStefano Zampini if (ctx->view_hdf5_ctx) need_hdf5 = PETSC_TRUE; 2073*66edf50cSStefano Zampini if (ctx->view_vtk_ctx) need_vtk = PETSC_TRUE; 2074*66edf50cSStefano Zampini ctx->view_times_k++; 2075*66edf50cSStefano Zampini } 2076*66edf50cSStefano Zampini if (need_vtk || need_hdf5) { 2077*66edf50cSStefano Zampini Vec diagnostic; 2078*66edf50cSStefano Zampini PetscBool dump_dm = (PetscBool)(!!ctx->view_dm); 2079*66edf50cSStefano Zampini 2080*66edf50cSStefano Zampini PetscCall(ComputeDiagnostic(u, ctx, &diagnostic)); 2081*66edf50cSStefano Zampini if (need_vtk) { 2082*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)diagnostic, "")); 2083*66edf50cSStefano Zampini PetscCall(TSMonitorSolutionVTK(ts, stepnum, time, diagnostic, ctx->view_vtk_ctx)); 2084*66edf50cSStefano Zampini } 2085*66edf50cSStefano Zampini if (need_hdf5) { 2086*66edf50cSStefano Zampini DM vdm; 2087*66edf50cSStefano Zampini PetscInt seqnum; 2088*66edf50cSStefano Zampini 2089*66edf50cSStefano Zampini PetscCall(VecGetDM(diagnostic, &vdm)); 2090*66edf50cSStefano Zampini if (!dump_dm) { 2091*66edf50cSStefano Zampini PetscCall(PetscViewerPushFormat(ctx->view_hdf5_ctx->viewer, ctx->view_hdf5_ctx->format)); 2092*66edf50cSStefano Zampini PetscCall(DMView(vdm, ctx->view_hdf5_ctx->viewer)); 2093*66edf50cSStefano Zampini PetscCall(PetscViewerPopFormat(ctx->view_hdf5_ctx->viewer)); 2094*66edf50cSStefano Zampini } 2095*66edf50cSStefano Zampini PetscCall(DMGetOutputSequenceNumber(vdm, &seqnum, NULL)); 2096*66edf50cSStefano Zampini PetscCall(DMSetOutputSequenceNumber(vdm, seqnum + 1, time)); 2097*66edf50cSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)diagnostic, "diagnostic")); 2098*66edf50cSStefano Zampini PetscCall(PetscViewerPushFormat(ctx->view_hdf5_ctx->viewer, ctx->view_hdf5_ctx->format)); 2099*66edf50cSStefano Zampini PetscCall(VecView(diagnostic, ctx->view_hdf5_ctx->viewer)); 2100*66edf50cSStefano Zampini if (ctx->diagnostic_num > 3 || ctx->diagnostic_num < 0) { 2101*66edf50cSStefano Zampini PetscCall(DMSetOutputSequenceNumber(dm, seqnum + 1, time)); 2102*66edf50cSStefano Zampini PetscCall(VecView(u, ctx->view_hdf5_ctx->viewer)); 2103*66edf50cSStefano Zampini } 2104*66edf50cSStefano Zampini PetscCall(PetscViewerPopFormat(ctx->view_hdf5_ctx->viewer)); 2105*66edf50cSStefano Zampini } 2106*66edf50cSStefano Zampini PetscCall(VecDestroy(&diagnostic)); 2107*66edf50cSStefano 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 2127*66edf50cSStefano Zampini /* Resample source if time dependent */ 2128*66edf50cSStefano Zampini static PetscErrorCode PreStage(TS ts, PetscReal stagetime) 2129*66edf50cSStefano Zampini { 2130*66edf50cSStefano Zampini AppCtx *ctx; 2131*66edf50cSStefano Zampini PetscBool resample, ismatis; 2132*66edf50cSStefano Zampini Mat A, P; 2133*66edf50cSStefano Zampini 2134*66edf50cSStefano Zampini PetscFunctionBeginUser; 2135*66edf50cSStefano Zampini PetscCall(TSGetApplicationContext(ts, &ctx)); 2136*66edf50cSStefano Zampini /* in case we need to call SNESSetFunctionDomainError */ 2137*66edf50cSStefano Zampini PetscCall(TSGetSNES(ts, &ctx->snes)); 2138*66edf50cSStefano Zampini 2139*66edf50cSStefano Zampini resample = ctx->split ? PETSC_TRUE : PETSC_FALSE; 2140*66edf50cSStefano Zampini for (PetscInt i = 0; i < ctx->source_ctx->n; i++) { 2141*66edf50cSStefano Zampini if (ctx->source_ctx->k[i] != 0.0) { 2142*66edf50cSStefano Zampini resample = PETSC_TRUE; 2143*66edf50cSStefano Zampini break; 2144*66edf50cSStefano Zampini } 2145*66edf50cSStefano Zampini } 2146*66edf50cSStefano Zampini if (resample) { 2147*66edf50cSStefano Zampini DM dm; 2148*66edf50cSStefano Zampini Vec u = NULL; 2149*66edf50cSStefano Zampini 2150*66edf50cSStefano Zampini PetscCall(TSGetDM(ts, &dm)); 2151*66edf50cSStefano Zampini /* In case of a multistage method, we always use the frozen values at the previous time-step */ 2152*66edf50cSStefano Zampini if (ctx->split) PetscCall(TSGetSolution(ts, &u)); 2153*66edf50cSStefano Zampini PetscCall(ProjectAuxDM(dm, stagetime, u, ctx)); 2154*66edf50cSStefano Zampini } 2155*66edf50cSStefano Zampini 2156*66edf50cSStefano Zampini /* element matrices are sparse, ignore zero entries */ 2157*66edf50cSStefano Zampini PetscCall(TSGetIJacobian(ts, &A, &P, NULL, NULL)); 2158*66edf50cSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)A, MATIS, &ismatis)); 2159*66edf50cSStefano Zampini if (!ismatis) PetscCall(MatSetOption(A, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 2160*66edf50cSStefano Zampini PetscCall(PetscObjectTypeCompare((PetscObject)P, MATIS, &ismatis)); 2161*66edf50cSStefano Zampini if (!ismatis) PetscCall(MatSetOption(P, MAT_IGNORE_ZERO_ENTRIES, PETSC_TRUE)); 2162*66edf50cSStefano Zampini 2163*66edf50cSStefano Zampini /* Set symmetric flag */ 2164*66edf50cSStefano Zampini PetscCall(MatSetOption(A, MAT_SYMMETRIC, PETSC_TRUE)); 2165*66edf50cSStefano Zampini PetscCall(MatSetOption(P, MAT_SYMMETRIC, PETSC_TRUE)); 2166*66edf50cSStefano Zampini PetscCall(MatSetOption(A, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 2167*66edf50cSStefano Zampini PetscCall(MatSetOption(P, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); 2168*66edf50cSStefano Zampini PetscFunctionReturn(PETSC_SUCCESS); 2169*66edf50cSStefano Zampini } 2170*66edf50cSStefano 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)); 2183*66edf50cSStefano Zampini 2184*66edf50cSStefano Zampini PetscCall(ZeroMeanPotential(dm, u, ctx->domain_volume)); 2185*66edf50cSStefano 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 2207*66edf50cSStefano Zampini PetscErrorCode MonitorNorms(SNES snes, PetscInt its, PetscReal f, void *vctx) 2208811d88abSStefano Zampini { 2209*66edf50cSStefano Zampini AppCtx *ctx = (AppCtx *)vctx; 2210*66edf50cSStefano Zampini Vec F; 2211*66edf50cSStefano Zampini DM dm; 2212*66edf50cSStefano Zampini PetscReal subnorm[NUM_FIELDS]; 2213811d88abSStefano Zampini 2214811d88abSStefano Zampini PetscFunctionBeginUser; 2215*66edf50cSStefano Zampini PetscCall(SNESGetDM(snes, &dm)); 2216*66edf50cSStefano Zampini PetscCall(SNESGetFunction(snes, &F, NULL, NULL)); 2217*66edf50cSStefano Zampini if (!ctx->subsct[C_FIELD_ID]) { 2218*66edf50cSStefano Zampini IS is; 2219811d88abSStefano Zampini 2220*66edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS conductivity", (PetscObject *)&is)); 2221*66edf50cSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing conductivity IS"); 2222*66edf50cSStefano Zampini PetscCall(MakeScatterAndVec(F, is, &ctx->subvec[C_FIELD_ID], &ctx->subsct[C_FIELD_ID])); 2223*66edf50cSStefano Zampini } 2224*66edf50cSStefano Zampini if (!ctx->subsct[P_FIELD_ID]) { 2225*66edf50cSStefano Zampini IS is; 2226*66edf50cSStefano Zampini 2227*66edf50cSStefano Zampini PetscCall(PetscObjectQuery((PetscObject)dm, "IS potential", (PetscObject *)&is)); 2228*66edf50cSStefano Zampini PetscCheck(is, PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Missing potential IS"); 2229*66edf50cSStefano Zampini PetscCall(MakeScatterAndVec(F, is, &ctx->subvec[P_FIELD_ID], &ctx->subsct[P_FIELD_ID])); 2230*66edf50cSStefano Zampini } 2231*66edf50cSStefano Zampini PetscCall(VecScatterBegin(ctx->subsct[C_FIELD_ID], F, ctx->subvec[C_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 2232*66edf50cSStefano Zampini PetscCall(VecScatterEnd(ctx->subsct[C_FIELD_ID], F, ctx->subvec[C_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 2233*66edf50cSStefano Zampini PetscCall(VecScatterBegin(ctx->subsct[P_FIELD_ID], F, ctx->subvec[P_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 2234*66edf50cSStefano Zampini PetscCall(VecScatterEnd(ctx->subsct[P_FIELD_ID], F, ctx->subvec[P_FIELD_ID], INSERT_VALUES, SCATTER_FORWARD)); 2235*66edf50cSStefano Zampini PetscCall(VecNorm(ctx->subvec[C_FIELD_ID], NORM_2, &subnorm[C_FIELD_ID])); 2236*66edf50cSStefano Zampini PetscCall(VecNorm(ctx->subvec[P_FIELD_ID], NORM_2, &subnorm[P_FIELD_ID])); 2237*66edf50cSStefano 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")); 2263*66edf50cSStefano 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)); 2271*66edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " snum : %" PetscInt_FMT "\n", ctx->source_ctx->n)); 2272*66edf50cSStefano Zampini for (PetscInt i = 0; i < ctx->source_ctx->n; i++) { 2273*66edf50cSStefano Zampini const PetscReal *x0 = ctx->source_ctx->x0 + ctx->dim * i; 2274*66edf50cSStefano Zampini const PetscReal w = ctx->source_ctx->w[i]; 2275*66edf50cSStefano Zampini const PetscReal k = ctx->source_ctx->k[i]; 2276*66edf50cSStefano Zampini const PetscReal p = ctx->source_ctx->p[i]; 2277*66edf50cSStefano Zampini const PetscReal r = ctx->source_ctx->r[i]; 2278*66edf50cSStefano Zampini 2279*66edf50cSStefano Zampini if (ctx->dim == 2) { 2280*66edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " x0 : (%g,%g)\n", (double)x0[0], (double)x0[1])); 2281*66edf50cSStefano Zampini } else { 2282*66edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " x0 : (%g,%g,%g)\n", (double)x0[0], (double)x0[1], (double)x0[2])); 2283*66edf50cSStefano Zampini } 2284*66edf50cSStefano Zampini PetscCall(PetscPrintf(comm, " scals: (%g,%g,%g,%g)\n", (double)w, (double)k, (double)p, (double)r)); 2285*66edf50cSStefano 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)); 2317*66edf50cSStefano Zampini PetscCall(TSSetPreStage(ts, PreStage)); 2318811d88abSStefano Zampini PetscCall(TSSetPostStage(ts, PostStage)); 2319811d88abSStefano Zampini PetscCall(TSSetMaxSNESFailures(ts, -1)); 2320*66edf50cSStefano Zampini PetscCall(TSSetFunctionDomainError(ts, FunctionDomainError)); 2321811d88abSStefano Zampini PetscCall(TSSetFromOptions(ts)); 2322*66edf50cSStefano Zampini if (ctx->monitor_norms) { 2323*66edf50cSStefano Zampini SNES snes; 2324*66edf50cSStefano Zampini 2325*66edf50cSStefano Zampini PetscCall(TSGetSNES(ts, &snes)); 2326*66edf50cSStefano Zampini PetscCall(SNESMonitorSet(snes, MonitorNorms, ctx, NULL)); 2327*66edf50cSStefano Zampini } 2328811d88abSStefano Zampini 2329811d88abSStefano Zampini PetscCall(DMCreateGlobalVector(dm, &u)); 2330811d88abSStefano Zampini PetscCall(PetscObjectSetName((PetscObject)u, "solution_")); 2331811d88abSStefano Zampini PetscCall(DMHasNamedGlobalVector(dm, "solution_", &flg)); 2332*66edf50cSStefano 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 } 2339*66edf50cSStefano 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()); 2348*66edf50cSStefano Zampini if (ctx->view_vtk_ctx) PetscCall(TSMonitorSolutionVTKDestroy(&ctx->view_vtk_ctx)); 2349*66edf50cSStefano Zampini if (ctx->view_hdf5_ctx) PetscCall(PetscViewerAndFormatDestroy(&ctx->view_hdf5_ctx)); 2350*66edf50cSStefano Zampini PetscCall(DMDestroy(&ctx->view_dm)); 2351*66edf50cSStefano Zampini for (PetscInt i = 0; i < NUM_FIELDS; i++) { 2352*66edf50cSStefano Zampini PetscCall(VecScatterDestroy(&ctx->subsct[i])); 2353*66edf50cSStefano Zampini PetscCall(VecDestroy(&ctx->subvec[i])); 2354*66edf50cSStefano 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 } 2406*66edf50cSStefano Zampini PetscCall(PetscFree5(ctx.source_ctx->x0, ctx.source_ctx->w, ctx.source_ctx->k, ctx.source_ctx->p, ctx.source_ctx->r)); 2407*66edf50cSStefano 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: 2415*66edf50cSStefano 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}} 2420*66edf50cSStefano Zampini args: -dm_refine 1 -lump {{0 1}} -exclude_potential_lte 2421*66edf50cSStefano Zampini 2422*66edf50cSStefano Zampini test: 2423*66edf50cSStefano Zampini suffix: 0_split 2424*66edf50cSStefano Zampini nsize: {{1 2}} 2425*66edf50cSStefano Zampini args: -dm_refine 1 -split 2426*66edf50cSStefano Zampini 2427*66edf50cSStefano Zampini test: 2428*66edf50cSStefano Zampini suffix: 0_3d 2429*66edf50cSStefano Zampini nsize: {{1 2}} 2430*66edf50cSStefano 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 2498*66edf50cSStefano Zampini test: 2499*66edf50cSStefano Zampini suffix: annulus 2500*66edf50cSStefano Zampini requires: exodusii 2501*66edf50cSStefano 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 2502*66edf50cSStefano Zampini 2503*66edf50cSStefano Zampini test: 2504*66edf50cSStefano Zampini suffix: hdf5_diagnostic 2505*66edf50cSStefano Zampini requires: hdf5 exodusii 2506*66edf50cSStefano 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 2507*66edf50cSStefano Zampini 2508*66edf50cSStefano Zampini test: 2509*66edf50cSStefano Zampini suffix: vtk_diagnostic 2510*66edf50cSStefano Zampini requires: exodusii 2511*66edf50cSStefano 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 2512*66edf50cSStefano Zampini 2513*66edf50cSStefano Zampini test: 2514*66edf50cSStefano Zampini suffix: full_cdisc 2515*66edf50cSStefano 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 2516*66edf50cSStefano Zampini 2517*66edf50cSStefano Zampini test: 2518*66edf50cSStefano Zampini suffix: full_cdisc_split 2519*66edf50cSStefano 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 2520*66edf50cSStefano Zampini 2521*66edf50cSStefano Zampini test: 2522*66edf50cSStefano Zampini suffix: full_cdisc_minres 2523*66edf50cSStefano 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 2524*66edf50cSStefano Zampini 2525811d88abSStefano Zampini TEST*/ 2526