Actual source code: meshmgsnes.c

  1: #include <petscpcmg.h>      /*I "petscpcmg.h"   I*/
  2: #include <petscdmmg.h>      /*I "petscdmmg.h"   I*/
  3: #include <petscdmmesh.h>    /*I "petscdmmesh.h" I*/
  4: #include <Selection.hh>

  6: /* Just to set iterations */
  7: #include <private/snesimpl.h>      /*I "petscsnes.h"  I*/

  9: #if 0
 10: PetscErrorCode CreateNullSpace(DMMG dmmg, Vec *nulls) {
 11:   DM             mesh = dmmg->dm;
 12:   Vec            nS   = nulls[0];
 13:   SectionReal    nullSpace;

 17:   DMMeshGetSectionReal(mesh, "nullSpace", &nullSpace);
 18:   {
 19:     ALE::Obj<PETSC_MESH_TYPE> m;
 20:     ALE::Obj<PETSC_MESH_TYPE::real_section_type> s;

 22:     DMMeshGetMesh(mesh, m);
 23:     SectionRealGetSection(nullSpace, s);
 24:     ALE::Obj<ALE::Discretization> disc = m->getDiscretization("p");
 25:     const int dim = m->getDimension();

 27:     for(int d = 0; d <= dim; ++d) {
 28:       const int numDof = disc->getNumDof(d);

 30:       if (numDof) {
 31:         const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& stratum = m->depthStratum(d);
 32:         const PETSC_MESH_TYPE::label_sequence::iterator  end     = stratum->end();
 33:         double                                    *values  = new double[numDof];

 35:         for(PETSC_MESH_TYPE::label_sequence::iterator p_iter = stratum->begin(); p_iter != end; ++p_iter) {
 36:           for(int i = 0; i < numDof; ++i) values[i] = 1.0;
 37:           s->updatePoint(*p_iter, values);
 38:         }
 39:       }
 40:     }
 41:   }
 42:   SectionRealToVec(nullSpace, mesh, SCATTER_FORWARD, nS);
 43:   std::cout << "Null space:" << std::endl;
 44:   VecView(nS, PETSC_VIEWER_STDOUT_SELF);
 45:   SectionRealDestroy(&nullSpace);
 46:   return(0);
 47: }
 48: #endif

 50: /* Nonlinear relaxation on all the equations with an initial guess in x */
 54: PetscErrorCode Relax_Mesh(DMMG *dmmg, DM mesh, MatSORType flag, int its, Vec X, Vec B)
 55: {
 56:   SectionReal      sectionX, sectionB, cellX;
 57:   DM               smallMesh;
 58:   DMMG            *smallDmmg;
 59:   DMDALocalFunction1 func;
 60:   DMDALocalFunction1 jac;
 61:   ALE::Obj<PETSC_MESH_TYPE> m;
 62:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> sX;
 63:   ALE::Obj<PETSC_MESH_TYPE::real_section_type> sB;
 64:   PetscBool        fasDebug;
 65:   PetscErrorCode   ierr;

 68:   PetscOptionsHasName(dmmg[0]->prefix, "-dmmg_fas_debug", &fasDebug);
 69:   if (fasDebug) {PetscPrintf(dmmg[0]->comm, "  FAS mesh relaxation\n");}
 70:   if (its <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Relaxation requires global its %D positive", its);
 71:   DMMeshCreate(PETSC_COMM_SELF, &smallMesh);
 72:   DMMGCreate(PETSC_COMM_SELF, -1, PETSC_NULL, &smallDmmg);
 73:   //DMMGSetMatType(smallDmmg, MATSEQDENSE);
 74:   DMMGSetOptionsPrefix(smallDmmg, "fas_");
 75:   DMMGSetUser(smallDmmg, 0, DMMGGetUser(dmmg, 0));
 76:   DMMGGetSNESLocal(dmmg, &func, &jac);
 77:   DMMeshGetMesh(mesh, m);
 78:   DMMeshGetSectionReal(mesh, "default", &sectionX);
 79:   SectionRealToVec(sectionX, mesh, SCATTER_REVERSE, X);
 80:   SectionRealGetSection(sectionX, sX);
 81:   DMMeshGetSectionReal(mesh, "constant", &sectionB);
 82:   SectionRealToVec(sectionB, mesh, SCATTER_REVERSE, B);
 83:   SectionRealGetSection(sectionB, sB);
 84:   SectionRealCreate(PETSC_COMM_SELF, &cellX);
 85:   //const ALE::Obj<PETSC_MESH_TYPE::sieve_type>&     sieve   = m->getSieve();
 86:   //const ALE::Obj<PETSC_MESH_TYPE::label_sequence>& cells   = m->heightStratum(0);
 87:   //const int                                  depth   = m->depth();
 88:   //const ALE::Obj<PETSC_MESH_TYPE::label_type>&     marker  = m->getLabel("marker");
 89:   //const int                                  cellDof = m->sizeWithBC(sX, *cells->begin());

 91: #ifdef PETSC_OPT_SIEVE
 92:   SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "I am being lazy, bug me.");
 93: #else
 94:   ALE::Obj<PETSC_MESH_TYPE::names_type> fields = m->getDiscretizations();
 95:   std::map<std::string, ALE::Obj<ALE::Discretization> > sDiscs;

 97:   for(PETSC_MESH_TYPE::names_type::iterator f_iter = fields->begin(); f_iter != fields->end(); ++f_iter) {
 98:     const ALE::Obj<ALE::Discretization>& disc  = m->getDiscretization(*f_iter);
 99:     ALE::Obj<ALE::Discretization>        sDisc = new ALE::Discretization(disc->comm(), disc->debug());

101:     sDisc->setQuadratureSize(disc->getQuadratureSize());
102:     sDisc->setQuadraturePoints(disc->getQuadraturePoints());
103:     sDisc->setQuadratureWeights(disc->getQuadratureWeights());
104:     sDisc->setBasisSize(disc->getBasisSize());
105:     sDisc->setBasis(disc->getBasis());
106:     sDisc->setBasisDerivatives(disc->getBasisDerivatives());
107:     for(int d = 0; d <= m->getDimension(); ++d) {
108:       sDisc->setNumDof(d, disc->getNumDof(d));
109:       sDisc->setDofClass(d, disc->getDofClass(d));
110:     }
111:     if (disc->getBoundaryConditions()->size()) {
112:       if (fasDebug) {std::cout << "Adding BC for field " << *f_iter << std::endl;}
113:       ALE::Obj<ALE::BoundaryCondition> sBC = new ALE::BoundaryCondition(disc->comm(), disc->debug());
114:       sBC->setLabelName("marker");
115:       sBC->setMarker(1);
116:       sBC->setFunction(PETSC_NULL);
117:       sBC->setDualIntegrator(PETSC_NULL);
118:       sDisc->setBoundaryCondition(sBC);
119:     }
120:     sDiscs[*f_iter] = sDisc;
121:   }
122:   while(its--) {
123:     if (fasDebug) {PetscPrintf(dmmg[0]->comm, "    forward sweep %d\n", its);}
124:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
125:       // Loop over all cells
126:       //   This is an overlapping block SOR, but it is easier and seems more natural than doing each unknown
127:       for(PETSC_MESH_TYPE::label_sequence::iterator c_iter = cells->begin(); c_iter != cells->end(); ++c_iter) {
128:         ALE::Obj<PETSC_MESH_TYPE::sieve_type::supportSet> cellBlock  = sieve->nSupport(sieve->nCone(*c_iter, depth), depth);
129:         ALE::Obj<PETSC_MESH_TYPE>                         sm         = ALE::Selection<PETSC_MESH_TYPE>::submesh(m, cellBlock);
130:         ALE::Obj<PETSC_MESH_TYPE::real_section_type>      ssX        = sm->getRealSection("default");
131:         const ALE::Obj<PETSC_MESH_TYPE::label_type>&      cellMarker = sm->createLabel("marker");

133:         if (fasDebug) {PetscPrintf(dmmg[0]->comm, "    forward sweep cell %d\n", *c_iter);}
134:         SectionRealSetSection(cellX, ssX);
135:         // Assign BC to mesh
136:         for(PETSC_MESH_TYPE::sieve_type::supportSet::iterator b_iter = cellBlock->begin(); b_iter != cellBlock->end(); ++b_iter) {
137:           const ALE::Obj<PETSC_MESH_TYPE::coneArray> closure = ALE::SieveAlg<PETSC_MESH_TYPE>::closure(m, *b_iter);
138:           const PETSC_MESH_TYPE::coneArray::iterator end     = closure->end();
139:           const bool                           isCell  = *b_iter == *c_iter;

141:           for(PETSC_MESH_TYPE::coneArray::iterator cl_iter = closure->begin(); cl_iter != end; ++cl_iter) {
142:             if (isCell) {
143:               sm->setValue(cellMarker, *cl_iter, m->getValue(marker, *cl_iter));
144:             } else {
145:               if (sm->height(*cl_iter) == 0) {
146:                 sm->setValue(cellMarker, *cl_iter, 2);
147:               } else if (sm->getValue(cellMarker, *cl_iter, -1) < 0) {
148:                 sm->setValue(cellMarker, *cl_iter, 1);
149:               }
150:             }
151:           }
152:         }
153:         for(std::map<std::string, ALE::Obj<ALE::Discretization> >::iterator d_iter = sDiscs.begin(); d_iter != sDiscs.end(); ++d_iter) {
154:           sm->setDiscretization(d_iter->first, d_iter->second);
155:         }
156:         // Create field
157:         sm->setupField(ssX, 2, true);
158:         // Setup constant
159:         sm->setRealSection("constant", sB);
160:         // Setup DMMG
161:         DMMeshSetMesh(smallMesh, sm);
162:         DMMGSetDM(smallDmmg, smallMesh);
163:         DMMGSetSNESLocal(smallDmmg, func, jac, 0, 0);
164:         DMMGSetFromOptions(smallDmmg);
165:         // TODO: Construct null space, if necessary
166:         //DMMGSetNullSpace(smallDmmg, PETSC_FALSE, 1, CreateNullSpace);
167:         //ALE::Obj<PETSC_MESH_TYPE::real_section_type> nullSpace = sm->getRealSection("nullSpace");
168:         //sm->setupField(nullSpace, 2, true);
169:         // Fill in intial guess with BC values
170:         for(PETSC_MESH_TYPE::sieve_type::supportSet::iterator b_iter = cellBlock->begin(); b_iter != cellBlock->end(); ++b_iter) {
171:           sm->updateAll(ssX, *b_iter, m->restrictNew(sX, *b_iter));
172:         }
173:         if (fasDebug) {
174:           sX->view("Initial solution guess");
175:           ssX->view("Cell solution guess");
176:         }
177:         // Solve
178:         DMMGSolve(smallDmmg);
179:         // Update global solution with local solution
180:         SectionRealToVec(cellX, smallMesh, SCATTER_REVERSE, DMMGGetx(smallDmmg));
181:         m->updateAll(sX, *c_iter, sm->restrictNew(ssX, *c_iter));
182:         if (fasDebug) {
183:           ssX->view("Cell solution final");
184:           sX->view("Final solution");
185:         }
186:       }
187:     }
188:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
189:     }
190:   }
191: #endif
192:   sB->zero();
193:   SectionRealToVec(sectionX, mesh, SCATTER_FORWARD, X);
194:   SectionRealDestroy(&sectionX);
195:   SectionRealDestroy(&sectionB);
196:   SectionRealDestroy(&cellX);
197:   DMMGDestroy(smallDmmg);
198:   DMDestroy(&smallMesh);
199:   return(0);
200: }

203: #if 0
204: PetscErrorCode DMMGFormFunctionMesh(SNES snes, Vec X, Vec F, void *ptr);

206: /*
207:  This is alpha FAS code.

209:   R is the usual multigrid restriction (e.g. the tranpose of piecewise linear interpolation)
210:   Q is either a scaled injection or the usual R
211: */
214: PetscErrorCode DMMGSolveFAS_Mesh(DMMG *dmmg, PetscInt level)
215: {
216:   SNES           snes = dmmg[level]->snes;
217:   PetscReal      norm;
218:   PetscInt       i, j, k;
219:   PetscBool      fasDebug;

223:   PetscOptionsHasName(dmmg[0]->prefix, "-dmmg_fas_debug", &fasDebug);
224:   VecSet(dmmg[level]->r, 0.0);
225: /*   for(j = 1; j <= level; ++j) { */
226: /*     if (!dmmg[j]->inject) { */
227: /*       DMGetInjection(dmmg[j-1]->dm, dmmg[j]->dm, &dmmg[j]->inject); */
228: /*     } */
229: /*   } */

231:   for(i = 0, snes->iter = 1; i < 100; ++i, ++snes->iter) {
232:     PetscPrintf(dmmg[0]->comm, "FAS iteration %d\n", i);
233:     for(j = level; j > 0; j--) {
234:       if (dmmg[j]->monitorall) {PetscPrintf(dmmg[0]->comm, "  FAS level %d\n", j);}
235:       /* Relax on fine mesh to obtain x^{new}_{fine}, residual^{new}_{fine} = F_{fine}(x^{new}_{fine}) \approx 0 */
236:       Relax_Mesh(dmmg, dmmg[j]->dm, SOR_SYMMETRIC_SWEEP, dmmg[j]->presmooth, dmmg[j]->x, dmmg[j]->r);
237:       DMMGFormFunctionMesh(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);

239:       /* residual^{old}_fine} - residual^{new}_{fine} = F(x^{old}_{fine}) - residual^{new}_{fine} */
240:       VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);

242:       if (j == level || dmmg[j]->monitorall) {
243:         /* norm( residual_fine - f(x_fine) ) */
244:         VecNorm(dmmg[j]->w,NORM_2,&norm);
245:         if (dmmg[j]->monitorall) {
246:           for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm,"  ");}
247:           PetscPrintf(dmmg[j]->comm,"FAS lvl %d function norm %G\n",j,norm);
248:         }
249:         if (j == level) {
250:           if (norm < dmmg[level]->abstol) goto theend;
251:           if (i == 0) {
252:             dmmg[level]->rrtol = norm*dmmg[level]->rtol;
253:           } else {
254:             if (norm < dmmg[level]->rrtol) goto theend;
255:           }
256:         }
257:       }

259:       /* residual^{new}_{coarse} = R*(residual^{old}_fine} - residual^{new}_{fine}) */
260:       MatRestrict(dmmg[j]->R, dmmg[j]->w, dmmg[j-1]->r);

262:       /* F_{coarse}(R*x^{new}_{fine}) */
263:       MatRestrict(dmmg[j]->R, dmmg[j]->x, dmmg[j-1]->x);
264: /*       VecScatterBegin(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD); */
265: /*       VecScatterEnd(dmmg[j]->inject,dmmg[j]->x,dmmg[j-1]->x,INSERT_VALUES,SCATTER_FORWARD); */
266:       DMMGFormFunctionMesh(0,dmmg[j-1]->x,dmmg[j-1]->w,dmmg[j-1]);

268:       /* residual_coarse = F_{coarse}(R*x_{fine}) + R*(residual^{old}_fine} - residual^{new}_{fine}) */
269:       VecAYPX(dmmg[j-1]->r,1.0,dmmg[j-1]->w);

271:       /* save R*x^{new}_{fine} into b (needed when interpolating compute x back up) */
272:       VecCopy(dmmg[j-1]->x,dmmg[j-1]->b);
273:     }

275:     if (dmmg[0]->monitorall) {
276:       for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm,"  ");}
277:       PetscPrintf(dmmg[0]->comm, "FAS coarse grid\n");
278:     }
279:     if (level == 0) {
280:       DMMGFormFunctionMesh(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
281:       VecAYPX(dmmg[j]->w,-1.0,dmmg[j]->r);
282:       VecNorm(dmmg[0]->w,NORM_2,&norm);
283:       if (norm < dmmg[level]->abstol) goto theend;
284:       if (i == 0) {
285:         dmmg[level]->rrtol = norm*dmmg[level]->rtol;
286:       }
287:     }
288:     Relax_Mesh(dmmg, dmmg[0]->dm, SOR_SYMMETRIC_SWEEP, dmmg[0]->coarsesmooth, dmmg[0]->x, dmmg[0]->r);
289:     if (level == 0 || dmmg[0]->monitorall) {
290:       DMMGFormFunctionMesh(0,dmmg[0]->x,dmmg[0]->w,dmmg[0]);
291:       if (fasDebug) {
292:         SectionReal residual;

294:         DMMeshGetSectionReal(dmmg[0]->dm, "default", &residual);
295:         SectionRealView(residual, PETSC_VIEWER_STDOUT_WORLD);
296:         SectionRealDestroy(&residual);
297:       }
298:       VecAXPY(dmmg[0]->w,-1.0,dmmg[0]->r);
299:       VecNorm(dmmg[0]->w,NORM_2,&norm);
300:       for (k=0; k<level+1; k++) {PetscPrintf(dmmg[0]->comm,"  ");}
301:       PetscPrintf(dmmg[0]->comm,"FAS coarse grid function norm %G\n",norm);
302:       if (level == 0) {
303:         if (norm < dmmg[level]->abstol) goto theend;
304:         if (norm < dmmg[level]->rrtol)  goto theend;
305:       }
306:     }

308:     for (j=1; j<=level; j++) {
309:       PetscPrintf(dmmg[0]->comm, "  FAS level %d\n", j);
310:       /* x^{new}_{coarse} - R*x^{new}_{fine} */
311:       VecAXPY(dmmg[j-1]->x,-1.0,dmmg[j-1]->b);
312:       /* x_fine = x_fine + R'*(x^{new}_{coarse} - R*x^{new}_{fine}) */
313:       MatInterpolateAdd(dmmg[j]->R, dmmg[j-1]->x, dmmg[j]->x, dmmg[j]->x);

315:       if (dmmg[j]->monitorall) {
316:         /* norm( F(x_fine) - residual_fine ) */
317:         DMMGFormFunctionMesh(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
318:         VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
319:         VecNorm(dmmg[j]->w,NORM_2,&norm);
320:         for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm,"  ");}
321:         PetscPrintf(dmmg[j]->comm,"FAS lvl %d function norm before postsmooth %G\n",j,norm);
322:       }

324:       /* Relax residual_fine - F(x_fine)  = 0 */
325:       for (k=0; k<dmmg[j]->postsmooth; k++) {
326:         Relax_Mesh(dmmg, dmmg[j]->dm, SOR_SYMMETRIC_SWEEP, 1, dmmg[j]->x, dmmg[j]->r);
327:       }

329:       if ((j == level) || dmmg[j]->monitorall) {
330:         /* norm( F(x_fine) - residual_fine ) */
331:         DMMGFormFunctionMesh(0,dmmg[j]->x,dmmg[j]->w,dmmg[j]);
332:         VecAXPY(dmmg[j]->w,-1.0,dmmg[j]->r);
333:         VecNorm(dmmg[j]->w,NORM_2,&norm);
334:         for (k=0; k<level-j+1; k++) {PetscPrintf(dmmg[j]->comm,"  ");}
335:         PetscPrintf(dmmg[j]->comm,"FAS lvl %d function norm %G\n",j,norm);
336:         if (j == level) {
337:           if (norm < dmmg[level]->abstol) goto theend;
338:           if (norm < dmmg[level]->rrtol) goto theend;
339:         }
340:       }
341:     }

343:     if (dmmg[level]->monitor){
344:       DMMGFormFunctionMesh(0,dmmg[level]->x,dmmg[level]->w,dmmg[level]);
345:       VecNorm(dmmg[level]->w,NORM_2,&norm);
346:       PetscPrintf(dmmg[level]->comm,"%D FAS function norm %G\n",i+1,norm);
347:     }
348:   }
349:   theend:
350:   return(0);
351: }
352: #endif