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