xref: /petsc/src/ts/tests/ex15.c (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
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