xref: /petsc/src/ts/tutorials/ex35.cxx (revision c4762a1b19cd2af06abeed90e8f9d34fb975dd94)
1*c4762a1bSJed Brown static const char help[] = "Time-dependent Brusselator reaction-diffusion PDE in 1d. Demonstrates IMEX methods and uses MOAB.\n";
2*c4762a1bSJed Brown /*
3*c4762a1bSJed Brown    u_t - alpha u_xx = A + u^2 v - (B+1) u
4*c4762a1bSJed Brown    v_t - alpha v_xx = B u - u^2 v
5*c4762a1bSJed Brown    0 < x < 1;
6*c4762a1bSJed Brown    A = 1, B = 3, alpha = 1/50
7*c4762a1bSJed Brown 
8*c4762a1bSJed Brown    Initial conditions:
9*c4762a1bSJed Brown    u(x,0) = 1 + sin(2 pi x)
10*c4762a1bSJed Brown    v(x,0) = 3
11*c4762a1bSJed Brown 
12*c4762a1bSJed Brown    Boundary conditions:
13*c4762a1bSJed Brown    u(0,t) = u(1,t) = 1
14*c4762a1bSJed Brown    v(0,t) = v(1,t) = 3
15*c4762a1bSJed Brown */
16*c4762a1bSJed Brown 
17*c4762a1bSJed Brown // PETSc includes:
18*c4762a1bSJed Brown #include <petscts.h>
19*c4762a1bSJed Brown #include <petscdmmoab.h>
20*c4762a1bSJed Brown 
21*c4762a1bSJed Brown typedef struct {
22*c4762a1bSJed Brown   PetscScalar u,v;
23*c4762a1bSJed Brown } Field;
24*c4762a1bSJed Brown 
25*c4762a1bSJed Brown struct pUserCtx {
26*c4762a1bSJed Brown   PetscReal A,B;        /* Reaction coefficients */
27*c4762a1bSJed Brown   PetscReal alpha;      /* Diffusion coefficient */
28*c4762a1bSJed Brown   Field leftbc;         /* Dirichlet boundary conditions at left boundary */
29*c4762a1bSJed Brown   Field rightbc;        /* Dirichlet boundary conditions at right boundary */
30*c4762a1bSJed Brown   PetscInt  n,npts;       /* Number of mesh points */
31*c4762a1bSJed Brown   PetscInt  ntsteps;    /* Number of time steps */
32*c4762a1bSJed Brown   PetscInt nvars;       /* Number of variables in the equation system */
33*c4762a1bSJed Brown   PetscBool io;
34*c4762a1bSJed Brown };
35*c4762a1bSJed Brown typedef pUserCtx* UserCtx;
36*c4762a1bSJed Brown 
37*c4762a1bSJed Brown PetscErrorCode Initialize_AppContext(UserCtx *puser)
38*c4762a1bSJed Brown {
39*c4762a1bSJed Brown   UserCtx           user;
40*c4762a1bSJed Brown   PetscErrorCode    ierr;
41*c4762a1bSJed Brown 
42*c4762a1bSJed Brown   PetscFunctionBegin;
43*c4762a1bSJed Brown   ierr = PetscNew(&user);CHKERRQ(ierr);
44*c4762a1bSJed Brown 
45*c4762a1bSJed Brown   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Advection-reaction options","ex35.cxx");
46*c4762a1bSJed Brown   {
47*c4762a1bSJed Brown     user->nvars  = 2;
48*c4762a1bSJed Brown     user->A      = 1;
49*c4762a1bSJed Brown     user->B      = 3;
50*c4762a1bSJed Brown     user->alpha  = 0.02;
51*c4762a1bSJed Brown     user->leftbc.u  = 1;
52*c4762a1bSJed Brown     user->rightbc.u = 1;
53*c4762a1bSJed Brown     user->leftbc.v  = 3;
54*c4762a1bSJed Brown     user->rightbc.v = 3;
55*c4762a1bSJed Brown     user->n      = 10;
56*c4762a1bSJed Brown     user->ntsteps = 10000;
57*c4762a1bSJed Brown     user->io = PETSC_FALSE;
58*c4762a1bSJed Brown     ierr = PetscOptionsReal("-A","Reaction rate","ex35.cxx",user->A,&user->A,NULL);CHKERRQ(ierr);
59*c4762a1bSJed Brown     ierr = PetscOptionsReal("-B","Reaction rate","ex35.cxx",user->B,&user->B,NULL);CHKERRQ(ierr);
60*c4762a1bSJed Brown     ierr = PetscOptionsReal("-alpha","Diffusion coefficient","ex35.cxx",user->alpha,&user->alpha,NULL);CHKERRQ(ierr);
61*c4762a1bSJed Brown     ierr = PetscOptionsScalar("-uleft","Dirichlet boundary condition","ex35.cxx",user->leftbc.u,&user->leftbc.u,NULL);CHKERRQ(ierr);
62*c4762a1bSJed Brown     ierr = PetscOptionsScalar("-uright","Dirichlet boundary condition","ex35.cxx",user->rightbc.u,&user->rightbc.u,NULL);CHKERRQ(ierr);
63*c4762a1bSJed Brown     ierr = PetscOptionsScalar("-vleft","Dirichlet boundary condition","ex35.cxx",user->leftbc.v,&user->leftbc.v,NULL);CHKERRQ(ierr);
64*c4762a1bSJed Brown     ierr = PetscOptionsScalar("-vright","Dirichlet boundary condition","ex35.cxx",user->rightbc.v,&user->rightbc.v,NULL);CHKERRQ(ierr);
65*c4762a1bSJed Brown     ierr = PetscOptionsInt("-n","Number of 1-D elements","ex35.cxx",user->n,&user->n,NULL);CHKERRQ(ierr);
66*c4762a1bSJed Brown     ierr = PetscOptionsInt("-ndt","Number of time steps","ex35.cxx",user->ntsteps,&user->ntsteps,NULL);CHKERRQ(ierr);
67*c4762a1bSJed Brown     ierr = PetscOptionsBool("-io","Write the mesh and solution output to a file.","ex35.cxx",user->io,&user->io,NULL);CHKERRQ(ierr);
68*c4762a1bSJed Brown     user->npts   = user->n+1;
69*c4762a1bSJed Brown   }
70*c4762a1bSJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
71*c4762a1bSJed Brown 
72*c4762a1bSJed Brown   *puser = user;
73*c4762a1bSJed Brown   PetscFunctionReturn(0);
74*c4762a1bSJed Brown }
75*c4762a1bSJed Brown 
76*c4762a1bSJed Brown PetscErrorCode Destroy_AppContext(UserCtx *user)
77*c4762a1bSJed Brown {
78*c4762a1bSJed Brown   PetscErrorCode ierr;
79*c4762a1bSJed Brown 
80*c4762a1bSJed Brown   PetscFunctionBegin;
81*c4762a1bSJed Brown   ierr = PetscFree(*user);CHKERRQ(ierr);
82*c4762a1bSJed Brown   PetscFunctionReturn(0);
83*c4762a1bSJed Brown }
84*c4762a1bSJed Brown 
85*c4762a1bSJed Brown static PetscErrorCode FormInitialSolution(TS,Vec,void*);
86*c4762a1bSJed Brown static PetscErrorCode FormRHSFunction(TS,PetscReal,Vec,Vec,void*);
87*c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS,PetscReal,Vec,Vec,Vec,void*);
88*c4762a1bSJed Brown static PetscErrorCode FormIJacobian(TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);
89*c4762a1bSJed Brown 
90*c4762a1bSJed Brown /****************
91*c4762a1bSJed Brown  *              *
92*c4762a1bSJed Brown  *     MAIN     *
93*c4762a1bSJed Brown  *              *
94*c4762a1bSJed Brown  ****************/
95*c4762a1bSJed Brown int main(int argc,char **argv)
96*c4762a1bSJed Brown {
97*c4762a1bSJed Brown   TS                ts;         /* nonlinear solver */
98*c4762a1bSJed Brown   Vec               X;          /* solution, residual vectors */
99*c4762a1bSJed Brown   Mat               J;          /* Jacobian matrix */
100*c4762a1bSJed Brown   PetscInt          steps,mx;
101*c4762a1bSJed Brown   PetscErrorCode    ierr;
102*c4762a1bSJed Brown   PetscReal         hx,dt,ftime;
103*c4762a1bSJed Brown   UserCtx           user;       /* user-defined work context */
104*c4762a1bSJed Brown   TSConvergedReason reason;
105*c4762a1bSJed Brown 
106*c4762a1bSJed Brown   DM                dm;
107*c4762a1bSJed Brown   const char        *fields[2] = {"U","V"};
108*c4762a1bSJed Brown 
109*c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,(char *)0,help);if (ierr) return ierr;
110*c4762a1bSJed Brown 
111*c4762a1bSJed Brown   /* Initialize the user context struct */
112*c4762a1bSJed Brown   ierr = Initialize_AppContext(&user);CHKERRQ(ierr);
113*c4762a1bSJed Brown 
114*c4762a1bSJed Brown   /* Fill in the user defined work context: */
115*c4762a1bSJed Brown   ierr = DMMoabCreateBoxMesh(PETSC_COMM_WORLD, 1, PETSC_FALSE, NULL, user->n, 1, &dm);CHKERRQ(ierr);
116*c4762a1bSJed Brown   ierr = DMMoabSetFieldNames(dm, user->nvars, fields);CHKERRQ(ierr);
117*c4762a1bSJed Brown   ierr = DMMoabSetBlockSize(dm, user->nvars);CHKERRQ(ierr);
118*c4762a1bSJed Brown   ierr = DMSetFromOptions(dm);CHKERRQ(ierr);
119*c4762a1bSJed Brown 
120*c4762a1bSJed Brown   /* SetUp the data structures for DMMOAB */
121*c4762a1bSJed Brown   ierr = DMSetUp(dm);CHKERRQ(ierr);
122*c4762a1bSJed Brown 
123*c4762a1bSJed Brown   /*  Create timestepping solver context */
124*c4762a1bSJed Brown   ierr = TSCreate(PETSC_COMM_WORLD,&ts);CHKERRQ(ierr);
125*c4762a1bSJed Brown   ierr = TSSetDM(ts, dm);CHKERRQ(ierr);
126*c4762a1bSJed Brown   ierr = TSSetType(ts,TSARKIMEX);CHKERRQ(ierr);
127*c4762a1bSJed Brown   ierr = TSSetEquationType(ts,TS_EQ_DAE_IMPLICIT_INDEX1);CHKERRQ(ierr);
128*c4762a1bSJed Brown   ierr = DMSetMatType(dm,MATBAIJ);CHKERRQ(ierr);
129*c4762a1bSJed Brown   ierr = DMCreateMatrix(dm,&J);CHKERRQ(ierr);
130*c4762a1bSJed Brown 
131*c4762a1bSJed Brown   ierr = TSSetRHSFunction(ts,NULL,FormRHSFunction,user);CHKERRQ(ierr);
132*c4762a1bSJed Brown   ierr = TSSetIFunction(ts,NULL,FormIFunction,user);CHKERRQ(ierr);
133*c4762a1bSJed Brown   ierr = TSSetIJacobian(ts,J,J,FormIJacobian,user);CHKERRQ(ierr);
134*c4762a1bSJed Brown 
135*c4762a1bSJed Brown   ftime = 10.0;
136*c4762a1bSJed Brown   ierr = TSSetMaxSteps(ts,user->ntsteps);CHKERRQ(ierr);
137*c4762a1bSJed Brown   ierr = TSSetMaxTime(ts,ftime);CHKERRQ(ierr);
138*c4762a1bSJed Brown   ierr = TSSetExactFinalTime(ts,TS_EXACTFINALTIME_STEPOVER);CHKERRQ(ierr);
139*c4762a1bSJed Brown 
140*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
141*c4762a1bSJed Brown      Create the solution vector and set the initial conditions
142*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
143*c4762a1bSJed Brown   ierr = DMCreateGlobalVector(dm, &X);CHKERRQ(ierr);
144*c4762a1bSJed Brown 
145*c4762a1bSJed Brown   ierr = FormInitialSolution(ts,X,user);CHKERRQ(ierr);
146*c4762a1bSJed Brown   ierr = TSSetSolution(ts,X);CHKERRQ(ierr);
147*c4762a1bSJed Brown   ierr = VecGetSize(X,&mx);CHKERRQ(ierr);
148*c4762a1bSJed Brown   hx = 1.0/(PetscReal)(mx/2-1);
149*c4762a1bSJed Brown   dt = 0.4 * PetscSqr(hx) / user->alpha; /* Diffusive stability limit */
150*c4762a1bSJed Brown   ierr = TSSetTimeStep(ts,dt);CHKERRQ(ierr);
151*c4762a1bSJed Brown 
152*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
153*c4762a1bSJed Brown      Set runtime options
154*c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
155*c4762a1bSJed Brown   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
156*c4762a1bSJed Brown 
157*c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
158*c4762a1bSJed Brown      Solve nonlinear system
159*c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
160*c4762a1bSJed Brown   ierr = TSSolve(ts,X);CHKERRQ(ierr);
161*c4762a1bSJed Brown   ierr = TSGetSolveTime(ts,&ftime);CHKERRQ(ierr);
162*c4762a1bSJed Brown   ierr = TSGetStepNumber(ts,&steps);CHKERRQ(ierr);
163*c4762a1bSJed Brown   ierr = TSGetConvergedReason(ts,&reason);CHKERRQ(ierr);
164*c4762a1bSJed Brown   ierr = PetscPrintf(PETSC_COMM_WORLD,"%s at time %g after %D steps\n",TSConvergedReasons[reason],ftime,steps);CHKERRQ(ierr);
165*c4762a1bSJed Brown 
166*c4762a1bSJed Brown   if (user->io) {
167*c4762a1bSJed Brown     /* Print the numerical solution to screen and then dump to file */
168*c4762a1bSJed Brown     ierr = VecView(X,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
169*c4762a1bSJed Brown 
170*c4762a1bSJed Brown     /* Write out the solution along with the mesh */
171*c4762a1bSJed Brown     ierr = DMMoabSetGlobalFieldVector(dm, X);CHKERRQ(ierr);
172*c4762a1bSJed Brown #ifdef MOAB_HAVE_HDF5
173*c4762a1bSJed Brown     ierr = DMMoabOutput(dm, "ex35.h5m", "");CHKERRQ(ierr);
174*c4762a1bSJed Brown #else
175*c4762a1bSJed Brown     /* MOAB does not support true parallel writers that aren't HDF5 based
176*c4762a1bSJed Brown        And so if you are using VTK as the output format in parallel,
177*c4762a1bSJed Brown        the data could be jumbled due to the order in which the processors
178*c4762a1bSJed Brown        write out their parts of the mesh and solution tags
179*c4762a1bSJed Brown     */
180*c4762a1bSJed Brown     ierr = DMMoabOutput(dm, "ex35.vtk", "");CHKERRQ(ierr);
181*c4762a1bSJed Brown #endif
182*c4762a1bSJed Brown   }
183*c4762a1bSJed Brown 
184*c4762a1bSJed Brown   /* Free work space.
185*c4762a1bSJed Brown      Free all PETSc related resources: */
186*c4762a1bSJed Brown   ierr = MatDestroy(&J);CHKERRQ(ierr);
187*c4762a1bSJed Brown   ierr = VecDestroy(&X);CHKERRQ(ierr);
188*c4762a1bSJed Brown   ierr = TSDestroy(&ts);CHKERRQ(ierr);
189*c4762a1bSJed Brown   ierr = DMDestroy(&dm);CHKERRQ(ierr);
190*c4762a1bSJed Brown 
191*c4762a1bSJed Brown   /* Free all MOAB related resources: */
192*c4762a1bSJed Brown   ierr = Destroy_AppContext(&user);CHKERRQ(ierr);
193*c4762a1bSJed Brown   ierr = PetscFinalize();
194*c4762a1bSJed Brown   return ierr;
195*c4762a1bSJed Brown }
196*c4762a1bSJed Brown 
197*c4762a1bSJed Brown 
198*c4762a1bSJed Brown /*
199*c4762a1bSJed Brown   IJacobian - Compute IJacobian = dF/dU + a dF/dUdot
200*c4762a1bSJed Brown */
201*c4762a1bSJed Brown PetscErrorCode FormIJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal a,Mat J,Mat Jpre,void *ptr)
202*c4762a1bSJed Brown {
203*c4762a1bSJed Brown   UserCtx             user = (UserCtx)ptr;
204*c4762a1bSJed Brown   PetscErrorCode      ierr;
205*c4762a1bSJed Brown   PetscInt            dof;
206*c4762a1bSJed Brown   PetscReal           hx;
207*c4762a1bSJed Brown   DM                  dm;
208*c4762a1bSJed Brown   const moab::Range   *vlocal;
209*c4762a1bSJed Brown   PetscBool           vonboundary;
210*c4762a1bSJed Brown 
211*c4762a1bSJed Brown   PetscFunctionBegin;
212*c4762a1bSJed Brown   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
213*c4762a1bSJed Brown 
214*c4762a1bSJed Brown   /* get the essential MOAB mesh related quantities needed for FEM assembly */
215*c4762a1bSJed Brown   ierr = DMMoabGetLocalVertices(dm, &vlocal, NULL);CHKERRQ(ierr);
216*c4762a1bSJed Brown 
217*c4762a1bSJed Brown   /* compute local element sizes - structured grid */
218*c4762a1bSJed Brown   hx = 1.0/user->n;
219*c4762a1bSJed Brown 
220*c4762a1bSJed Brown   /* Compute function over the locally owned part of the grid
221*c4762a1bSJed Brown      Assemble the operator by looping over edges and computing
222*c4762a1bSJed Brown      contribution for each vertex dof                         */
223*c4762a1bSJed Brown   for(moab::Range::iterator iter = vlocal->begin(); iter != vlocal->end(); iter++) {
224*c4762a1bSJed Brown     const moab::EntityHandle vhandle = *iter;
225*c4762a1bSJed Brown 
226*c4762a1bSJed Brown     ierr = DMMoabGetDofsBlocked(dm, 1, &vhandle, &dof);CHKERRQ(ierr);
227*c4762a1bSJed Brown 
228*c4762a1bSJed Brown     /* check if vertex is on the boundary */
229*c4762a1bSJed Brown     ierr = DMMoabIsEntityOnBoundary(dm,vhandle,&vonboundary);CHKERRQ(ierr);
230*c4762a1bSJed Brown 
231*c4762a1bSJed Brown     if (vonboundary) {
232*c4762a1bSJed Brown       const PetscScalar bcvals[2][2] = {{hx,0},{0,hx}};
233*c4762a1bSJed Brown       ierr = MatSetValuesBlocked(Jpre,1,&dof,1,&dof,&bcvals[0][0],INSERT_VALUES);CHKERRQ(ierr);
234*c4762a1bSJed Brown     }
235*c4762a1bSJed Brown     else {
236*c4762a1bSJed Brown       const PetscInt    row           = dof,col[] = {dof-1,dof,dof+1};
237*c4762a1bSJed Brown       const PetscScalar dxxL          = -user->alpha/hx,dxx0 = 2.*user->alpha/hx,dxxR = -user->alpha/hx;
238*c4762a1bSJed Brown       const PetscScalar vals[2][3][2] = {{{dxxL,0},{a *hx+dxx0,0},{dxxR,0}},
239*c4762a1bSJed Brown                                          {{0,dxxL},{0,a*hx+dxx0},{0,dxxR}}};
240*c4762a1bSJed Brown       ierr = MatSetValuesBlocked(Jpre,1,&row,3,col,&vals[0][0][0],INSERT_VALUES);CHKERRQ(ierr);
241*c4762a1bSJed Brown     }
242*c4762a1bSJed Brown   }
243*c4762a1bSJed Brown 
244*c4762a1bSJed Brown   ierr = MatAssemblyBegin(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
245*c4762a1bSJed Brown   ierr = MatAssemblyEnd(Jpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
246*c4762a1bSJed Brown   if (J != Jpre) {
247*c4762a1bSJed Brown     ierr = MatAssemblyBegin(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
248*c4762a1bSJed Brown     ierr = MatAssemblyEnd(J,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
249*c4762a1bSJed Brown   }
250*c4762a1bSJed Brown   PetscFunctionReturn(0);
251*c4762a1bSJed Brown }
252*c4762a1bSJed Brown 
253*c4762a1bSJed Brown 
254*c4762a1bSJed Brown static PetscErrorCode FormRHSFunction(TS ts,PetscReal t,Vec X,Vec F,void *ptr)
255*c4762a1bSJed Brown {
256*c4762a1bSJed Brown   UserCtx           user = (UserCtx)ptr;
257*c4762a1bSJed Brown   DM                dm;
258*c4762a1bSJed Brown   PetscReal         hx;
259*c4762a1bSJed Brown   const Field       *x;
260*c4762a1bSJed Brown   Field             *f;
261*c4762a1bSJed Brown   PetscInt          dof;
262*c4762a1bSJed Brown   const moab::Range *ownedvtx;
263*c4762a1bSJed Brown   PetscErrorCode    ierr;
264*c4762a1bSJed Brown 
265*c4762a1bSJed Brown   PetscFunctionBegin;
266*c4762a1bSJed Brown   hx = 1.0/user->n;
267*c4762a1bSJed Brown   ierr = TSGetDM(ts,&dm);CHKERRQ(ierr);
268*c4762a1bSJed Brown 
269*c4762a1bSJed Brown   /* Get pointers to vector data */
270*c4762a1bSJed Brown   ierr = VecSet(F,0.0);CHKERRQ(ierr);
271*c4762a1bSJed Brown 
272*c4762a1bSJed Brown   ierr = DMMoabVecGetArrayRead(dm, X, &x);CHKERRQ(ierr);
273*c4762a1bSJed Brown   ierr = DMMoabVecGetArray(dm, F, &f);CHKERRQ(ierr);
274*c4762a1bSJed Brown 
275*c4762a1bSJed Brown   ierr = DMMoabGetLocalVertices(dm, &ownedvtx, NULL);CHKERRQ(ierr);
276*c4762a1bSJed Brown 
277*c4762a1bSJed Brown   /* Compute function over the locally owned part of the grid */
278*c4762a1bSJed Brown   for(moab::Range::iterator iter = ownedvtx->begin(); iter != ownedvtx->end(); iter++) {
279*c4762a1bSJed Brown     const moab::EntityHandle vhandle = *iter;
280*c4762a1bSJed Brown     ierr = DMMoabGetDofsBlockedLocal(dm, 1, &vhandle, &dof);CHKERRQ(ierr);
281*c4762a1bSJed Brown 
282*c4762a1bSJed Brown     PetscScalar u = x[dof].u,v = x[dof].v;
283*c4762a1bSJed Brown     f[dof].u = hx*(user->A + u*u*v - (user->B+1)*u);
284*c4762a1bSJed Brown     f[dof].v = hx*(user->B*u - u*u*v);
285*c4762a1bSJed Brown   }
286*c4762a1bSJed Brown 
287*c4762a1bSJed Brown   /* Restore vectors */
288*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArrayRead(dm, X, &x);CHKERRQ(ierr);
289*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArray(dm, F, &f);CHKERRQ(ierr);
290*c4762a1bSJed Brown   PetscFunctionReturn(0);
291*c4762a1bSJed Brown }
292*c4762a1bSJed Brown 
293*c4762a1bSJed Brown 
294*c4762a1bSJed Brown static PetscErrorCode FormIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
295*c4762a1bSJed Brown {
296*c4762a1bSJed Brown   UserCtx         user = (UserCtx)ctx;
297*c4762a1bSJed Brown   DM              dm;
298*c4762a1bSJed Brown   Field           *x,*xdot,*f;
299*c4762a1bSJed Brown   PetscReal       hx;
300*c4762a1bSJed Brown   Vec             Xloc;
301*c4762a1bSJed Brown   PetscErrorCode  ierr;
302*c4762a1bSJed Brown   PetscInt        i,bcindx;
303*c4762a1bSJed Brown   PetscBool       elem_on_boundary;
304*c4762a1bSJed Brown   const moab::Range   *vlocal;
305*c4762a1bSJed Brown 
306*c4762a1bSJed Brown   PetscFunctionBegin;
307*c4762a1bSJed Brown   hx = 1.0/user->n;
308*c4762a1bSJed Brown   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
309*c4762a1bSJed Brown 
310*c4762a1bSJed Brown   /* get the essential MOAB mesh related quantities needed for FEM assembly */
311*c4762a1bSJed Brown   ierr = DMMoabGetLocalVertices(dm, &vlocal, NULL);CHKERRQ(ierr);
312*c4762a1bSJed Brown 
313*c4762a1bSJed Brown   /* reset the residual vector */
314*c4762a1bSJed Brown   ierr = VecSet(F,0.0);CHKERRQ(ierr);
315*c4762a1bSJed Brown 
316*c4762a1bSJed Brown   ierr = DMGetLocalVector(dm,&Xloc);CHKERRQ(ierr);
317*c4762a1bSJed Brown   ierr = DMGlobalToLocalBegin(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
318*c4762a1bSJed Brown   ierr = DMGlobalToLocalEnd(dm,X,INSERT_VALUES,Xloc);CHKERRQ(ierr);
319*c4762a1bSJed Brown 
320*c4762a1bSJed Brown   /* get the local representation of the arrays from Vectors */
321*c4762a1bSJed Brown   ierr = DMMoabVecGetArrayRead(dm, Xloc, &x);CHKERRQ(ierr);
322*c4762a1bSJed Brown   ierr = DMMoabVecGetArrayRead(dm, Xdot, &xdot);CHKERRQ(ierr);
323*c4762a1bSJed Brown   ierr = DMMoabVecGetArray(dm, F, &f);CHKERRQ(ierr);
324*c4762a1bSJed Brown 
325*c4762a1bSJed Brown   /* loop over local elements */
326*c4762a1bSJed Brown   for(moab::Range::iterator iter = vlocal->begin(); iter != vlocal->end(); iter++) {
327*c4762a1bSJed Brown     const moab::EntityHandle vhandle = *iter;
328*c4762a1bSJed Brown 
329*c4762a1bSJed Brown     ierr = DMMoabGetDofsBlockedLocal(dm,1,&vhandle,&i);CHKERRQ(ierr);
330*c4762a1bSJed Brown 
331*c4762a1bSJed Brown     /* check if vertex is on the boundary */
332*c4762a1bSJed Brown     ierr = DMMoabIsEntityOnBoundary(dm,vhandle,&elem_on_boundary);CHKERRQ(ierr);
333*c4762a1bSJed Brown 
334*c4762a1bSJed Brown     if (elem_on_boundary) {
335*c4762a1bSJed Brown       ierr = DMMoabGetDofsBlocked(dm, 1, &vhandle, &bcindx);CHKERRQ(ierr);
336*c4762a1bSJed Brown       if (bcindx == 0) {  /* Apply left BC */
337*c4762a1bSJed Brown         f[i].u = hx * (x[i].u - user->leftbc.u);
338*c4762a1bSJed Brown         f[i].v = hx * (x[i].v - user->leftbc.v);
339*c4762a1bSJed Brown       } else {       /* Apply right BC */
340*c4762a1bSJed Brown         f[i].u = hx * (x[i].u - user->rightbc.u);
341*c4762a1bSJed Brown         f[i].v = hx * (x[i].v - user->rightbc.v);
342*c4762a1bSJed Brown       }
343*c4762a1bSJed Brown     }
344*c4762a1bSJed Brown     else {
345*c4762a1bSJed Brown       f[i].u = hx * xdot[i].u - user->alpha * (x[i-1].u - 2.*x[i].u + x[i+1].u) / hx;
346*c4762a1bSJed Brown       f[i].v = hx * xdot[i].v - user->alpha * (x[i-1].v - 2.*x[i].v + x[i+1].v) / hx;
347*c4762a1bSJed Brown     }
348*c4762a1bSJed Brown   }
349*c4762a1bSJed Brown 
350*c4762a1bSJed Brown   /* Restore data */
351*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArrayRead(dm, Xloc, &x);CHKERRQ(ierr);
352*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArrayRead(dm, Xdot, &xdot);CHKERRQ(ierr);
353*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArray(dm, F, &f);CHKERRQ(ierr);
354*c4762a1bSJed Brown   ierr = DMRestoreLocalVector(dm, &Xloc);CHKERRQ(ierr);
355*c4762a1bSJed Brown   PetscFunctionReturn(0);
356*c4762a1bSJed Brown }
357*c4762a1bSJed Brown 
358*c4762a1bSJed Brown 
359*c4762a1bSJed Brown PetscErrorCode FormInitialSolution(TS ts,Vec X,void *ctx)
360*c4762a1bSJed Brown {
361*c4762a1bSJed Brown   UserCtx           user = (UserCtx)ctx;
362*c4762a1bSJed Brown   PetscReal         vpos[3];
363*c4762a1bSJed Brown   DM                dm;
364*c4762a1bSJed Brown   Field             *x;
365*c4762a1bSJed Brown   PetscErrorCode    ierr;
366*c4762a1bSJed Brown   const moab::Range *vowned;
367*c4762a1bSJed Brown   PetscInt          dof;
368*c4762a1bSJed Brown   moab::Range::iterator iter;
369*c4762a1bSJed Brown 
370*c4762a1bSJed Brown   PetscFunctionBegin;
371*c4762a1bSJed Brown   ierr = TSGetDM(ts, &dm);CHKERRQ(ierr);
372*c4762a1bSJed Brown 
373*c4762a1bSJed Brown   /* get the essential MOAB mesh related quantities needed for FEM assembly */
374*c4762a1bSJed Brown   ierr = DMMoabGetLocalVertices(dm, &vowned, NULL);CHKERRQ(ierr);
375*c4762a1bSJed Brown 
376*c4762a1bSJed Brown   ierr = VecSet(X, 0.0);CHKERRQ(ierr);
377*c4762a1bSJed Brown 
378*c4762a1bSJed Brown   /* Get pointers to vector data */
379*c4762a1bSJed Brown   ierr = DMMoabVecGetArray(dm, X, &x);CHKERRQ(ierr);
380*c4762a1bSJed Brown 
381*c4762a1bSJed Brown   /* Compute function over the locally owned part of the grid */
382*c4762a1bSJed Brown   for(moab::Range::iterator iter = vowned->begin(); iter != vowned->end(); iter++) {
383*c4762a1bSJed Brown     const moab::EntityHandle vhandle = *iter;
384*c4762a1bSJed Brown     ierr = DMMoabGetDofsBlockedLocal(dm, 1, &vhandle, &dof);CHKERRQ(ierr);
385*c4762a1bSJed Brown 
386*c4762a1bSJed Brown     /* compute the mid-point of the element and use a 1-point lumped quadrature */
387*c4762a1bSJed Brown     ierr = DMMoabGetVertexCoordinates(dm,1,&vhandle,vpos);CHKERRQ(ierr);
388*c4762a1bSJed Brown 
389*c4762a1bSJed Brown     PetscReal xi = vpos[0];
390*c4762a1bSJed Brown     x[dof].u = user->leftbc.u*(1.-xi) + user->rightbc.u*xi + PetscSinReal(2.*PETSC_PI*xi);
391*c4762a1bSJed Brown     x[dof].v = user->leftbc.v*(1.-xi) + user->rightbc.v*xi;
392*c4762a1bSJed Brown   }
393*c4762a1bSJed Brown 
394*c4762a1bSJed Brown   /* Restore vectors */
395*c4762a1bSJed Brown   ierr = DMMoabVecRestoreArray(dm, X, &x);CHKERRQ(ierr);
396*c4762a1bSJed Brown   PetscFunctionReturn(0);
397*c4762a1bSJed Brown }
398*c4762a1bSJed Brown 
399*c4762a1bSJed Brown /*TEST
400*c4762a1bSJed Brown 
401*c4762a1bSJed Brown     build:
402*c4762a1bSJed Brown       requires: moab
403*c4762a1bSJed Brown 
404*c4762a1bSJed Brown     test:
405*c4762a1bSJed Brown       args: -n 20 -ts_type rosw -ts_rosw_type 2p -ts_dt 5e-2 -ts_adapt_type none
406*c4762a1bSJed Brown 
407*c4762a1bSJed Brown     test:
408*c4762a1bSJed Brown       suffix: 2
409*c4762a1bSJed Brown       nsize: 2
410*c4762a1bSJed Brown       args: -n 50 -ts_type glee -ts_adapt_type none -ts_dt 0.1 -io
411*c4762a1bSJed Brown       TODO:
412*c4762a1bSJed Brown 
413*c4762a1bSJed Brown TEST*/
414