Actual source code: fieldClassMap2d.c

  1: #ifdef PETSC_RCS_HEADER
  2: static char vcid[] = "$Id: fieldClassMap2d.c,v 1.6 2000/01/30 18:30:46 huangp Exp $";
  3: #endif

  5: #include "src/grid/gridimpl.h"         /*I "grid.h" I*/
  6: #include "fieldClassMap2d.h"

  8: /*---------------------------------------- Creation and Destruction Functions ---------------------------------------*/
  9: /*@C
 10:   FieldClassMapCreateTriangular2D - This function creates a class map for the given grid.

 12:   Collective on Grid

 14:   Input Parameters:
 15: + grid      - The underlying grid for the ordering
 16: . numFields - The number of fields in the ordering
 17: - fields    - The fields in the ordering

 19:   Output Parameter:
 20: . map       - The map

 22:   Level: beginner

 24: .keywords: class, field class, class map, create
 25: .seealso: FieldClassMapCreate(), FieldClassMapDestroy()
 26: @*/
 27: int FieldClassMapCreateTriangular2D(Grid grid, int numFields, int *fields, FieldClassMap *map)
 28: {
 29:   MPI_Comm      comm;
 30:   ParameterDict dict;
 31:   int           numTotalFields, f;
 32:   int           ierr;

 35:   GridGetNumFields(grid, &numTotalFields);
 36:   if (numFields > numTotalFields) {
 37:     SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid number  %d of fields, grid only has %d", numFields, numTotalFields);
 38:   }
 39:   for(f = 0; f < numFields; f++) {
 40:     if ((fields[f] < 0) || (fields[f] >= numTotalFields)) {
 41:       SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid field number %d", fields[f]);
 42:     }
 43:   }
 44:   PetscObjectGetComm((PetscObject) grid, &comm);
 45:   FieldClassMapCreate(comm, map);
 46:   PetscObjectGetComm((PetscObject) grid, &comm);
 47:   ParameterDictCreate(comm, &dict);
 48:   ParameterDictSetInteger(dict, "numFields", numFields);
 49:   ParameterDictSetObject(dict,  "fields",    fields);
 50:   ParameterDictSetObject(dict,  "grid",      grid);
 51:   PetscObjectSetParameterDict((PetscObject) *map, dict);
 52:   ParameterDictDestroy(dict);
 53:   FieldClassMapSetType(*map, CLASS_MAP_TRIANGULAR_2D);
 54:   return(0);
 55: }

 57: int FieldClassMapDestroy_Triangular_2D(FieldClassMap map)
 58: {
 60:   return(0);
 61: }

 63: int FieldClassMapConstrain_Triangular_2D(FieldClassMap map, Grid grid, PetscTruth useBC, PetscTruth useConst,
 64:                                          FieldClassMap *newMap)
 65: {
 66:   FieldClassMap cm;
 67:   Mesh          mesh;
 68:   Partition     part;
 69:   int           numBd              = grid->numBd;
 70:   int           numBC              = grid->numBC;
 71:   GridBC       *gBC                = grid->bc;
 72:   int           numPointBC         = grid->numPointBC;
 73:   GridBC       *pBC                = grid->pointBC;
 74:   int           numFields          = map->numFields;
 75:   int          *fields             = map->fields;
 76:   int           numNodes           = map->numNodes;
 77:   int           numOverlapNodes    = map->numOverlapNodes;
 78:   int           numClasses         = map->numClasses;
 79:   int          *classes            = map->classes;
 80:   int        ***localClassMap, ***classMap;
 81:   PetscTruth    isConst;
 82:   int           f, g, field, comp, node, bd, oldBd, bc, marker, nclass, newNClass, oldNClass;
 83:   int           ierr;

 86:   FieldClassMapCreate(map->comm, &cm);
 87:   PetscMemcpy(cm->ops, map->ops, sizeof(FieldClassMapOps));
 88:   PetscStrallocpy(map->serialize_name, &cm->serialize_name);

 90:   GridGetMesh(grid, &mesh);
 91:   cm->numFields       = numFields;
 92:   cm->numNodes        = numNodes;
 93:   cm->numOverlapNodes = numOverlapNodes;
 94:   cm->numGhostNodes   = cm->numOverlapNodes - cm->numNodes;
 95:   PetscMalloc(numFields * sizeof(int), &cm->fields);
 96:   PetscMemcpy(cm->fields, fields, numFields * sizeof(int));
 97:   /*
 98:     classMap[numBd+numPointBC+1][numClasses][numFields]:

100:     The classMap[][][] structure is organized as follows. For every boundary, we determine the classes which are
101:     present on that boundary. For each class, we create a new class which does not contain the constrained fields.
102:     The classMap[][][] structure has for each boundary

104:       flag_0, flag_1, ldots, flag_numFields-1
105:       flag_0, flag_1, ldots, flag_numFields-1
106:       ...
107:       flag_0, flag_1, ldots, flag_numFields-1

109:     where a positive flag indicates that the field is constrained in that class, and a zero indicates no change.
110:     Point boundary conditions are treated like additional boundaries, and since we only allow one constraint,
111:     the last position is used for the constraint.
112:   */
113:   cm->mapSize       = numBd + numPointBC + 1;
114:   cm->numOldClasses = numClasses;
115:   PetscMalloc(cm->mapSize * sizeof(int **), &localClassMap);
116:   PetscMalloc(cm->mapSize * sizeof(int **), &classMap);
117:   for(bd = 0; bd < cm->mapSize; bd++) {
118:     PetscMalloc(numClasses * sizeof(int *), &localClassMap[bd]);
119:     PetscMalloc(numClasses * sizeof(int *), &classMap[bd]);
120:     for(nclass = 0; nclass < numClasses; nclass++) {
121:       PetscMalloc(numFields * sizeof(int), &localClassMap[bd][nclass]);
122:       PetscMalloc(numFields * sizeof(int), &classMap[bd][nclass]);
123:       PetscMemzero(localClassMap[bd][nclass], numFields * sizeof(int));
124:       PetscMemzero(classMap[bd][nclass],      numFields * sizeof(int));
125:     }
126:   }
127:   /* Mark constrained classes for reassignment */
128:   for(node = 0; node < numNodes; node++) {
129:     MeshGetNodeBoundary(mesh, node, &marker);
130:     if (marker == 0)
131:       continue;
132:     nclass = classes[node];
133:     if ((useConst == PETSC_TRUE) && (marker < 0)) {
134:       /* All constrained nodes have negative markers */
135:       for(f = 0; f < numFields; f++) {
136:         field = fields[f];
137:         if (grid->fields[field].isConstrained == PETSC_TRUE) {
138:           localClassMap[cm->mapSize-1][nclass][f] = 1;
139:         }
140:       }
141:     } else if ((useBC == PETSC_TRUE) && (marker > 0)) {
142:       for(bc = 0; bc < numBC; bc++) {
143:         if (gBC[bc].reduce == PETSC_FALSE) continue;
144:         if (gBC[bc].boundary == marker) {
145:           MeshGetBoundaryIndex(mesh, marker, &bd);
146:           for(f = 0; f < numFields; f++) {
147:             if (fields[f] == gBC[bc].field) {
148:               localClassMap[bd][nclass][f] = 1;
149:               break;
150:             }
151:           }
152:         }
153:       }
154:       for(bc = 0; bc < numPointBC; bc++) {
155:         if (pBC[bc].reduce == PETSC_FALSE) continue;
156:         if (pBC[bc].node == node) {
157:           for(f = 0; f < numFields; f++) {
158:             if (fields[f] == pBC[bc].field) {
159:               localClassMap[numBd+bc][nclass][f] = 1;
160:               break;
161:             }
162:           }
163:         }
164:       }
165:     }
166:   }
167:   /* Synchronize localClassMap */
168:   for(bd = 0; bd < cm->mapSize; bd++) {
169:     for(nclass = 0; nclass < numClasses; nclass++) {
170:       MPI_Allreduce(localClassMap[bd][nclass], classMap[bd][nclass], numFields, MPI_INT, MPI_LOR, cm->comm);
171: 
172:     }
173:   }
174:   /* Assign new classes */
175:   PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap);
176:   for(bd = 0; bd < cm->mapSize; bd++) {
177:     PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]);
178:     for(nclass = 0; nclass < numClasses; nclass++) {
179:       cm->classMap[bd][nclass] = nclass;
180:     }
181:   }
182:   for(bd = 0, cm->numClasses = numClasses; bd < cm->mapSize; bd++) {
183:     for(nclass = 0; nclass < numClasses; nclass++) {
184:       for(f = 0, isConst = PETSC_FALSE; f < numFields; f++) {
185:         if (classMap[bd][nclass][f] != 0) {
186:           isConst = PETSC_TRUE;
187:           field   = fields[f];
188:           /* Map old classes to new with the condition which created it for a given field */
189:           classMap[bd][nclass][f] = cm->numClasses;
190:           /* Check that field should be constrained */
191:           if ((bd == cm->mapSize-1) && (grid->fields[field].isConstrained == PETSC_FALSE)) {
192:             SETERRQ1(PETSC_ERR_PLIB, "Invalid constrained field %d", field);
193:           }
194:           /* Must include previous constraints on the node */
195:           for(g = 0; g < numFields; g++) {
196:             for(oldBd = 0; oldBd < bd; oldBd++) {
197:               for(oldNClass = 0; oldNClass < numClasses; oldNClass++) {
198:                 if (classMap[oldBd][oldNClass][g] != 0) {
199:                   classMap[bd][nclass][g] = cm->numClasses;
200:                   break;
201:                 }
202:               }
203:             }
204:           }
205:           break;
206:         }
207:       }
208:       /* Create a new class */
209:       if (isConst == PETSC_TRUE) {
210:         cm->classMap[bd][nclass] = cm->numClasses++;
211:       }
212:     }
213:   }
214:   /* Set new classes on nodes */
215:   PetscMalloc(numOverlapNodes * sizeof(int), &cm->classes);
216:   PetscMemcpy(cm->classes, classes, numOverlapNodes * sizeof(int));
217:   for(node = 0; node < numOverlapNodes; node++) {
218:     MeshGetNodeBoundary(mesh, node, &marker);
219:     if (marker == 0)
220:       continue;
221:     nclass = classes[node];
222:     if (marker < 0) {
223:       cm->classes[node] = cm->classMap[cm->mapSize-1][nclass];
224:     } else {
225:       for(bc = 0; bc < numBC; bc++) {
226:         if (gBC[bc].reduce == PETSC_FALSE) continue;
227:         if (gBC[bc].boundary == marker) {
228:           MeshGetBoundaryIndex(mesh, marker, &bd);
229:           if (cm->classMap[bd][nclass] != nclass) {
230:             cm->classes[node] = cm->classMap[bd][nclass];
231:           }
232:         }
233:       }
234:       /* Notice that point BC must come last since these nodes may lie on a boundary which was also constrained */
235:       for(bc = 0; bc < numPointBC; bc++) {
236:         if (pBC[bc].reduce == PETSC_FALSE) continue;
237:         if (pBC[bc].node == node) {
238:           if (cm->classMap[numBd+bc][nclass] != nclass) {
239:             cm->classes[node] = cm->classMap[numBd+bc][nclass];
240:           }
241:         }
242:       }
243:     }
244:   }
245:   /* Calculate new class structure */
246:   cm->isReduced          = map->isReduced;
247:   cm->isConstrained      = map->isConstrained;
248:   PetscMalloc(numFields      * sizeof(int *), &cm->fieldClasses);
249:   PetscMalloc(numFields      * sizeof(int *), &cm->reduceFieldClasses);
250:   PetscMalloc(cm->numClasses * sizeof(int),   &cm->classSizes);
251:   PetscMalloc(cm->numClasses * sizeof(int),   &cm->isClassConstrained);
252:   PetscMalloc(cm->numClasses * sizeof(int),   &cm->classSizeDiffs);
253:   PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int));
254:   PetscMemzero(cm->classSizeDiffs,     cm->numClasses * sizeof(int));
255:   /* Copy old structure */
256:   for(nclass = 0; nclass < numClasses; nclass++) {
257:     cm->classSizes[nclass]         = map->classSizes[nclass];
258:     cm->isClassConstrained[nclass] = map->isClassConstrained[nclass];
259:     cm->classSizeDiffs[nclass]     = map->classSizeDiffs[nclass];
260:   }
261:   for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) {
262:     /* Invert the class map */
263:     for(bd = 0; bd < cm->mapSize; bd++) {
264:       for(nclass = 0; nclass < numClasses; nclass++)
265:         if (cm->classMap[bd][nclass] == newNClass)
266:           break;
267:       if (nclass < numClasses)
268:         break;
269:     }
270:     if ((nclass >= numClasses) || (bd >= cm->mapSize)) {
271:       SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass);
272:     }

274:     cm->classSizes[newNClass]     = map->classSizes[nclass];
275:     cm->classSizeDiffs[newNClass] = map->classSizeDiffs[nclass];
276:   }
277:   /* Apply constraints */
278:   for(f = 0; f < numFields; f++) {
279:     PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]);
280:     PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]);
281:     PetscMemzero(cm->reduceFieldClasses[f], cm->numClasses * sizeof(int));
282:     /* Copy old structure */
283:     for(nclass = 0; nclass < numClasses; nclass++) {
284:       cm->fieldClasses[f][nclass]         = map->fieldClasses[f][nclass];
285:       if (map->reduceFieldClasses) {
286:         cm->reduceFieldClasses[f][nclass] = map->reduceFieldClasses[f][nclass];
287:       }
288:     }

290:     /* Remove constrained fields from new classes */
291:     for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) {
292:       /* Invert the class map */
293:       for(bd = 0; bd < cm->mapSize; bd++) {
294:         for(nclass = 0; nclass < numClasses; nclass++)
295:           if (cm->classMap[bd][nclass] == newNClass)
296:             break;
297:         if (nclass < numClasses)
298:           break;
299:       }
300:       if ((nclass >= numClasses) || (bd >= cm->mapSize)) {
301:         SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass);
302:       }
303:       /* Check every BC for constraints on this field/class */
304:       cm->fieldClasses[f][newNClass]             = map->fieldClasses[f][nclass];
305:       for(bd = 0; bd < cm->mapSize; bd++) {
306:         if (classMap[bd][nclass][f] == newNClass) {
307:           /* New classes can be redefined by another BC to be a higher number, but do not
308:              operate on the existing new class with that BC (hence the second check) */
309:           if (cm->classMap[bd][nclass] != newNClass) {
310:             SETERRQ3(PETSC_ERR_PLIB, "Invalid bc %d constraining class %d to %d", bd, nclass, newNClass);
311:           }
312:           /* If the field is constrained, it has no values on these nodes */
313:           cm->fieldClasses[f][newNClass]         = 0;
314:           if (bd < cm->mapSize-1) {
315:             cm->isReduced                        = PETSC_TRUE;
316:             cm->reduceFieldClasses[f][newNClass] = 1;
317:           }
318:           /* Subtract the degrees of freedom of the constrained field for each BC */
319:           GridGetFieldComponents(grid, fields[f], &comp);
320:           cm->classSizes[newNClass]             -= comp;
321:           if (cm->classSizes[newNClass] < 0) {
322:             SETERRQ2(PETSC_ERR_PLIB, "Invalid size for class %d (derived from class %d)", newNClass, nclass);
323:           }
324:           /* Handle user constraints separately from BC */
325:           if (bd == cm->mapSize-1) {
326:             cm->isConstrained                    = PETSC_TRUE;
327:             /* This class is constrained */
328:             cm->isClassConstrained[newNClass]    = 1;
329:             /* There are this many components in the new field */
330:             cm->classSizeDiffs[newNClass]       += grid->fields[fields[f]].constraintCompDiff + comp;
331:           }
332:         }
333:       }
334:     }
335:   }

337:   /* Cleanup */
338:   if (cm->isReduced == PETSC_FALSE) {
339:     for(f = 0; f < map->numFields; f++) {
340:       PetscFree(cm->reduceFieldClasses[f]);
341:     }
342:     PetscFree(cm->reduceFieldClasses);
343:   }
344:   for(bd = 0; bd < cm->mapSize; bd++) {
345:     for(nclass = 0; nclass < numClasses; nclass++) {
346:       PetscFree(localClassMap[bd][nclass]);
347:       PetscFree(classMap[bd][nclass]);
348:     }
349:     PetscFree(localClassMap[bd]);
350:     PetscFree(classMap[bd]);
351:   }
352:   PetscFree(localClassMap);
353:   PetscFree(classMap);

355:   /* Communicate ghost classes */
356:   MeshGetPartition(mesh, &part);
357:   PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]);
358: 

360:   PetscLogObjectMemory(cm, (cm->mapSize + numFields*2) * sizeof(int *) + (numFields + cm->numOldClasses*cm->mapSize +
361:                        cm->numClasses*(numFields*2 + 3) + numOverlapNodes) * sizeof(int));
362:   *newMap = cm;
363:   return(0);
364: }

366: int FieldClassMapReduce_Triangular_2D(FieldClassMap map, Grid grid, FieldClassMap *newMap) {
367:   FieldClassMap cm;
368:   Mesh          mesh;
369:   Partition     part;
370:   int           numBd              = grid->numBd;
371:   int           numBC              = grid->numBC;
372:   GridBC       *gBC                = grid->bc;
373:   int           numPointBC         = grid->numPointBC;
374:   GridBC       *pBC                = grid->pointBC;
375:   int           numFields          = map->numFields;
376:   int          *fields             = map->fields;
377:   int           numNodes           = map->numNodes;
378:   int           numOverlapNodes    = map->numOverlapNodes;
379:   int           numClasses         = map->numClasses;
380:   int          *classes            = map->classes;
381:   int        ***localClassMap, ***classMap;
382:   PetscTruth    isConst;
383:   int           f, g, field, comp, node, bd, bc, marker, nclass, newNClass;
384:   int           ierr;

387:   FieldClassMapCreate(map->comm, &cm);
388:   PetscMemcpy(cm->ops, map->ops, sizeof(FieldClassMapOps));
389:   PetscStrallocpy(map->serialize_name, &cm->serialize_name);

391:   GridGetMesh(grid, &mesh);
392:   cm->numNodes        = numNodes;
393:   cm->numOverlapNodes = numOverlapNodes;
394:   cm->numGhostNodes   = cm->numOverlapNodes - cm->numNodes;
395:   PetscMalloc(numFields * sizeof(int), &cm->fields);
396:   /*
397:     classMap[numBd+numPointBC][numClasses][numFields]:

399:     The classMap[][][] structure is organized as follows. For every boundary, we determine the classes which are
400:     present on that boundary. For each class, we create a new class which does not contain the constrained fields.
401:     The classMap[][][] structure has for each boundary

403:       flag_0, flag_1, ldots, flag_numFields-1
404:       flag_0, flag_1, ldots, flag_numFields-1
405:       ...
406:       flag_0, flag_1, ldots, flag_numFields-1

408:     where a positive flag indicates that the field is constrained in that class, and a zero indicates no change.
409:     Point boundary conditions are treated like additional boundaries.
410:   */
411:   cm->mapSize       = numBd + numPointBC;
412:   cm->numOldClasses = numClasses;
413:   PetscMalloc(cm->mapSize * sizeof(int **), &localClassMap);
414:   PetscMalloc(cm->mapSize * sizeof(int **), &classMap);
415:   for(bd = 0; bd < cm->mapSize; bd++) {
416:     PetscMalloc(numClasses * sizeof(int *), &localClassMap[bd]);
417:     PetscMalloc(numClasses * sizeof(int *), &classMap[bd]);
418:     for(nclass = 0; nclass < numClasses; nclass++) {
419:       PetscMalloc(numFields * sizeof(int), &localClassMap[bd][nclass]);
420:       PetscMalloc(numFields * sizeof(int), &classMap[bd][nclass]);
421:       PetscMemzero(localClassMap[bd][nclass], numFields * sizeof(int));
422:       PetscMemzero(classMap[bd][nclass],      numFields * sizeof(int));
423:     }
424:   }
425:   /* Mark constrained classes for reassignment */
426:   for(node = 0; node < numNodes; node++) {
427:     MeshGetNodeBoundary(mesh, node, &marker);
428:     if (marker == 0)
429:       continue;
430:     nclass = classes[node];
431:     if (marker > 0) {
432:       for(bc = 0; bc < numBC; bc++) {
433:         if (gBC[bc].reduce == PETSC_FALSE)
434:           continue;
435:         if (gBC[bc].boundary == marker) {
436:           MeshGetBoundaryIndex(mesh, marker, &bd);
437:           for(f = 0; f < numFields; f++) {
438:             if (fields[f] == gBC[bc].field) {
439:               localClassMap[bd][nclass][f] = 1;
440:               break;
441:             }
442:           }
443:         }
444:       }
445:       for(bc = 0; bc < numPointBC; bc++) {
446:         if (pBC[bc].reduce == PETSC_FALSE) continue;
447:         if (pBC[bc].node == node) {
448:           for(f = 0; f < numFields; f++) {
449:             if (fields[f] == pBC[bc].field) {
450:               localClassMap[numBd+bc][nclass][f] = 1;
451:               break;
452:             }
453:           }
454:         }
455:       }
456:     }
457:   }
458:   /* Synchronize localClassMap */
459:   for(bd = 0; bd < cm->mapSize; bd++) {
460:     for(nclass = 0; nclass < numClasses; nclass++) {
461:       MPI_Allreduce(localClassMap[bd][nclass], classMap[bd][nclass], numFields, MPI_INT, MPI_LOR, cm->comm);
462: 
463:     }
464:   }

466:   /* Assign new classes and build field list */
467:   PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap);
468:   for(bd = 0; bd < cm->mapSize; bd++) {
469:     PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]);
470:     for(nclass = 0; nclass < numClasses; nclass++) {
471:       cm->classMap[bd][nclass] = nclass;
472:     }
473:   }
474:   cm->numFields = 0;
475:   for(bd = 0, cm->numClasses = numClasses; bd < cm->mapSize; bd++) {
476:     for(nclass = 0; nclass < numClasses; nclass++) {
477:       for(f = 0, isConst = PETSC_FALSE; f < numFields; f++) {
478:         if (classMap[bd][nclass][f] != 0) {
479:           isConst = PETSC_TRUE;
480:           field   = fields[f];
481:           /* Add to list of reduced fields */
482:           for(g = 0; g < cm->numFields; g++)
483:             if (field == cm->fields[g])
484:               break;
485:           if (g == cm->numFields)
486:             cm->fields[cm->numFields++] = field;
487:         }
488:       }
489:       /* Create a new class */
490:       if (isConst == PETSC_TRUE) {
491:         cm->classMap[bd][nclass] = cm->numClasses++;
492:       }
493:     }
494:   }

496:   /* Set new classes on nodes */
497:   PetscMalloc(numOverlapNodes * sizeof(int), &cm->classes);
498:   PetscMemcpy(cm->classes, classes, numOverlapNodes * sizeof(int));
499:   for(node = 0; node < numOverlapNodes; node++) {
500:     MeshGetNodeBoundary(mesh, node, &marker);
501:     if (marker == 0)
502:       continue;
503:     nclass = classes[node];
504:     for(bc = 0; bc < numBC; bc++) {
505:       if (gBC[bc].reduce == PETSC_FALSE) continue;
506:       if (gBC[bc].boundary == marker) {
507:         MeshGetBoundaryIndex(mesh, marker, &bd);
508:         cm->classes[node] = cm->classMap[bd][nclass];
509:       }
510:     }
511:     /* Notice that point BC must come last since these nodes may lie on a boundary which was also constrained */
512:     for(bc = 0; bc < numPointBC; bc++) {
513:       if (pBC[bc].reduce == PETSC_FALSE) continue;
514:       if (pBC[bc].node == node) {
515:         cm->classes[node] = cm->classMap[numBd+bc][nclass];
516:       }
517:     }
518:   }
519:   /* Calculate new class structure */
520:   cm->isReduced          = PETSC_TRUE;
521:   cm->isConstrained      = map->isConstrained;
522:   PetscMalloc(cm->numFields  * sizeof(int *), &cm->fieldClasses);
523:   PetscMalloc(cm->numFields  * sizeof(int *), &cm->reduceFieldClasses);
524:   PetscMalloc(cm->numClasses * sizeof(int),   &cm->isClassConstrained);
525:   PetscMalloc(cm->numClasses * sizeof(int),   &cm->classSizeDiffs);
526:   PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int));
527:   PetscMemzero(cm->classSizeDiffs,     cm->numClasses * sizeof(int));
528:   /* Copy old structure */
529:   for(nclass = 0; nclass < numClasses; nclass++) {
530:     cm->isClassConstrained[nclass] = map->isClassConstrained[nclass];
531:     cm->classSizeDiffs[nclass]     = map->classSizeDiffs[nclass];
532:   }
533:   /* Apply constraints */
534:   for(f = 0; f < cm->numFields; f++) {
535:     PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]);
536:     PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]);
537:     PetscMemzero(cm->fieldClasses[f], cm->numClasses * sizeof(int));
538:     /* Copy old structure */
539:     for(nclass = 0; nclass < numClasses; nclass++) {
540:       cm->reduceFieldClasses[f][nclass] = map->fieldClasses[f][nclass];
541:       if (map->reduceFieldClasses) {
542:         cm->fieldClasses[f][nclass]     = map->reduceFieldClasses[f][nclass];
543:       }
544:     }

546:     /* Remove constrained fields from new classes */
547:     for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) {
548:       /* Invert the class map */
549:       for(bd = 0; bd < cm->mapSize; bd++) {
550:         for(nclass = 0; nclass < numClasses; nclass++)
551:           if (cm->classMap[bd][nclass] == newNClass)
552:             break;
553:         if (nclass < numClasses)
554:           break;
555:       }
556:       if ((nclass >= numClasses) || (bd >= cm->mapSize)) {
557:         SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass);
558:       }
559:       /* Check every BC for constraints on this field/class */
560:       cm->reduceFieldClasses[f][newNClass]     = map->fieldClasses[f][nclass];
561:       for(bd = 0; bd < cm->mapSize; bd++) {
562:         /* New classes can be redefined by another BC to be a higher number, but do not
563:            operate on the existing new class with that BC (hence the second check)
564:         */
565:         if ((classMap[bd][nclass][f] == 1) && (cm->classMap[bd][nclass] <= newNClass)) {
566:           /* If the field is constrained, it has no values on these nodes */
567:           cm->fieldClasses[f][newNClass]       = 1;
568:           cm->reduceFieldClasses[f][newNClass] = 0;
569:         }
570:       }
571:     }
572:   }

574:   /* Setup class sizes */
575:   PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes);
576:   PetscMemzero(cm->classSizes, cm->numClasses * sizeof(int));
577:   for(nclass = 0; nclass < cm->numClasses; nclass++) {
578:     for(f = 0; f < cm->numFields; f++) {
579:       field = cm->fields[f];
580:       if (cm->fieldClasses[f][nclass]) {
581:         GridGetFieldComponents(grid, field, &comp);
582:         cm->classSizes[nclass] += comp;
583:       }
584:     }
585:   }

587:   /* Cleanup */
588:   for(bd = 0; bd < cm->mapSize; bd++) {
589:     for(nclass = 0; nclass < numClasses; nclass++) {
590:       PetscFree(localClassMap[bd][nclass]);
591:       PetscFree(classMap[bd][nclass]);
592:     }
593:     PetscFree(localClassMap[bd]);
594:     PetscFree(classMap[bd]);
595:   }
596:   PetscFree(localClassMap);
597:   PetscFree(classMap);

599:   /* Communicate ghost classes */
600:   MeshGetPartition(mesh, &part);
601:   PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]);
602: 

604:   PetscLogObjectMemory(cm, (cm->mapSize + cm->numFields*2) * sizeof(int *) + (numFields + cm->numOldClasses*cm->mapSize +
605:                        cm->numClasses*(cm->numFields*2 + 3) + numOverlapNodes) * sizeof(int));
606:   *newMap = cm;
607:   return(0);
608: }

610: static FieldClassMapOps cmOps = {0,
611:                                  FieldClassMapConstrain_Triangular_2D,
612:                                  FieldClassMapReduce_Triangular_2D,
613:                                  FieldClassMapDestroy_Triangular_2D,
614:                                  0};

616: EXTERN_C_BEGIN
617: int FieldClassMapSerialize_Triangular_2D(MPI_Comm comm, FieldClassMap *map, PetscViewer viewer, PetscTruth store)
618: {
619:   FieldClassMap cm;
620:   int           fd;
621:   int           zero = 0;
622:   int           one  = 0;
623:   int           hasClassMap;
624:   int           bd, f;
625:   int           ierr;

628:   PetscViewerBinaryGetDescriptor(viewer, &fd);
629:   if (store) {
630:     cm   = *map;
631:     PetscBinaryWrite(fd, &cm->numFields,          1,                    PETSC_INT, 0);
632:     PetscBinaryWrite(fd,  cm->fields,             cm->numFields,        PETSC_INT, 0);
633:     PetscBinaryWrite(fd, &cm->numNodes,           1,                    PETSC_INT, 0);
634:     PetscBinaryWrite(fd, &cm->numGhostNodes,      1,                    PETSC_INT, 0);
635:     PetscBinaryWrite(fd, &cm->numOverlapNodes,    1,                    PETSC_INT, 0);
636:     PetscBinaryWrite(fd, &cm->numClasses,         1,                    PETSC_INT, 0);
637:     for(f = 0; f < cm->numFields; f++) {
638:       PetscBinaryWrite(fd,  cm->fieldClasses[f],  cm->numClasses,       PETSC_INT, 0);
639:     }
640:     PetscBinaryWrite(fd,  cm->classes,            cm->numOverlapNodes,  PETSC_INT, 0);
641:     PetscBinaryWrite(fd,  cm->classSizes,         cm->numClasses,       PETSC_INT, 0);
642:     PetscBinaryWrite(fd, &cm->isReduced,          1,                    PETSC_INT, 0);
643:     if (cm->isReduced == PETSC_TRUE) {
644:       for(f = 0; f < cm->numFields; f++) {
645:         PetscBinaryWrite(fd,  cm->reduceFieldClasses[f], cm->numClasses, PETSC_INT, 0);
646:       }
647:     }
648:     PetscBinaryWrite(fd, &cm->isConstrained,      1,                    PETSC_INT, 0);
649:     PetscBinaryWrite(fd,  cm->isClassConstrained, cm->numClasses,       PETSC_INT, 0);
650:     PetscBinaryWrite(fd,  cm->classSizeDiffs,     cm->numClasses,       PETSC_INT, 0);
651:     PetscBinaryWrite(fd, &cm->mapSize,            1,                    PETSC_INT, 0);
652:     PetscBinaryWrite(fd, &cm->numOldClasses,      1,                    PETSC_INT, 0);
653:     if (cm->classMap != PETSC_NULL) {
654:       PetscBinaryWrite(fd, &one,                  1,                    PETSC_INT, 0);
655:       for(bd = 0; bd < cm->mapSize; bd++) {
656:         PetscBinaryWrite(fd,  cm->classMap[bd],   cm->numOldClasses,    PETSC_INT, 0);
657:       }
658:     } else {
659:       PetscBinaryWrite(fd, &zero,                 1,                    PETSC_INT, 0);
660:     }
661:   } else {
662:     /* Create the mesh context */
663:     FieldClassMapCreate(comm, &cm);
664:     PetscMemcpy(cm->ops, &cmOps, sizeof(FieldClassMapOps));
665:     PetscStrallocpy(CLASS_MAP_TRIANGULAR_2D, &cm->type_name);
666:     cm->data = PETSC_NULL;

668:     PetscBinaryRead(fd, &cm->numFields,          1,                   PETSC_INT);
669:     PetscMalloc(cm->numFields * sizeof(int), &cm->fields);
670:     PetscBinaryRead(fd,  cm->fields,             cm->numFields,       PETSC_INT);
671:     PetscBinaryRead(fd, &cm->numNodes,           1,                   PETSC_INT);
672:     PetscBinaryRead(fd, &cm->numGhostNodes,      1,                   PETSC_INT);
673:     PetscBinaryRead(fd, &cm->numOverlapNodes,    1,                   PETSC_INT);
674:     PetscBinaryRead(fd, &cm->numClasses,         1,                   PETSC_INT);
675:     PetscMalloc(cm->numFields * sizeof(int *), &cm->fieldClasses);
676:     for(f = 0; f < cm->numFields; f++) {
677:       PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]);
678:       PetscBinaryRead(fd,  cm->fieldClasses[f],  cm->numClasses,      PETSC_INT);
679:     }
680:     PetscMalloc(cm->numOverlapNodes * sizeof(int), &cm->classes);
681:     PetscBinaryRead(fd,  cm->classes,            cm->numOverlapNodes, PETSC_INT);
682:     PetscMalloc(cm->numClasses      * sizeof(int), &cm->classSizes);
683:     PetscBinaryRead(fd,  cm->classSizes,         cm->numClasses,      PETSC_INT);
684:     PetscBinaryRead(fd, &cm->isReduced,          1,                   PETSC_INT);
685:     if (cm->isReduced == PETSC_TRUE) {
686:       PetscMalloc(cm->numFields * sizeof(int *), &cm->reduceFieldClasses);
687:       for(f = 0; f < cm->numFields; f++) {
688:         PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]);
689:         PetscBinaryRead(fd, cm->reduceFieldClasses[f], cm->numClasses, PETSC_INT);
690:       }
691:     }
692:     PetscBinaryRead(fd, &cm->isConstrained,      1,                   PETSC_INT);
693:     PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained);
694:     PetscBinaryRead(fd,  cm->isClassConstrained, cm->numClasses,      PETSC_INT);
695:     PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs);
696:     PetscBinaryRead(fd,  cm->classSizeDiffs,     cm->numClasses,      PETSC_INT);
697:     PetscBinaryRead(fd, &cm->mapSize,            1,                   PETSC_INT);
698:     PetscBinaryRead(fd, &cm->numOldClasses,      1,                   PETSC_INT);
699:     PetscBinaryRead(fd, &hasClassMap,            1,                   PETSC_INT);
700:     if (hasClassMap) {
701:       PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap);
702:       for(bd = 0; bd < cm->mapSize; bd++) {
703:         PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]);
704:         PetscBinaryRead(fd,  cm->classMap[bd],   cm->numOldClasses,   PETSC_INT);
705:       }
706:     }

708:     PetscLogObjectMemory(cm, (cm->numFields + cm->mapSize) * sizeof(int *) + (cm->numFields*(cm->numClasses + 1) +
709:                          cm->numOverlapNodes + cm->numOldClasses*cm->mapSize + cm->numClasses*3) * sizeof(int));
710:     *map = cm;
711:   }
712:   return(0);
713: }
714: EXTERN_C_END

716: EXTERN_C_BEGIN
717: int FieldClassMapCreate_Triangular_2D(FieldClassMap cm)
718: {
719:   ParameterDict  dict;
720:   Grid           grid;
721:   Mesh           mesh;
722:   Partition      part;
723:   Discretization disc, firstDisc;
724:   int           *fields;
725:   int            numOverlapElements, numCorners;
726:   int            f, field, comp, elem, corner, node, nclass;
727:   PetscTruth     match, isconst, islin, isquad;
728:   int            ierr;

731:   PetscMemcpy(cm->ops, &cmOps, sizeof(FieldClassMapOps));
732:   PetscStrallocpy(CLASS_MAP_SER_TRIANGULAR_2D_BINARY, &cm->serialize_name);
733:   /* Get arguments */
734:   PetscObjectGetParameterDict((PetscObject) cm, &dict);
735:   ParameterDictGetInteger(dict, "numFields", &cm->numFields);
736:   ParameterDictGetObject(dict,  "fields",    (void **) &fields);
737:   ParameterDictGetObject(dict,  "grid",      (void **) &grid);
738:   /* Get fields */
739:   PetscMalloc(cm->numFields * sizeof(int), &cm->fields);
740:   PetscMemcpy(cm->fields, fields, cm->numFields * sizeof(int));

742:   /* Get number of classes -- this is very simplistic, needs to be changed for other discretizations */
743:   GridGetFieldDisc(grid, 0, &firstDisc);
744:   cm->numClasses = 1;
745:   for(f = 0; f < cm->numFields; f++) {
746:     GridGetFieldDisc(grid, cm->fields[f], &disc);
747:     PetscStrcmp(disc->type_name, firstDisc->type_name, &match);
748:     if (match == PETSC_FALSE) {
749:       cm->numClasses++;
750:       break;
751:     }
752:   }
753:   GridGetMesh(grid, &mesh);
754:   MeshGetPartition(mesh, &part);
755:   PartitionGetNumNodes(part, &cm->numNodes);
756:   PartitionGetNumOverlapNodes(part, &cm->numOverlapNodes);
757:   cm->numGhostNodes = cm->numOverlapNodes - cm->numNodes;
758:   PetscMalloc(cm->numOverlapNodes * sizeof(int), &cm->classes);

760:   /* Setup field class membership -- this is very simplistic, needs to be changed for other discretizations */
761:   PetscMalloc(cm->numFields * sizeof(int *), &cm->fieldClasses);
762:   for(f = 0; f < cm->numFields; f++) {
763:     field = cm->fields[f];
764:     PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]);
765:     GridGetFieldDisc(grid, field, &disc);
766:     for(nclass = 0; nclass < cm->numClasses; nclass++) {
767:       if (grid->dim == 1) {
768:         PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_CONSTANT,  &isconst);
769:         PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_LINEAR,    &islin);
770:         PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_QUADRATIC, &isquad);
771:       } else if (grid->dim == 2) {
772:         PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_2D_LINEAR,    &islin);
773:         PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_2D_QUADRATIC, &isquad);
774:       }
775:       /* These only work for pairs in 2D (all are fine in 1D, how do I generalize this?) */
776:       if (isconst == PETSC_TRUE) {
777:         cm->fieldClasses[f][nclass] = (nclass == 1 ? 1 : 0);
778:       } else if (islin == PETSC_TRUE) {
779:         cm->fieldClasses[f][nclass] = (nclass == 0 ? 1 : 0);
780:       } else if (isquad == PETSC_TRUE) {
781:         cm->fieldClasses[f][nclass] = 1;
782:       } else {
783:         SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid discretization type");
784:       }
785:     }
786:   }

788:   /* Setup classes */
789:   PetscMemzero(cm->classes, cm->numOverlapNodes * sizeof(int));
790:   if (cm->numClasses > 1) {
791:     /* Set all midnodes to class 1 */
792:     PartitionGetNumOverlapElements(part, &numOverlapElements);
793:     MeshGetNumCorners(mesh, &numCorners);
794:     for(elem = 0; elem < numOverlapElements; elem++) {
795:       for(corner = grid->dim+1; corner < numCorners; corner++) {
796:         MeshGetNodeFromElement(mesh, elem, corner, &node);
797:         if (cm->classes[node] == 0)
798:           cm->classes[node] = 1;
799:       }
800:     }
801:   }

803:   /* Communicate ghost classes */
804:   PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]);
805: 

807:   /* Setup class sizes */
808:   PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes);
809:   PetscMemzero(cm->classSizes, cm->numClasses * sizeof(int));
810:   for(nclass = 0; nclass < cm->numClasses; nclass++) {
811:     for(f = 0; f < cm->numFields; f++) {
812:       field = cm->fields[f];
813:       if (cm->fieldClasses[f][nclass]) {
814:         GridGetFieldComponents(grid, field, &comp);
815:         cm->classSizes[nclass] += comp;
816:       }
817:     }
818:   }

820:   /* Initialize constraint support */
821:   PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained);
822:   PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs);
823:   PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int));
824:   PetscMemzero(cm->classSizeDiffs,     cm->numClasses * sizeof(int));

826:   PetscLogObjectMemory(cm, (cm->numFields + cm->numOverlapNodes + (cm->numFields + 4)*cm->numClasses) * sizeof(int) +
827:                    cm->numFields * sizeof(int *));
828:   return(0);
829: }
830: EXTERN_C_END