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: }