Actual source code: mlCheck.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: mlCheck.c,v 1.2 2000/01/10 03:20:33 knepley Exp $";
  3: #endif
  4: /*
  5:    Defines error checking routines for the multilevel preconditioner
  6: */
 7:  #include src/sles/pc/pcimpl.h
 8:  #include ml.h

 10: /*
 11:   PCValidQ_Multilevel - Validates the ML data structure

 13:   Collective on PC

 15:   Input Parameter:
 16: . pc - The PC

 18:   Level: advanced

 20: .keywords PC, Valid
 21: .seealso PCDebug_Multilevel()
 22: */
 23: int PCValidQ_Multilevel(PC pc)
 24: {
 25:   PC_Multilevel *ml = (PC_Multilevel *) pc->data;
 26:   int            numRows, numCols;
 27:   int            level, part;
 28:   int            ierr;

 31:   if (pc->setupcalled < 2)
 32:     PetscFunctionReturn(1);

 35:   /* Check dimensions */
 36:   if (ml->locB != PETSC_NULL) {
 37:     MatGetSize(ml->locB, &numRows, &numCols);
 38:     if ((ml->numRows != numRows) || (ml->numCols != numCols)) {
 39:       PetscLogInfo(pc, "PCValidQ_Multilevel: Invalid dimensions (%d,%d) for factorization", numRows, numCols);
 40:       PetscFunctionReturn(1);
 41:     }
 42:   }
 43:   if (ml->numLevels < 0) {
 44:     PetscLogInfo(pc, "PCValidQ_Multilevel: Invalid number of levels %d for factorization", ml->numLevels);
 45:     PetscFunctionReturn(1);
 46:   }
 47:   /* Check thresholds */
 48:   if (ml->QRthresh < 0) {
 49:     PetscLogInfo(pc, "PCValidQ_Multilevel: Invalid threshold %d for final QR factorization", ml->QRthresh);
 50:     PetscFunctionReturn(1);
 51:   }
 52:   if (ml->zeroTol < PETSC_MACHINE_EPSILON) {
 53:     PetscLogInfo(pc, "PCValidQ_Multilevel: Numeric tolerance %g less than machine epsilon", ml->zeroTol);
 54:     PetscFunctionReturn(1);
 55:   }

 57:   /* Check meshes */
 58:   if (ml->numMeshes != ml->numLevels + 1)
 59:     PetscLogInfo(pc, "PCValidQ_Multilevel: Invalid number %d of hierarchical meshes", ml->numMeshes);
 63:   for(level = 0; level <= ml->numLevels; level++) {
 68:   }

 70:   /* Bail out if no factorization was done */
 71:   if (ml->numLevels == 0)
 72:     return(0);

 74:   /* Check numbering */
 80:   for(level = 0; level < ml->numLevels; level++) {
 81:     if (ml->numPartitions[level] == 0)
 82:       continue;
 90:     if (ml->numPartitionRows[level][ml->numPartitions[level]] > 0)
 92:     if (ml->numPartitionRows[level][ml->numPartitions[level]+1] > 0)
 94:     for(part = 0; part < ml->numPartitions[level]; part++) {
 95:       if (ml->numPartitionCols[level][part] > 0)
 97:       if (ml->numPartitionRows[level][part] > 0)
 99:     }
100:   }

102:   /* Check factorization */
104:   for(level = 0; level < ml->numLevels; level++) {
105:     if (ml->numPartitions[level] == 0)
106:       continue;
108:     for(part = 0; part < ml->numPartitions[level]; part++) {
109:       numRows = ml->numPartitionRows[level][part];
110:       numCols = ml->numPartitionCols[level][part];
112:       if (numRows > 0) {
114:         if (PCMultiLevelDoQR_Private(pc, numRows, numCols) == PETSC_TRUE) {
117:         }
118:       }
119:       if (numCols > 0) {
122:       }
123:     }
124:   }

126:   /* Check boundary gradients */
133:   for(level = 0; level < ml->numLevels; level++) {
134:     if (ml->numPartitions[level] == 0)
135:       continue;
140:   }

142:   return(0);
143: }

145: int PCDebugPrintMat_Multilevel_Private(PC pc, VarOrdering rowOrder, VarOrdering colOrder, int (*applyM)(PC, GVec, GVec))
146: {
147:   PC_Multilevel *ml   = (PC_Multilevel *) pc->data;
148:   Grid           grid = ml->grid;
149:   PetscScalar    zero = 0.0;
150:   GVec           rowVec,    colVec;
151:   PetscScalar   *rowArray, *colArray;
152:   int            rank;
153:   int            tempLevels, colVars, locRowVars;
154:   int           *firstCol;
155:   int            row, col;
156:   PetscTruth     opt;
157:   int            ierr;

160:   /* Setup storage */
161:   MPI_Comm_rank(pc->comm, &rank);
162:   GVecCreateRectangular(grid, rowOrder, &rowVec);
163:   GVecCreateRectangular(grid, colOrder, &colVec);
164:   VecGetArray(rowVec, &rowArray);
165:   VecGetArray(colVec, &colArray);

167:   /* Allow only the first k levels to be used */
168:   tempLevels = ml->numLevels;
169:   PetscOptionsGetInt(pc->prefix, "-pc_ml_debug_level", &tempLevels, &opt);

171:   /* Print out the matrix M */
172:   VarOrderingGetSize(colOrder, &colVars);
173:   VarOrderingGetLocalSize(rowOrder, &locRowVars);
174:   VarOrderingGetFirst(colOrder, &firstCol);
175:   for(col = 0; col < colVars; col++)
176:   {
177:     /* Start with e_col */
178:     VecSet(&zero, colVec);
179:     if ((col >= firstCol[rank]) && (col < firstCol[rank+1]))
180:       colArray[col-firstCol[rank]] = 1.0;
181:     /* M_col = M e_col */
182:     (*applyM)(pc, colVec, rowVec);
183:     /* Print out as a row so we get the transpose */
184:     for(row = 0; row < locRowVars; row++)
185:       PetscSynchronizedPrintf(pc->comm, "%g ", rowArray[row]);
186:     PetscSynchronizedFlush(pc->comm);
187:     PetscPrintf(pc->comm, "n");
188:   }

190:   /* Cleanup stroage */
191:   VecRestoreArray(rowVec, &rowArray);
192:   VecRestoreArray(colVec, &colArray);
193:   GVecDestroy(rowVec);
194:   GVecDestroy(colVec);
195:   return(0);
196: }

198: /*
199:   PCDebugPrintMat_Multilevel - Prints out the dense form of the level matrices.

201:   Collective on PC

203:   Input Parameter:
204: . pc - The PC

206:   Level: advanced

208: .keywords PC, debug
209: .seealso PCDebug_Multilevel()
210: */
211: int PCDebugPrintMat_Multilevel(PC pc, const char mat[])
212: {
213:   PC_Multilevel *ml = (PC_Multilevel *) pc->data;
214:   PetscTruth     isP, isB, isV, isD, isall;
215:   int            ierr;

218:   PetscStrcasecmp(mat, "P",   &isP);
219:   PetscStrcasecmp(mat, "B",   &isB);
220:   PetscStrcasecmp(mat, "V",   &isV);
221:   PetscStrcasecmp(mat, "D",   &isD);
222:   PetscStrcasecmp(mat, "all", &isall);
223:   if (isP == PETSC_TRUE) {
224:     PetscPrintf(pc->comm, "P^Tn");
225:     PCDebugPrintMat_Multilevel_Private(pc, ml->tOrder, ml->tOrder, PCMultiLevelApplyP);
226:   } else if (isB == PETSC_TRUE) {
227:     PetscPrintf(pc->comm, "B^Tn");
228:     PCDebugPrintMat_Multilevel_Private(pc, ml->tOrder, ml->sOrder, PCMultiLevelApplyGradient);
229:   } else if (isV == PETSC_TRUE) {
230:     PetscPrintf(PETSC_COMM_WORLD, "V^Tn");
231:     PCDebugPrintMat_Multilevel_Private(pc, ml->sOrder, ml->sOrder, PCMultiLevelApplyV);
232:   } else if (isD == PETSC_TRUE) {
233:     PetscPrintf(PETSC_COMM_WORLD, "D^{-T}n");
234:     PCDebugPrintMat_Multilevel_Private(pc, ml->sOrder, ml->sOrder, PCMultiLevelApplyDInv);
235:   } else if (isall == PETSC_TRUE) {
236:     PCDebugPrintMat_Multilevel_Private(pc, ml->tOrder, ml->tOrder, PCMultiLevelApplyP);
237:     PCDebugPrintMat_Multilevel_Private(pc, ml->tOrder, ml->sOrder, PCMultiLevelApplyGradient);
238:     PCDebugPrintMat_Multilevel_Private(pc, ml->sOrder, ml->sOrder, PCMultiLevelApplyV);
239:     PCDebugPrintMat_Multilevel_Private(pc, ml->sOrder, ml->sOrder, PCMultiLevelApplyDInv);
240:   } else {
241:     SETERRQ1(PETSC_ERR_ARG_WRONG, "Unknown ML level matrix %s.", mat);
242:   }
243:   return(0);
244: }

246: int PCDebug_Multilevel(PC pc)
247: {
248:   PC_Multilevel       *ml   = (PC_Multilevel *) pc->data;
249:   Grid                 grid = ml->grid;
250:   PetscScalar          zero = 0.0;
251:   GVec                 testVec,    testVec2,    testVec3;
252:   PetscScalar         *testArray, *testArray2, *testArray3;
253:   GVec                 singVec;
254:   PetscScalar         *singArray;
255:   PetscScalar          norm;
256:   char                 printMat[256];
257:   int                  rank;
258:   int                  range;
259:   int                  rowVars, colVars, locColVars;
260:   int                 *firstRow, *firstCol;
261:   int                  singCount,    singRow;
262:   int                  locSingCount, locSingRow;
263:   int                  row, col, locCol;
264:   PetscTruth           opt;
265:   int                  ierr;

268:   /* Initialize testing */
269:   MPI_Comm_rank(pc->comm, &rank);
270:   GVecCreateRectangular(grid, ml->sOrder, &testVec);
271:   GVecDuplicate(testVec, &singVec);
272:   GVecCreateConstrained(grid, &testVec2);
273:   GVecCreateConstrained(grid, &testVec3);
274:   VecGetArray(testVec,  &testArray);
275:   VecGetArray(testVec2, &testArray2);
276:   VecGetArray(testVec3, &testArray3);
277:   VecGetArray(singVec,  &singArray);

279:   /* Print matrices */
280:   PetscOptionsGetString(pc->prefix, "-pc_ml_print_mat", printMat, 255, &opt);
281:   if (opt == PETSC_TRUE) {
282:     PCDebugPrintMat_Multilevel(pc, printMat);
283:   }

285:   VarOrderingGetSize(ml->tOrder, &rowVars);
286:   VarOrderingGetSize(ml->sOrder, &colVars);
287:   VarOrderingGetLocalSize(ml->sOrder, &locColVars);
288:   VarOrderingGetFirst(ml->tOrder, &firstRow);
289:   VarOrderingGetFirst(ml->sOrder, &firstCol);

291:   /* Check that B^T P = 0 for numNullSpace rows */
292:   for(row = 0, range = 0; row < rowVars; row++)
293:   {
294:     /* Start with e_row */
295:     VecSet(&zero, testVec2);
296:     if ((row >= firstRow[rank]) && (row < firstRow[rank+1]))
297:       testArray2[row-firstRow[rank]] = 1.0;
298:     /* P e_row */
299:     PCMultiLevelApplyP(pc, testVec2, testVec2);
300:     /* B^T P e_row */
301:     PCMultiLevelApplyGradientTrans(pc, testVec2, testVec);
302:     /* Check for nonzeros only in the range */
303:     VecNorm(testVec, NORM_2, &norm);
304:     if (norm > ml->zeroTol)
305:       range++;
306:   }
307:   if (range != ml->globalRank) {
308:     PetscLogInfo(pc, "PCDebug_Multilevel: P_2 is not a null space for B^T, %d != %d range vectorsn", range, ml->globalRank);
309:     PetscFunctionReturn(1);
310:   }

312:   /* Test to see that D^{-1} P^T_1 B Z = I */
313:   for(col = 0; col < colVars; col++)
314:   {
315:     /* Start with e_col */
316:     locCol = col - firstCol[rank];
317:     VecSet(&zero, testVec);
318:     if ((col >= firstCol[rank]) && (col < firstCol[rank+1]))
319:       testArray[locCol] = 1.0;

321:     /* Z e_col */
322:     PCMultiLevelApplyV(pc, testVec, testVec);
323:     /* B Z e_col */
324:     PCMultiLevelApplyGradient(pc, testVec, testVec2);
325:     /* P^T B Z e_col */
326:     PCMultiLevelApplyPTrans(pc, testVec2, testVec2);
327:     /* Scatter to a column vector */
328:     VecScatterBegin(testVec2, testVec, INSERT_VALUES, SCATTER_FORWARD, ml->rangeScatter);
329:     VecScatterEnd(testVec2, testVec, INSERT_VALUES, SCATTER_FORWARD, ml->rangeScatter);
330:     /* D^{-1} P^T B Z e_col */
331:     PCMultiLevelApplyDInv(pc, testVec, testVec);
332:     /* Check the row */
333:     for(row = 0, locSingCount = 0, locSingRow = -1; row < locColVars; row++)
334:       if (testArray[row] > ml->zeroTol) {
335:         locSingCount++;
336:         locSingRow = row;
337:       }
338:     MPI_Allreduce(&locSingCount, &singCount, 1, MPI_INT, MPI_SUM, pc->comm);
339:     MPI_Allreduce(&locSingRow,   &singRow,   1, MPI_INT, MPI_MAX, pc->comm);
340:     if (singCount > 1) {
341:       PetscLogInfo(pc, "PCDebug_Multilevel: Invalid column %d in P^T B Z, %d nonzerosn", col, singCount);
342:       PetscFunctionReturn(1);
343:     } else if (singCount == 0) {
344:       PetscLogInfo(pc, "PCDebug_Multilevel: B is rank deficient in column %dn", col);
345:     }
346:     /* Check the singular value */
347:     if (locSingRow > -1)
348:     {
349:       singRow += firstCol[rank];
350:       if (singRow != col) {
351:         PetscLogInfo(pc, "PCDebug_Multilevel: Invalid ordering in P^T B Z, value in column %d and row %dn", col, singRow);
352:         PetscFunctionReturn(1);
353:       }
354:       if (PetscAbsScalar(testArray[locSingRow] - 1.0) > ml->zeroTol) {
355:         PetscLogInfo(pc, "PCDebug_Multilevel: Invalid singular value in column %dn", col);
356:         PetscFunctionReturn(1);
357:       }
358:     }
359:   }

361:   /* Cleanup testing */
362:   VecRestoreArray(testVec,  &testArray);
363:   VecRestoreArray(testVec2, &testArray2);
364:   VecRestoreArray(testVec3, &testArray3);
365:   VecRestoreArray(singVec,  &singArray);
366:   GVecDestroy(testVec);
367:   GVecDestroy(testVec2);
368:   GVecDestroy(testVec3);
369:   GVecDestroy(singVec);

371:   return(0);
372: }