1*c4762a1bSJed Brown static char help[] ="Test conservation properties for 2-variable system\n\n"; 2*c4762a1bSJed Brown 3*c4762a1bSJed Brown /*F 4*c4762a1bSJed Brown We consider a linear reaction system with two concentrations 5*c4762a1bSJed Brown 6*c4762a1bSJed Brown \begin{align} 7*c4762a1bSJed Brown \frac{\partial c_0}{\partial t} &= -c_0 \\ 8*c4762a1bSJed Brown \frac{\partial c_1}{\partial t} &= c_0, 9*c4762a1bSJed Brown \end{align} 10*c4762a1bSJed Brown 11*c4762a1bSJed Brown wherethe sum $c_0 + c_1$ is conserved, as can be seen by adding the two equations. 12*c4762a1bSJed Brown 13*c4762a1bSJed Brown We now consider a different set of variables, defined implicitly by $c(u) = e^u$. This type of transformation is 14*c4762a1bSJed Brown sometimes used to ensure positivity, and related transformations are sometimes used to develop a well-conditioned 15*c4762a1bSJed Brown formulation in limits such as zero Mach number. In this instance, the relation is explicitly invertible, but that is 16*c4762a1bSJed Brown not always the case. We can rewrite the differential equation in terms of non-conservative variables u, 17*c4762a1bSJed Brown 18*c4762a1bSJed Brown \begin{align} 19*c4762a1bSJed Brown \frac{\partial c_0}{\partial u_0} \frac{\partial u_0}{\partial t} &= -c_0(u_0) \\ 20*c4762a1bSJed Brown \frac{\partial c_1}{\partial u_1} \frac{\partial u_1}{\partial t} &= c_0(u_0). 21*c4762a1bSJed Brown \end{align} 22*c4762a1bSJed Brown 23*c4762a1bSJed Brown We'll consider this three ways, each using an IFunction 24*c4762a1bSJed Brown 25*c4762a1bSJed Brown 1. CONSERVATIVE: standard integration in conservative variables: F(C, Cdot) = 0 26*c4762a1bSJed Brown 2. NONCONSERVATIVE: chain rule formulation entirely in primitive variables: F(U, Udot) = 0 27*c4762a1bSJed Brown 3. TRANSIENTVAR: Provide function C(U) and solve F(U, Cdot) = 0, where the time integrators handles the transformation 28*c4762a1bSJed Brown 29*c4762a1bSJed Brown We will see that 1 and 3 are conservative (up to machine precision/solver tolerance, independent of temporal 30*c4762a1bSJed Brown discretization error) while 2 is not conservative (i.e., scales with temporal discretization error). 31*c4762a1bSJed Brown 32*c4762a1bSJed Brown F*/ 33*c4762a1bSJed Brown 34*c4762a1bSJed Brown #include <petscts.h> 35*c4762a1bSJed Brown 36*c4762a1bSJed Brown typedef enum {VAR_CONSERVATIVE, VAR_NONCONSERVATIVE, VAR_TRANSIENTVAR} VarMode; 37*c4762a1bSJed Brown static const char *const VarModes[] = {"CONSERVATIVE", "NONCONSERVATIVE", "TRANSIENTVAR", "VarMode", "VAR_", NULL}; 38*c4762a1bSJed Brown 39*c4762a1bSJed Brown static PetscErrorCode IFunction_Conservative(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx) 40*c4762a1bSJed Brown { 41*c4762a1bSJed Brown const PetscScalar *u,*udot; 42*c4762a1bSJed Brown PetscScalar *f; 43*c4762a1bSJed Brown PetscErrorCode ierr; 44*c4762a1bSJed Brown 45*c4762a1bSJed Brown PetscFunctionBegin; 46*c4762a1bSJed Brown ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr); 47*c4762a1bSJed Brown ierr = VecGetArrayRead(Udot,&udot);CHKERRQ(ierr); 48*c4762a1bSJed Brown ierr = VecGetArray(F,&f);CHKERRQ(ierr); 49*c4762a1bSJed Brown 50*c4762a1bSJed Brown f[0] = udot[0] + u[0]; 51*c4762a1bSJed Brown f[1] = udot[1] - u[0]; 52*c4762a1bSJed Brown 53*c4762a1bSJed Brown ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr); 54*c4762a1bSJed Brown ierr = VecRestoreArrayRead(Udot,&udot);CHKERRQ(ierr); 55*c4762a1bSJed Brown ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 56*c4762a1bSJed Brown PetscFunctionReturn(0); 57*c4762a1bSJed Brown } 58*c4762a1bSJed Brown 59*c4762a1bSJed Brown static PetscErrorCode IFunction_Nonconservative(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx) 60*c4762a1bSJed Brown { 61*c4762a1bSJed Brown const PetscScalar *u,*udot; 62*c4762a1bSJed Brown PetscScalar *f; 63*c4762a1bSJed Brown PetscErrorCode ierr; 64*c4762a1bSJed Brown 65*c4762a1bSJed Brown PetscFunctionBegin; 66*c4762a1bSJed Brown ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr); 67*c4762a1bSJed Brown ierr = VecGetArrayRead(Udot,&udot);CHKERRQ(ierr); 68*c4762a1bSJed Brown ierr = VecGetArray(F,&f);CHKERRQ(ierr); 69*c4762a1bSJed Brown 70*c4762a1bSJed Brown f[0] = PetscExpScalar(u[0])*udot[0] + PetscExpScalar(u[0]); 71*c4762a1bSJed Brown f[1] = PetscExpScalar(u[1])*udot[1] - PetscExpScalar(u[0]); 72*c4762a1bSJed Brown 73*c4762a1bSJed Brown ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr); 74*c4762a1bSJed Brown ierr = VecRestoreArrayRead(Udot,&udot);CHKERRQ(ierr); 75*c4762a1bSJed Brown ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 76*c4762a1bSJed Brown PetscFunctionReturn(0); 77*c4762a1bSJed Brown } 78*c4762a1bSJed Brown 79*c4762a1bSJed Brown static PetscErrorCode IFunction_TransientVar(TS ts,PetscReal t,Vec U,Vec Cdot,Vec F,void *ctx) 80*c4762a1bSJed Brown { 81*c4762a1bSJed Brown const PetscScalar *u,*cdot; 82*c4762a1bSJed Brown PetscScalar *f; 83*c4762a1bSJed Brown PetscErrorCode ierr; 84*c4762a1bSJed Brown 85*c4762a1bSJed Brown PetscFunctionBegin; 86*c4762a1bSJed Brown ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr); 87*c4762a1bSJed Brown ierr = VecGetArrayRead(Cdot,&cdot);CHKERRQ(ierr); 88*c4762a1bSJed Brown ierr = VecGetArray(F,&f);CHKERRQ(ierr); 89*c4762a1bSJed Brown 90*c4762a1bSJed Brown f[0] = cdot[0] + PetscExpScalar(u[0]); 91*c4762a1bSJed Brown f[1] = cdot[1] - PetscExpScalar(u[0]); 92*c4762a1bSJed Brown 93*c4762a1bSJed Brown ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr); 94*c4762a1bSJed Brown ierr = VecRestoreArrayRead(Cdot,&cdot);CHKERRQ(ierr); 95*c4762a1bSJed Brown ierr = VecRestoreArray(F,&f);CHKERRQ(ierr); 96*c4762a1bSJed Brown PetscFunctionReturn(0); 97*c4762a1bSJed Brown } 98*c4762a1bSJed Brown 99*c4762a1bSJed Brown static PetscErrorCode TransientVar(TS ts,Vec U,Vec C,void *ctx) 100*c4762a1bSJed Brown { 101*c4762a1bSJed Brown PetscErrorCode ierr; 102*c4762a1bSJed Brown 103*c4762a1bSJed Brown PetscFunctionBegin; 104*c4762a1bSJed Brown ierr = VecCopy(U,C);CHKERRQ(ierr); 105*c4762a1bSJed Brown ierr = VecExp(C);CHKERRQ(ierr); 106*c4762a1bSJed Brown PetscFunctionReturn(0); 107*c4762a1bSJed Brown } 108*c4762a1bSJed Brown 109*c4762a1bSJed Brown int main(int argc, char *argv[]) 110*c4762a1bSJed Brown { 111*c4762a1bSJed Brown TS ts; 112*c4762a1bSJed Brown DM dm; 113*c4762a1bSJed Brown Vec U; 114*c4762a1bSJed Brown VarMode var = VAR_CONSERVATIVE; 115*c4762a1bSJed Brown PetscScalar sum; 116*c4762a1bSJed Brown PetscErrorCode ierr; 117*c4762a1bSJed Brown 118*c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr; 119*c4762a1bSJed Brown ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"TS conservation example","");CHKERRQ(ierr); 120*c4762a1bSJed Brown ierr = PetscOptionsEnum("-var","Variable formulation",NULL,VarModes,(PetscEnum)var,(PetscEnum*)&var,NULL);CHKERRQ(ierr); 121*c4762a1bSJed Brown ierr = PetscOptionsEnd();CHKERRQ(ierr); 122*c4762a1bSJed Brown 123*c4762a1bSJed Brown ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr); 124*c4762a1bSJed Brown ierr = TSSetType(ts,TSBDF);CHKERRQ(ierr); 125*c4762a1bSJed Brown ierr = TSGetDM(ts,&dm);CHKERRQ(ierr); 126*c4762a1bSJed Brown ierr = VecCreateSeq(PETSC_COMM_SELF,2,&U);CHKERRQ(ierr); 127*c4762a1bSJed Brown ierr = VecSetValue(U,0,2.,INSERT_VALUES);CHKERRQ(ierr); 128*c4762a1bSJed Brown ierr = VecSetValue(U,1,1.,INSERT_VALUES);CHKERRQ(ierr); 129*c4762a1bSJed Brown switch (var) { 130*c4762a1bSJed Brown case VAR_CONSERVATIVE: 131*c4762a1bSJed Brown ierr = DMTSSetIFunction(dm,IFunction_Conservative,NULL);CHKERRQ(ierr); 132*c4762a1bSJed Brown break; 133*c4762a1bSJed Brown case VAR_NONCONSERVATIVE: 134*c4762a1bSJed Brown ierr = VecLog(U);CHKERRQ(ierr); 135*c4762a1bSJed Brown ierr = DMTSSetIFunction(dm,IFunction_Nonconservative,NULL);CHKERRQ(ierr); 136*c4762a1bSJed Brown break; 137*c4762a1bSJed Brown case VAR_TRANSIENTVAR: 138*c4762a1bSJed Brown ierr = VecLog(U);CHKERRQ(ierr); 139*c4762a1bSJed Brown ierr = DMTSSetIFunction(dm,IFunction_TransientVar,NULL);CHKERRQ(ierr); 140*c4762a1bSJed Brown ierr = DMTSSetTransientVariable(dm,TransientVar,NULL);CHKERRQ(ierr); 141*c4762a1bSJed Brown } 142*c4762a1bSJed Brown ierr = TSSetMaxTime(ts,1.);CHKERRQ(ierr); 143*c4762a1bSJed Brown ierr = TSSetFromOptions(ts);CHKERRQ(ierr); 144*c4762a1bSJed Brown 145*c4762a1bSJed Brown ierr = TSSolve(ts,U);CHKERRQ(ierr); 146*c4762a1bSJed Brown switch (var) { 147*c4762a1bSJed Brown case VAR_CONSERVATIVE: 148*c4762a1bSJed Brown break; 149*c4762a1bSJed Brown case VAR_NONCONSERVATIVE: 150*c4762a1bSJed Brown case VAR_TRANSIENTVAR: 151*c4762a1bSJed Brown ierr = VecExp(U);CHKERRQ(ierr); 152*c4762a1bSJed Brown break; 153*c4762a1bSJed Brown } 154*c4762a1bSJed Brown ierr = VecView(U,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 155*c4762a1bSJed Brown ierr = VecSum(U,&sum);CHKERRQ(ierr); 156*c4762a1bSJed Brown ierr = PetscPrintf(PETSC_COMM_WORLD,"Conservation error %g\n", PetscRealPart(sum - 3.));CHKERRQ(ierr); 157*c4762a1bSJed Brown 158*c4762a1bSJed Brown ierr = VecDestroy(&U);CHKERRQ(ierr); 159*c4762a1bSJed Brown ierr = TSDestroy(&ts);CHKERRQ(ierr); 160*c4762a1bSJed Brown ierr = PetscFinalize(); 161*c4762a1bSJed Brown return ierr; 162*c4762a1bSJed Brown } 163*c4762a1bSJed Brown 164*c4762a1bSJed Brown /*TEST 165*c4762a1bSJed Brown 166*c4762a1bSJed Brown test: 167*c4762a1bSJed Brown suffix: conservative 168*c4762a1bSJed Brown args: -snes_fd -var conservative 169*c4762a1bSJed Brown test: 170*c4762a1bSJed Brown suffix: nonconservative 171*c4762a1bSJed Brown args: -snes_fd -var nonconservative 172*c4762a1bSJed Brown test: 173*c4762a1bSJed Brown suffix: transientvar 174*c4762a1bSJed Brown args: -snes_fd -var transientvar 175*c4762a1bSJed Brown 176*c4762a1bSJed Brown TEST*/ 177