Actual source code: mp.c
2: static char help[] = "Model multi-physics solver. Modified from src/snes/examples/tutorials/ex19.c \n\\n";
4: /* ------------------------------------------------------------------------
5: See ex19.c for discussion of the problem
7: Examples of command line options:
8: ./mp -dmmg_jacobian_mf_fd_operator
9: ./mp -dmcomposite_dense_jacobian #inefficient, but compute entire Jacobian for testing
10: ./mp -couple -snes_monitor_short -pc_type fieldsplit -ksp_monitor_short -pc_fieldsplit_type schur -fieldsplit_ksp_monitor_short -fieldsplit_1_ksp_type fgmres -fieldsplit_0_ksp_type gmres -fieldsplit_0_ksp_monitor_short -pc_fieldsplit_schur_precondition self
11: ----------------------------------------------------------------------------------------- */
12: #include mp.h
21: int main(int argc,char **argv)
22: {
23: DMMG *dmmg_comp; /* multilevel grid structure */
24: AppCtx user; /* user-defined work context */
25: PetscInt mx,my,its;
27: MPI_Comm comm;
28: SNES snes;
29: DM da1,da2;
30: DM pack;
31: PetscBool couple = PETSC_FALSE;
33: PetscInitialize(&argc,&argv,(char *)0,help);
34: PetscLogEventRegister("FormFunc1", 0,&EVENT_FORMFUNCTIONLOCAL1);
35: PetscLogEventRegister("FormFunc2", 0,&EVENT_FORMFUNCTIONLOCAL2);
36: comm = PETSC_COMM_WORLD;
38: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
39: Create user context, set problem data, create vector data structures.
40: Also, compute the initial guess.
41: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
44: Setup Physics 1:
45: - Lap(U) - Grad_y(Omega) = 0
46: - Lap(V) + Grad_x(Omega) = 0
47: - Lap(Omega) + Div([U*Omega,V*Omega]) - GR*Grad_x(T) = 0
48: where T is given by the given x.temp
49: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
50: DMDACreate2d(comm,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,3,1,0,0,&da1);
51: DMDASetFieldName(da1,0,"x-velocity");
52: DMDASetFieldName(da1,1,"y-velocity");
53: DMDASetFieldName(da1,2,"Omega");
55: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
56: Setup Physics 2:
57: - Lap(T) + PR*Div([U*T,V*T]) = 0
58: where U and V are given by the given x.u and x.v
59: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
60: DMDACreate2d(comm,DMDA_BOUNDARY_NONE,DMDA_BOUNDARY_NONE,DMDA_STENCIL_STAR,-4,-4,PETSC_DECIDE,PETSC_DECIDE,1,1,0,0,&da2);
61: DMDASetFieldName(da2,0,"temperature");
63: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
64: Create the DMComposite object to manage the two grids/physics.
65: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
66: DMCompositeCreate(comm,&pack);
67: DMCompositeAddDM(pack,da1);
68: DMCompositeAddDM(pack,da2);
70: PetscOptionsHasName(PETSC_NULL,"-couple",&couple);
71: if (couple) {
72: DMCompositeSetCoupling(pack,FormCoupleLocations);
73: }
75: /* Create the solver object and attach the grid/physics info */
76: DMMGCreate(comm,1,&user,&dmmg_comp);
77: DMMGSetDM(dmmg_comp,pack);
78: DMMGSetISColoringType(dmmg_comp,IS_COLORING_GLOBAL);
80: DMMGSetInitialGuess(dmmg_comp,FormInitialGuessComp);
81: DMMGSetSNES(dmmg_comp,FormFunctionComp,0);
82: DMMGSetFromOptions(dmmg_comp);
83: DMMGSetUp(dmmg_comp);
85: /* Problem parameters (velocity of lid, prandtl, and grashof numbers) */
86: DMDAGetInfo(da1,PETSC_NULL,&mx,&my,0,0,0,0,0,0,0,0,0,0);
87: user.lidvelocity = 1.0/(mx*my);
88: user.prandtl = 1.0;
89: user.grashof = 1000.0;
90: PetscOptionsGetReal(PETSC_NULL,"-lidvelocity",&user.lidvelocity,PETSC_NULL);
91: PetscOptionsGetReal(PETSC_NULL,"-prandtl",&user.prandtl,PETSC_NULL);
92: PetscOptionsGetReal(PETSC_NULL,"-grashof",&user.grashof,PETSC_NULL);
94: /* Solve the nonlinear system */
95: DMMGSolve(dmmg_comp);
96: snes = DMMGGetSNES(dmmg_comp);
97: SNESGetIterationNumber(snes,&its);
98: PetscPrintf(comm,"Composite Physics: Number of Newton iterations = %D\n\n", its);
100: /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
101: Free spaces
102: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
103: DMDestroy(&pack);
104: DMDestroy(&da1);
105: DMDestroy(&da2);
106: DMMGDestroy(dmmg_comp);
107: PetscFinalize();
108: return 0;
109: }
113: /*
114: FormInitialGuessComp -
115: Forms the initial guess for the composite model
116: Unwraps the global solution vector and passes its local pieces into the user functions
117: */
118: PetscErrorCode FormInitialGuessComp(DMMG dmmg,Vec X)
119: {
121: AppCtx *user = (AppCtx*)dmmg->user;
122: DM dm = dmmg->dm;
123: Vec X1,X2;
124: Field1 **x1;
125: Field2 **x2;
126: DMDALocalInfo info1,info2;
127: DM da1,da2;
130: DMCompositeGetEntries(dm,&da1,&da2);
131: /* Access the subvectors in X */
132: DMCompositeGetAccess(dm,X,&X1,&X2);
133: /* Access the arrays inside the subvectors of X */
134: DMDAVecGetArray(da1,X1,(void**)&x1);
135: DMDAVecGetArray(da2,X2,(void**)&x2);
137: DMDAGetLocalInfo(da1,&info1);
138: DMDAGetLocalInfo(da2,&info2);
140: /* Evaluate local user provided function */
141: FormInitialGuessLocal1(&info1,x1);
142: FormInitialGuessLocal2(&info2,x2,user);
144: DMDAVecRestoreArray(da1,X1,(void**)&x1);
145: DMDAVecRestoreArray(da2,X2,(void**)&x2);
146: DMCompositeRestoreAccess(dm,X,&X1,&X2);
147: return(0);
148: }
152: /*
153: FormFunctionComp - Unwraps the input vector and passes its local ghosted pieces into the user function
154: */
155: PetscErrorCode FormFunctionComp(SNES snes,Vec X,Vec F,void *ctx)
156: {
158: DMMG dmmg = (DMMG)ctx;
159: AppCtx *user = (AppCtx*)dmmg->user;
160: DM dm = dmmg->dm;
161: DMDALocalInfo info1,info2;
162: DM da1,da2;
163: Field1 **x1,**f1;
164: Field2 **x2,**f2;
165: Vec X1,X2,F1,F2;
169: DMCompositeGetEntries(dm,&da1,&da2);
170: DMDAGetLocalInfo(da1,&info1);
171: DMDAGetLocalInfo(da2,&info2);
173: /* Get local vectors to hold ghosted parts of X */
174: DMCompositeGetLocalVectors(dm,&X1,&X2);
175: DMCompositeScatter(dm,X,X1,X2);
177: /* Access the arrays inside the subvectors of X */
178: DMDAVecGetArray(da1,X1,(void**)&x1);
179: DMDAVecGetArray(da2,X2,(void**)&x2);
181: /* Access the subvectors in F.
182: These are not ghosted so directly access the memory locations in F */
183: DMCompositeGetAccess(dm,F,&F1,&F2);
185: /* Access the arrays inside the subvectors of F */
186: DMDAVecGetArray(da1,F1,(void**)&f1);
187: DMDAVecGetArray(da2,F2,(void**)&f2);
189: /* Evaluate local user provided function */
190: FormFunctionLocal1(&info1,x1,x2,f1,(void**)user);
191: FormFunctionLocal2(&info2,x1,x2,f2,(void**)user);
193: DMDAVecRestoreArray(da1,F1,(void**)&f1);
194: DMDAVecRestoreArray(da2,F2,(void**)&f2);
195: DMCompositeRestoreAccess(dm,F,&F1,&F2);
196: DMDAVecRestoreArray(da1,X1,(void**)&x1);
197: DMDAVecRestoreArray(da2,X2,(void**)&x2);
198: DMCompositeRestoreLocalVectors(dm,&X1,&X2);
199: return(0);
200: }
204: /*
205: Computes the coupling between DMDA1 and DMDA2. This determines the location of each coupling between DMDA1 and DMDA2.
206: Input Parameters:
207: + dmcomposite -
208: . A - Jacobian matrix
209: . dnz - number of nonzeros per row in DIAGONAL portion of local submatrix
210: . onz - number of nonzeros per row in the OFF-DIAGONAL portion of local submatrix
211: . __rstart - the global index of the first local row of A
212: . __nrows - number of loacal rows
213: . __start - the global index of the first local column
214: . __end - the global index of the last local column + 1
215: */
216: PetscErrorCode FormCoupleLocations(DM dmcomposite,Mat A,PetscInt *dnz,PetscInt *onz,PetscInt __rstart,PetscInt __nrows,PetscInt __start,PetscInt __end)
217: {
218: PetscInt i,j,cols[2],istart,jstart,in,jn,row,col,M;
220: DM da1,da2;
223: PetscMPIInt rank;
224: MPI_Comm_rank(((PetscObject)dmcomposite)->comm,&rank);
225: /* printf("[%d] __rstart %d, __nrows %d, __start %d, __end %d,\n",rank,__rstart,__nrows,__start,__end);*/
226: DMCompositeGetEntries(dmcomposite,&da1,&da2);
227: DMDAGetInfo(da1,0,&M,0,0,0,0,0,0,0,0,0,0,0);
228: DMDAGetCorners(da1,&istart,&jstart,PETSC_NULL,&in,&jn,PETSC_NULL);
230: /* coupling from physics 1 to physics 2 */
231: row = __rstart + 2; /* global location of first omega on this process */
232: col = __rstart + 3*in*jn; /* global location of first temp on this process */
233: for (j=jstart; j<jstart+jn; j++) {
234: for (i=istart; i<istart+in; i++) {
236: /* each omega is coupled to the temp to the left and right */
237: if (i == 0) {
238: cols[0] = col + 1;
239: MatPreallocateLocation(A,row,1,cols,dnz,onz);
240: } else if (i == M-1) {
241: cols[0] = col - 1;
242: MatPreallocateLocation(A,row,1,cols,dnz,onz);
243: } else {
244: cols[0] = col - 1;
245: cols[1] = col + 1;
246: MatPreallocateLocation(A,row,2,cols,dnz,onz);
247: }
248: row += 3;
249: col += 1;
250: }
251: }
253: /* coupling from physics 2 to physics 1 */
254: col = __rstart; /* global location of first u on this process */
255: row = __rstart + 3*in*jn; /* global location of first temp on this process */
256: for (j=jstart; j<jstart+jn; j++) {
257: for (i=istart; i<istart+in; i++) {
259: /* temp is coupled to both u and v at each point */
260: cols[0] = col;
261: cols[1] = col + 1;
262: MatPreallocateLocation(A,row,2,cols,dnz,onz);
263: row += 1;
264: col += 3;
265: }
266: }
268: return(0);
269: }