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", §ionX);
79: SectionRealToVec(sectionX, mesh, SCATTER_REVERSE, X);
80: SectionRealGetSection(sectionX, sX);
81: DMMeshGetSectionReal(mesh, "constant", §ionB);
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(§ionX);
195: SectionRealDestroy(§ionB);
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