Actual source code: ex31.c
petsc-dev 2014-02-02
1: /*T
2: Concepts: KSP^solving a system of linear equations
3: Concepts: KSP^semi-implicit
4: Processors: n
5: T*/
7: /*
8: This is intended to be a prototypical example of the semi-implicit algorithm for
9: a PDE. We have three phases:
11: 1) An explicit predictor step
13: u^{k+1/3} = P(u^k)
15: 2) An implicit corrector step
17: \Delta u^{k+2/3} = F(u^{k+1/3})
19: 3) An explicit update step
21: u^{k+1} = C(u^{k+2/3})
23: We will solve on the unit square with Dirichlet boundary conditions
25: u = f(x,y) for x = 0, x = 1, y = 0, y = 1
27: Although we are using a DMDA, and thus have a structured mesh, we will discretize
28: the problem with finite elements, splitting each cell of the DMDA into two
29: triangles.
31: This uses multigrid to solve the linear system
32: */
34: static char help[] = "Solves 2D compressible Euler using multigrid.\n\n";
36: #include <petscdmda.h>
37: #include <petscksp.h>
39: typedef struct {
40: Vec rho; /* The mass solution \rho */
41: Vec rho_u; /* The x-momentum solution \rho u */
42: Vec rho_v; /* The y-momentum solution \rho v */
43: Vec rho_e; /* The energy solution \rho e_t */
44: Vec p; /* The pressure solution P */
45: Vec t; /* The temperature solution T */
46: Vec u; /* The x-velocity solution u */
47: Vec v; /* The y-velocity solution v */
48: } SolutionContext;
50: typedef struct {
51: SolutionContext sol_n; /* The solution at time t^n */
52: SolutionContext sol_phi; /* The element-averaged solution at time t^{n+\phi} */
53: SolutionContext sol_np1; /* The solution at time t^{n+1} */
54: Vec mu; /* The dynamic viscosity \mu(T) at time n */
55: Vec kappa; /* The thermal conductivity \kappa(T) at time n */
56: PetscScalar phi; /* The time weighting parameter */
57: PetscScalar dt; /* The timestep \Delta t */
58: } UserContext;
60: extern PetscErrorCode CreateStructures(DM,UserContext*);
61: extern PetscErrorCode DestroyStructures(DM,UserContext*);
62: extern PetscErrorCode ComputePredictor(DM,UserContext*);
63: extern PetscErrorCode ComputeMatrix(KSP,Mat,Mat,MatStructure*,void*);
64: extern PetscErrorCode ComputeRHS(KSP,Vec,void*);
65: extern PetscErrorCode ComputeCorrector(DM,Vec,Vec);
69: int main(int argc,char **argv)
70: {
71: KSP ksp;
72: DM da;
73: Vec x, xNew;
74: UserContext user;
77: PetscInitialize(&argc,&argv,(char*)0,help);
79: KSPCreate(PETSC_COMM_WORLD,&ksp);
80: DMDACreate2d(PETSC_COMM_WORLD, DMDA_BOUNDARY_NONE, DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,3,3,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,&da);
81: DMSetApplicationContext(da, &user);
82: KSPSetDM(ksp, da);
84: PetscOptionsBegin(PETSC_COMM_WORLD, "", "Options for PCICE", "DM");
85: user.phi = 0.5;
86: PetscOptionsScalar("-phi", "The time weighting parameter", "ex31.c", user.phi, &user.phi, NULL);
87: user.dt = 0.1;
88: PetscOptionsScalar("-dt", "The time step", "ex31.c", user.dt, &user.dt, NULL);
89: PetscOptionsEnd();
91: CreateStructures(da, &user);
92: ComputePredictor(da, &user);
94: KSPSetComputeRHS(ksp,ComputeRHS,&user);
95: KSPSetComputeOperators(ksp,ComputeMatrix,&user);
96: KSPSetFromOptions(ksp);
97: KSPSolve(ksp, NULL, NULL);
99: KSPGetSolution(ksp, &x);
100: VecDuplicate(x, &xNew);
101: ComputeCorrector(da, x, xNew);
102: VecDestroy(&xNew);
104: DestroyStructures(da, &user);
105: DMDestroy(&da);
106: KSPDestroy(&ksp);
107: PetscFinalize();
108: return 0;
109: }
113: PetscErrorCode CreateStructures(DM da, UserContext *user)
114: {
115: const PetscInt *necon;
116: PetscInt ne,nc;
120: DMDAGetElements(da,&ne,&nc,&necon);
121: DMDARestoreElements(da,&ne,&nc,&necon);
122: DMCreateGlobalVector(da, &user->sol_n.rho);
123: DMCreateGlobalVector(da, &user->sol_n.rho_u);
124: DMCreateGlobalVector(da, &user->sol_n.rho_v);
125: DMCreateGlobalVector(da, &user->sol_n.rho_e);
126: DMCreateGlobalVector(da, &user->sol_n.p);
127: DMCreateGlobalVector(da, &user->sol_n.u);
128: DMCreateGlobalVector(da, &user->sol_n.v);
129: DMCreateGlobalVector(da, &user->sol_n.t);
130: VecCreate(PETSC_COMM_WORLD, &user->sol_phi.rho);
131: VecSetSizes(user->sol_phi.rho, ne, PETSC_DECIDE);
132: VecSetType(user->sol_phi.rho,VECMPI);
133: VecDuplicate(user->sol_phi.rho, &user->sol_phi.rho_u);
134: VecDuplicate(user->sol_phi.rho, &user->sol_phi.rho_v);
135: VecDuplicate(user->sol_phi.rho, &user->sol_phi.u);
136: VecDuplicate(user->sol_phi.rho, &user->sol_phi.v);
137: DMCreateGlobalVector(da, &user->sol_np1.rho);
138: DMCreateGlobalVector(da, &user->sol_np1.rho_u);
139: DMCreateGlobalVector(da, &user->sol_np1.rho_v);
140: DMCreateGlobalVector(da, &user->sol_np1.rho_e);
141: DMCreateGlobalVector(da, &user->sol_np1.p);
142: DMCreateGlobalVector(da, &user->sol_np1.u);
143: DMCreateGlobalVector(da, &user->sol_np1.v);
144: DMCreateGlobalVector(da, &user->mu);
145: DMCreateGlobalVector(da, &user->kappa);
146: return(0);
147: }
151: PetscErrorCode DestroyStructures(DM da, UserContext *user)
152: {
156: VecDestroy(&user->sol_n.rho);
157: VecDestroy(&user->sol_n.rho_u);
158: VecDestroy(&user->sol_n.rho_v);
159: VecDestroy(&user->sol_n.rho_e);
160: VecDestroy(&user->sol_n.p);
161: VecDestroy(&user->sol_n.u);
162: VecDestroy(&user->sol_n.v);
163: VecDestroy(&user->sol_n.t);
164: VecDestroy(&user->sol_phi.rho);
165: VecDestroy(&user->sol_phi.rho_u);
166: VecDestroy(&user->sol_phi.rho_v);
167: VecDestroy(&user->sol_phi.u);
168: VecDestroy(&user->sol_phi.v);
169: VecDestroy(&user->sol_np1.rho);
170: VecDestroy(&user->sol_np1.rho_u);
171: VecDestroy(&user->sol_np1.rho_v);
172: VecDestroy(&user->sol_np1.rho_e);
173: VecDestroy(&user->sol_np1.p);
174: VecDestroy(&user->sol_np1.u);
175: VecDestroy(&user->sol_np1.v);
176: VecDestroy(&user->mu);
177: VecDestroy(&user->kappa);
178: return(0);
179: }
183: /* Average the velocity (u,v) at time t^n over each element for time n+\phi */
184: PetscErrorCode CalculateElementVelocity(DM da, UserContext *user)
185: {
186: PetscScalar *u_n, *v_n;
187: PetscScalar *u_phi, *v_phi;
188: const PetscInt *necon;
189: PetscInt j, e, ne, nc;
193: DMDAGetElements(da, &ne, &nc, &necon);
194: VecGetArray(user->sol_n.u, &u_n);
195: VecGetArray(user->sol_n.v, &v_n);
196: PetscMalloc1(ne,&u_phi);
197: PetscMalloc1(ne,&v_phi);
198: for (e = 0; e < ne; e++) {
199: u_phi[e] = 0.0;
200: v_phi[e] = 0.0;
201: for (j = 0; j < 3; j++) {
202: u_phi[e] += u_n[necon[3*e+j]];
203: v_phi[e] += v_n[necon[3*e+j]];
204: }
205: u_phi[e] /= 3.0;
206: v_phi[e] /= 3.0;
207: }
208: PetscFree(u_phi);
209: PetscFree(v_phi);
210: DMDARestoreElements(da, &ne,&nc, &necon);
211: VecRestoreArray(user->sol_n.u, &u_n);
212: VecRestoreArray(user->sol_n.v, &v_n);
213: return(0);
214: }
218: /* This is equation 32,
220: U^{n+\phi}_E = {1\over Vol_E} \left(\int_\Omega [N]{U^n} d\Omega - \phi\Delta t \int_\Omega [\nabla N]\cdot{F^n} d\Omega \right) + \phi\Delta t Q^n
222: which is really simple for linear elements
224: U^{n+\phi}_E = {1\over3} \sum^3_{i=1} U^n_i - \phi\Delta t [\nabla N]\cdot{F^n} + \phi\Delta t Q^n
226: where
228: U^{n+\phi}_E = {\rho \rho u \rho v}^{n+\phi}_E
230: and the x and y components of the convective fluxes F are
232: f^n = {\rho u \rho u^2 \rho uv}^n g^n = {\rho v \rho uv \rho v^2}^n
233: */
234: PetscErrorCode TaylorGalerkinStepI(DM da, UserContext *user)
235: {
236: PetscScalar phi_dt = user->phi*user->dt;
237: PetscScalar *u_n, *v_n;
238: PetscScalar *rho_n, *rho_u_n, *rho_v_n;
239: PetscScalar *rho_phi, *rho_u_phi, *rho_v_phi;
240: PetscScalar Fx_x, Fy_y;
241: PetscScalar psi_x[3], psi_y[3];
242: PetscInt idx[3];
243: PetscReal hx, hy;
244: const PetscInt *necon;
245: PetscInt j, e, ne, nc, mx, my;
249: DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);
250: hx = 1.0 / (PetscReal)(mx-1);
251: hy = 1.0 / (PetscReal)(my-1);
252: VecSet(user->sol_phi.rho,0.0);
253: VecSet(user->sol_phi.rho_u,0.0);
254: VecSet(user->sol_phi.rho_v,0.0);
255: VecGetArray(user->sol_n.u, &u_n);
256: VecGetArray(user->sol_n.v, &v_n);
257: VecGetArray(user->sol_n.rho, &rho_n);
258: VecGetArray(user->sol_n.rho_u, &rho_u_n);
259: VecGetArray(user->sol_n.rho_v, &rho_v_n);
260: VecGetArray(user->sol_phi.rho, &rho_phi);
261: VecGetArray(user->sol_phi.rho_u, &rho_u_phi);
262: VecGetArray(user->sol_phi.rho_v, &rho_v_phi);
263: DMDAGetElements(da, &ne, &nc, &necon);
264: for (e = 0; e < ne; e++) {
265: /* Average the existing fields over the element */
266: for (j = 0; j < 3; j++) {
267: idx[j] = necon[3*e+j];
268: rho_phi[e] += rho_n[idx[j]];
269: rho_u_phi[e] += rho_u_n[idx[j]];
270: rho_v_phi[e] += rho_v_n[idx[j]];
271: }
272: rho_phi[e] /= 3.0;
273: rho_u_phi[e] /= 3.0;
274: rho_v_phi[e] /= 3.0;
275: /* Get basis function deriatives (we need the orientation of the element here) */
276: if (idx[1] > idx[0]) {
277: psi_x[0] = -hy; psi_x[1] = hy; psi_x[2] = 0.0;
278: psi_y[0] = -hx; psi_y[1] = 0.0; psi_y[2] = hx;
279: } else {
280: psi_x[0] = hy; psi_x[1] = -hy; psi_x[2] = 0.0;
281: psi_y[0] = hx; psi_y[1] = 0.0; psi_y[2] = -hx;
282: }
283: /* Determine the convective fluxes for \rho^{n+\phi} */
284: Fx_x = 0.0; Fy_y = 0.0;
285: for (j = 0; j < 3; j++) {
286: Fx_x += psi_x[j]*rho_u_n[idx[j]];
287: Fy_y += psi_y[j]*rho_v_n[idx[j]];
288: }
289: rho_phi[e] -= phi_dt*(Fx_x + Fy_y);
290: /* Determine the convective fluxes for (\rho u)^{n+\phi} */
291: Fx_x = 0.0; Fy_y = 0.0;
292: for (j = 0; j < 3; j++) {
293: Fx_x += psi_x[j]*rho_u_n[idx[j]]*u_n[idx[j]];
294: Fy_y += psi_y[j]*rho_v_n[idx[j]]*u_n[idx[j]];
295: }
296: rho_u_phi[e] -= phi_dt*(Fx_x + Fy_y);
297: /* Determine the convective fluxes for (\rho v)^{n+\phi} */
298: Fx_x = 0.0; Fy_y = 0.0;
299: for (j = 0; j < 3; j++) {
300: Fx_x += psi_x[j]*rho_u_n[idx[j]]*v_n[idx[j]];
301: Fy_y += psi_y[j]*rho_v_n[idx[j]]*v_n[idx[j]];
302: }
303: rho_v_phi[e] -= phi_dt*(Fx_x + Fy_y);
304: }
305: DMDARestoreElements(da, &ne, &nc, &necon);
306: VecRestoreArray(user->sol_n.u, &u_n);
307: VecRestoreArray(user->sol_n.v, &v_n);
308: VecRestoreArray(user->sol_n.rho, &rho_n);
309: VecRestoreArray(user->sol_n.rho_u, &rho_u_n);
310: VecRestoreArray(user->sol_n.rho_v, &rho_v_n);
311: VecRestoreArray(user->sol_phi.rho, &rho_phi);
312: VecRestoreArray(user->sol_phi.rho_u, &rho_u_phi);
313: VecRestoreArray(user->sol_phi.rho_v, &rho_v_phi);
314: return(0);
315: }
319: /*
320: The element stiffness matrix for the identity in linear elements is
322: 1 /2 1 1\
323: - |1 2 1|
324: 12 \1 1 2/
326: no matter what the shape of the triangle. */
327: PetscErrorCode TaylorGalerkinStepIIMomentum(DM da, UserContext *user)
328: {
329: MPI_Comm comm;
330: KSP ksp;
331: Mat mat;
332: Vec rhs_u, rhs_v;
333: PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333,
334: 0.08333333333, 0.16666666667, 0.08333333333,
335: 0.08333333333, 0.08333333333, 0.16666666667};
336: PetscScalar *u_n, *v_n, *mu_n;
337: PetscScalar *u_phi, *v_phi;
338: PetscScalar *rho_u_phi, *rho_v_phi;
339: PetscInt idx[3];
340: PetscScalar values_u[3];
341: PetscScalar values_v[3];
342: PetscScalar psi_x[3], psi_y[3];
343: PetscScalar mu, tau_xx, tau_xy, tau_yy;
344: PetscReal hx, hy, area;
345: const PetscInt *necon;
346: PetscInt j, k, e, ne, nc, mx, my;
350: PetscObjectGetComm((PetscObject) da, &comm);
351: DMSetMatType(da,MATAIJ);
352: DMCreateMatrix(da, &mat);
353: MatSetOption(mat,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
354: DMGetGlobalVector(da, &rhs_u);
355: DMGetGlobalVector(da, &rhs_v);
356: KSPCreate(comm, &ksp);
357: KSPSetFromOptions(ksp);
359: DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);
360: hx = 1.0 / (PetscReal)(mx-1);
361: hy = 1.0 / (PetscReal)(my-1);
362: area = 0.5*hx*hy;
363: VecGetArray(user->sol_n.u, &u_n);
364: VecGetArray(user->sol_n.v, &v_n);
365: VecGetArray(user->mu, &mu_n);
366: VecGetArray(user->sol_phi.u, &u_phi);
367: VecGetArray(user->sol_phi.v, &v_phi);
368: VecGetArray(user->sol_phi.rho_u, &rho_u_phi);
369: VecGetArray(user->sol_phi.rho_v, &rho_v_phi);
370: DMDAGetElements(da, &ne, &nc, &necon);
371: for (e = 0; e < ne; e++) {
372: for (j = 0; j < 3; j++) {
373: idx[j] = necon[3*e+j];
374: values_u[j] = 0.0;
375: values_v[j] = 0.0;
376: }
377: /* Get basis function deriatives (we need the orientation of the element here) */
378: if (idx[1] > idx[0]) {
379: psi_x[0] = -hy; psi_x[1] = hy; psi_x[2] = 0.0;
380: psi_y[0] = -hx; psi_y[1] = 0.0; psi_y[2] = hx;
381: } else {
382: psi_x[0] = hy; psi_x[1] = -hy; psi_x[2] = 0.0;
383: psi_y[0] = hx; psi_y[1] = 0.0; psi_y[2] = -hx;
384: }
385: /* <\nabla\psi, F^{n+\phi}_e>: Divergence of the element-averaged convective fluxes */
386: for (j = 0; j < 3; j++) {
387: values_u[j] += psi_x[j]*rho_u_phi[e]*u_phi[e] + psi_y[j]*rho_u_phi[e]*v_phi[e];
388: values_v[j] += psi_x[j]*rho_v_phi[e]*u_phi[e] + psi_y[j]*rho_v_phi[e]*v_phi[e];
389: }
390: /* -<\nabla\psi, F^n_v>: Divergence of the viscous fluxes */
391: for (j = 0; j < 3; j++) {
392: /* \tau_{xx} = 2/3 \mu(T) (2 {\partial u\over\partial x} - {\partial v\over\partial y}) */
393: /* \tau_{xy} = \mu(T) ( {\partial u\over\partial y} + {\partial v\over\partial x}) */
394: /* \tau_{yy} = 2/3 \mu(T) (2 {\partial v\over\partial y} - {\partial u\over\partial x}) */
395: mu = 0.0;
396: tau_xx = 0.0;
397: tau_xy = 0.0;
398: tau_yy = 0.0;
399: for (k = 0; k < 3; k++) {
400: mu += mu_n[idx[k]];
401: tau_xx += 2.0*psi_x[k]*u_n[idx[k]] - psi_y[k]*v_n[idx[k]];
402: tau_xy += psi_y[k]*u_n[idx[k]] + psi_x[k]*v_n[idx[k]];
403: tau_yy += 2.0*psi_y[k]*v_n[idx[k]] - psi_x[k]*u_n[idx[k]];
404: }
405: mu /= 3.0;
406: tau_xx *= (2.0/3.0)*mu;
407: tau_xy *= mu;
408: tau_yy *= (2.0/3.0)*mu;
409: values_u[j] -= area*(psi_x[j]*tau_xx + psi_y[j]*tau_xy);
410: values_v[j] -= area*(psi_x[j]*tau_xy + psi_y[j]*tau_yy);
411: }
412: /* Accumulate to global structures */
413: VecSetValuesLocal(rhs_u, 3, idx, values_u, ADD_VALUES);
414: VecSetValuesLocal(rhs_v, 3, idx, values_v, ADD_VALUES);
415: MatSetValuesLocal(mat, 3, idx, 3, idx, identity, ADD_VALUES);
416: }
417: DMDARestoreElements(da, &ne, &nc, &necon);
418: VecRestoreArray(user->sol_n.u, &u_n);
419: VecRestoreArray(user->sol_n.v, &v_n);
420: VecRestoreArray(user->mu, &mu_n);
421: VecRestoreArray(user->sol_phi.u, &u_phi);
422: VecRestoreArray(user->sol_phi.v, &v_phi);
423: VecRestoreArray(user->sol_phi.rho_u, &rho_u_phi);
424: VecRestoreArray(user->sol_phi.rho_v, &rho_v_phi);
426: VecAssemblyBegin(rhs_u);
427: VecAssemblyBegin(rhs_v);
428: MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY);
429: VecAssemblyEnd(rhs_u);
430: VecAssemblyEnd(rhs_v);
431: MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY);
432: VecScale(rhs_u,user->dt);
433: VecScale(rhs_v,user->dt);
435: KSPSetOperators(ksp, mat, mat, DIFFERENT_NONZERO_PATTERN);
436: KSPSolve(ksp, rhs_u, user->sol_np1.rho_u);
437: KSPSolve(ksp, rhs_v, user->sol_np1.rho_v);
438: KSPDestroy(&ksp);
439: MatDestroy(&mat);
440: DMRestoreGlobalVector(da, &rhs_u);
441: DMRestoreGlobalVector(da, &rhs_v);
442: return(0);
443: }
447: /* Notice that this requires the previous momentum solution.
449: The element stiffness matrix for the identity in linear elements is
451: 1 /2 1 1\
452: - |1 2 1|
453: 12 \1 1 2/
455: no matter what the shape of the triangle. */
456: PetscErrorCode TaylorGalerkinStepIIMassEnergy(DM da, UserContext *user)
457: {
458: MPI_Comm comm;
459: Mat mat;
460: Vec rhs_m, rhs_e;
461: PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333,
462: 0.08333333333, 0.16666666667, 0.08333333333,
463: 0.08333333333, 0.08333333333, 0.16666666667};
464: PetscScalar *u_n, *v_n, *p_n, *t_n, *mu_n, *kappa_n;
465: PetscScalar *rho_n, *rho_u_n, *rho_v_n, *rho_e_n;
466: PetscScalar *u_phi, *v_phi;
467: PetscScalar *rho_u_np1, *rho_v_np1;
468: PetscInt idx[3];
469: PetscScalar psi_x[3], psi_y[3];
470: PetscScalar values_m[3];
471: PetscScalar values_e[3];
472: PetscScalar phi = user->phi;
473: PetscScalar mu, kappa, tau_xx, tau_xy, tau_yy, q_x, q_y;
474: PetscReal hx, hy, area;
475: KSP ksp;
476: const PetscInt *necon;
477: PetscInt j, k, e, ne, nc, mx, my;
481: PetscObjectGetComm((PetscObject) da, &comm);
482: DMSetMatType(da,MATAIJ);
483: DMCreateMatrix(da, &mat);
484: MatSetOption(mat,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);
485: DMGetGlobalVector(da, &rhs_m);
486: DMGetGlobalVector(da, &rhs_e);
487: KSPCreate(comm, &ksp);
488: KSPSetFromOptions(ksp);
490: DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);
491: hx = 1.0 / (PetscReal)(mx-1);
492: hy = 1.0 / (PetscReal)(my-1);
493: area = 0.5*hx*hy;
494: VecGetArray(user->sol_n.u, &u_n);
495: VecGetArray(user->sol_n.v, &v_n);
496: VecGetArray(user->sol_n.p, &p_n);
497: VecGetArray(user->sol_n.t, &t_n);
498: VecGetArray(user->mu, &mu_n);
499: VecGetArray(user->kappa, &kappa_n);
500: VecGetArray(user->sol_n.rho, &rho_n);
501: VecGetArray(user->sol_n.rho_u, &rho_u_n);
502: VecGetArray(user->sol_n.rho_v, &rho_v_n);
503: VecGetArray(user->sol_n.rho_e, &rho_e_n);
504: VecGetArray(user->sol_phi.u, &u_phi);
505: VecGetArray(user->sol_phi.v, &v_phi);
506: VecGetArray(user->sol_np1.rho_u, &rho_u_np1);
507: VecGetArray(user->sol_np1.rho_v, &rho_v_np1);
508: DMDAGetElements(da, &ne, &nc, &necon);
509: for (e = 0; e < ne; e++) {
510: for (j = 0; j < 3; j++) {
511: idx[j] = necon[3*e+j];
512: values_m[j] = 0.0;
513: values_e[j] = 0.0;
514: }
515: /* Get basis function deriatives (we need the orientation of the element here) */
516: if (idx[1] > idx[0]) {
517: psi_x[0] = -hy; psi_x[1] = hy; psi_x[2] = 0.0;
518: psi_y[0] = -hx; psi_y[1] = 0.0; psi_y[2] = hx;
519: } else {
520: psi_x[0] = hy; psi_x[1] = -hy; psi_x[2] = 0.0;
521: psi_y[0] = hx; psi_y[1] = 0.0; psi_y[2] = -hx;
522: }
523: /* <\nabla\psi, F^*>: Divergence of the predicted convective fluxes */
524: for (j = 0; j < 3; j++) {
525: values_m[j] += (psi_x[j]*(phi*rho_u_np1[idx[j]] + rho_u_n[idx[j]]) + psi_y[j]*(rho_v_np1[idx[j]] + rho_v_n[idx[j]]))/3.0;
526: values_e[j] += values_m[j]*((rho_e_n[idx[j]] + p_n[idx[j]]) / rho_n[idx[j]]);
527: }
528: /* -<\nabla\psi, F^n_v>: Divergence of the viscous fluxes */
529: for (j = 0; j < 3; j++) {
530: /* \tau_{xx} = 2/3 \mu(T) (2 {\partial u\over\partial x} - {\partial v\over\partial y}) */
531: /* \tau_{xy} = \mu(T) ( {\partial u\over\partial y} + {\partial v\over\partial x}) */
532: /* \tau_{yy} = 2/3 \mu(T) (2 {\partial v\over\partial y} - {\partial u\over\partial x}) */
533: /* q_x = -\kappa(T) {\partial T\over\partial x} */
534: /* q_y = -\kappa(T) {\partial T\over\partial y} */
536: /* above code commeted out - causing ininitialized variables. */
537: q_x =0; q_y =0;
539: mu = 0.0;
540: kappa = 0.0;
541: tau_xx = 0.0;
542: tau_xy = 0.0;
543: tau_yy = 0.0;
544: for (k = 0; k < 3; k++) {
545: mu += mu_n[idx[k]];
546: kappa += kappa_n[idx[k]];
547: tau_xx += 2.0*psi_x[k]*u_n[idx[k]] - psi_y[k]*v_n[idx[k]];
548: tau_xy += psi_y[k]*u_n[idx[k]] + psi_x[k]*v_n[idx[k]];
549: tau_yy += 2.0*psi_y[k]*v_n[idx[k]] - psi_x[k]*u_n[idx[k]];
550: q_x += psi_x[k]*t_n[idx[k]];
551: q_y += psi_y[k]*t_n[idx[k]];
552: }
553: mu /= 3.0;
554: kappa /= 3.0;
555: tau_xx *= (2.0/3.0)*mu;
556: tau_xy *= mu;
557: tau_yy *= (2.0/3.0)*mu;
558: values_e[j] -= area*(psi_x[j]*(u_phi[e]*tau_xx + v_phi[e]*tau_xy + q_x) + psi_y[j]*(u_phi[e]*tau_xy + v_phi[e]*tau_yy + q_y));
559: }
560: /* Accumulate to global structures */
561: VecSetValuesLocal(rhs_m, 3, idx, values_m, ADD_VALUES);
562: VecSetValuesLocal(rhs_e, 3, idx, values_e, ADD_VALUES);
563: MatSetValuesLocal(mat, 3, idx, 3, idx, identity, ADD_VALUES);
564: }
565: DMDARestoreElements(da, &ne, &nc, &necon);
566: VecRestoreArray(user->sol_n.u, &u_n);
567: VecRestoreArray(user->sol_n.v, &v_n);
568: VecRestoreArray(user->sol_n.p, &p_n);
569: VecRestoreArray(user->sol_n.t, &t_n);
570: VecRestoreArray(user->mu, &mu_n);
571: VecRestoreArray(user->kappa, &kappa_n);
572: VecRestoreArray(user->sol_n.rho, &rho_n);
573: VecRestoreArray(user->sol_n.rho_u, &rho_u_n);
574: VecRestoreArray(user->sol_n.rho_v, &rho_v_n);
575: VecRestoreArray(user->sol_n.rho_e, &rho_e_n);
576: VecRestoreArray(user->sol_phi.u, &u_phi);
577: VecRestoreArray(user->sol_phi.v, &v_phi);
578: VecRestoreArray(user->sol_np1.rho_u, &rho_u_np1);
579: VecRestoreArray(user->sol_np1.rho_v, &rho_v_np1);
581: VecAssemblyBegin(rhs_m);
582: VecAssemblyBegin(rhs_e);
583: MatAssemblyBegin(mat, MAT_FINAL_ASSEMBLY);
584: VecAssemblyEnd(rhs_m);
585: VecAssemblyEnd(rhs_e);
586: MatAssemblyEnd(mat, MAT_FINAL_ASSEMBLY);
587: VecScale(rhs_m, user->dt);
588: VecScale(rhs_e, user->dt);
590: KSPSetOperators(ksp, mat, mat, DIFFERENT_NONZERO_PATTERN);
591: KSPSolve(ksp, rhs_m, user->sol_np1.rho);
592: KSPSolve(ksp, rhs_e, user->sol_np1.rho_e);
593: KSPDestroy(&ksp);
594: MatDestroy(&mat);
595: DMRestoreGlobalVector(da, &rhs_m);
596: DMRestoreGlobalVector(da, &rhs_e);
597: return(0);
598: }
602: PetscErrorCode ComputePredictor(DM da, UserContext *user)
603: {
604: Vec uOldLocal, uLocal,uOld;
605: PetscScalar *pOld;
606: PetscScalar *p;
610: DMGetGlobalVector(da, &uOld);
611: DMGetLocalVector(da, &uOldLocal);
612: DMGetLocalVector(da, &uLocal);
613: DMGlobalToLocalBegin(da, uOld, INSERT_VALUES, uOldLocal);
614: DMGlobalToLocalEnd(da, uOld, INSERT_VALUES, uOldLocal);
615: VecGetArray(uOldLocal, &pOld);
616: VecGetArray(uLocal, &p);
618: /* Source terms are all zero right now */
619: CalculateElementVelocity(da, user);
620: TaylorGalerkinStepI(da, user);
621: TaylorGalerkinStepIIMomentum(da, user);
622: TaylorGalerkinStepIIMassEnergy(da, user);
623: /* Solve equation (9) for \delta(\rho\vu) and (\rho\vu)^* */
624: /* Solve equation (13) for \delta\rho and \rho^* */
625: /* Solve equation (15) for \delta(\rho e_t) and (\rho e_t)^* */
626: /* Apply artifical dissipation */
627: /* Determine the smoothed explicit pressure, \tilde P and temperature \tilde T using the equation of state */
630: VecRestoreArray(uOldLocal, &pOld);
631: VecRestoreArray(uLocal, &p);
632: #if 0
633: DMLocalToGlobalBegin(da, uLocal, ADD_VALUES,u);
634: DMLocalToGlobalEnd(da, uLocal, ADD_VALUES,u);
635: DMRestoreLocalVector(da, &uOldLocal);
636: DMRestoreLocalVector(da, &uLocal);
637: #endif
638: return(0);
639: }
643: /*
644: We integrate over each cell
646: (i, j+1)----(i+1, j+1)
647: | \ |
648: | \ |
649: | \ |
650: | \ |
651: | \ |
652: | \ |
653: | \ |
654: (i, j)----(i+1, j)
655: */
656: PetscErrorCode ComputeRHS(KSP ksp, Vec b, void *ctx)
657: {
658: UserContext *user = (UserContext*)ctx;
659: PetscScalar phi = user->phi;
660: PetscScalar *array;
661: PetscInt ne,nc,i;
662: const PetscInt *e;
664: Vec blocal;
665: DM da;
668: KSPGetDM(ksp,&da);
669: /* access a local vector with room for the ghost points */
670: DMGetLocalVector(da,&blocal);
671: VecGetArray(blocal, (PetscScalar**) &array);
673: /* access the list of elements on this processor and loop over them */
674: DMDAGetElements(da,&ne,&nc,&e);
675: for (i=0; i<ne; i++) {
677: /* this is nonsense, but set each nodal value to phi (will actually do integration over element */
678: array[e[3*i]] = phi;
679: array[e[3*i+1]] = phi;
680: array[e[3*i+2]] = phi;
681: }
682: VecRestoreArray(blocal, (PetscScalar**) &array);
683: DMDARestoreElements(da,&ne,&nc,&e);
685: /* add our partial sums over all processors into b */
686: DMLocalToGlobalBegin(da,blocal,ADD_VALUES,b);
687: DMLocalToGlobalEnd(da,blocal, ADD_VALUES,b);
688: DMRestoreLocalVector(da,&blocal);
689: return(0);
690: }
694: /*
695: We integrate over each cell
697: (i, j+1)----(i+1, j+1)
698: | \ |
699: | \ |
700: | \ |
701: | \ |
702: | \ |
703: | \ |
704: | \ |
705: (i, j)----(i+1, j)
707: However, the element stiffness matrix for the identity in linear elements is
709: 1 /2 1 1\
710: - |1 2 1|
711: 12 \1 1 2/
713: no matter what the shape of the triangle. The Laplacian stiffness matrix is
715: 1 / (x_2 - x_1)^2 + (y_2 - y_1)^2 -(x_2 - x_0)(x_2 - x_1) - (y_2 - y_1)(y_2 - y_0) (x_1 - x_0)(x_2 - x_1) + (y_1 - y_0)(y_2 - y_1)\
716: - |-(x_2 - x_0)(x_2 - x_1) - (y_2 - y_1)(y_2 - y_0) (x_2 - x_0)^2 + (y_2 - y_0)^2 -(x_1 - x_0)(x_2 - x_0) - (y_1 - y_0)(y_2 - y_0)|
717: A \ (x_1 - x_0)(x_2 - x_1) + (y_1 - y_0)(y_2 - y_1) -(x_1 - x_0)(x_2 - x_0) - (y_1 - y_0)(y_2 - y_0) (x_1 - x_0)^2 + (y_1 - y_0)^2 /
719: where A is the area of the triangle, and (x_i, y_i) is its i'th vertex.
720: */
721: PetscErrorCode ComputeMatrix(KSP ksp, Mat J, Mat jac, MatStructure *flag,void *ctx)
722: {
723: UserContext *user = (UserContext*)ctx;
724: /* not being used!
725: PetscScalar identity[9] = {0.16666666667, 0.08333333333, 0.08333333333,
726: 0.08333333333, 0.16666666667, 0.08333333333,
727: 0.08333333333, 0.08333333333, 0.16666666667};
728: */
729: PetscScalar values[3][3];
730: PetscInt idx[3];
731: PetscScalar hx, hy, hx2, hy2, area,phi_dt2;
732: PetscInt i,mx,my,xm,ym,xs,ys;
733: PetscInt ne,nc;
734: const PetscInt *e;
736: DM da;
739: KSPGetDM(ksp,&da);
740: DMDAGetInfo(da, 0, &mx, &my, 0,0,0,0,0,0,0,0,0,0);
741: DMDAGetCorners(da,&xs,&ys,0,&xm,&ym,0);
742: hx = 1.0 / (mx-1);
743: hy = 1.0 / (my-1);
744: area = 0.5*hx*hy;
745: phi_dt2 = user->phi*user->dt*user->dt;
746: hx2 = hx*hx/area*phi_dt2;
747: hy2 = hy*hy/area*phi_dt2;
749: /* initially all elements have identical geometry so all element stiffness are identical */
750: values[0][0] = hx2 + hy2; values[0][1] = -hy2; values[0][2] = -hx2;
751: values[1][0] = -hy2; values[1][1] = hy2; values[1][2] = 0.0;
752: values[2][0] = -hx2; values[2][1] = 0.0; values[2][2] = hx2;
754: DMDAGetElements(da,&ne,&nc,&e);
755: for (i=0; i<ne; i++) {
756: idx[0] = e[3*i];
757: idx[1] = e[3*i+1];
758: idx[2] = e[3*i+2];
759: MatSetValuesLocal(jac,3,idx,3,idx,(PetscScalar*)values,ADD_VALUES);
760: }
761: DMDARestoreElements(da,&ne,&nc,&e);
762: MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY);
763: MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY);
764: return(0);
765: }
769: PetscErrorCode ComputeCorrector(DM da, Vec uOld, Vec u)
770: {
771: Vec uOldLocal, uLocal;
772: PetscScalar *cOld;
773: PetscScalar *c;
774: PetscInt i,ne,nc;
775: const PetscInt *e;
779: VecSet(u,0.0);
780: DMGetLocalVector(da, &uOldLocal);
781: DMGetLocalVector(da, &uLocal);
782: VecSet(uLocal,0.0);
783: DMGlobalToLocalBegin(da, uOld, INSERT_VALUES, uOldLocal);
784: DMGlobalToLocalEnd(da, uOld, INSERT_VALUES, uOldLocal);
785: VecGetArray(uOldLocal, &cOld);
786: VecGetArray(uLocal, &c);
788: /* access the list of elements on this processor and loop over them */
789: DMDAGetElements(da,&ne,&nc,&e);
790: for (i=0; i<ne; i++) {
792: /* this is nonsense, but copy each nodal value*/
793: c[e[3*i]] = cOld[e[3*i]];
794: c[e[3*i+1]] = cOld[e[3*i+1]];
795: c[e[3*i+2]] = cOld[e[3*i+2]];
796: }
797: DMDARestoreElements(da,&ne,&nc,&e);
798: VecRestoreArray(uOldLocal, &cOld);
799: VecRestoreArray(uLocal, &c);
800: DMLocalToGlobalBegin(da, uLocal, ADD_VALUES,u);
801: DMLocalToGlobalEnd(da, uLocal, ADD_VALUES,u);
802: DMRestoreLocalVector(da, &uOldLocal);
803: DMRestoreLocalVector(da, &uLocal);
804: return(0);
805: }