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