#ifdef PETSC_RCS_HEADER static char vcid[] = "$Id: fieldClassMap2d.c,v 1.6 2000/01/30 18:30:46 huangp Exp $"; #endif #include "src/grid/gridimpl.h" /*I "grid.h" I*/ #include "fieldClassMap2d.h" /*---------------------------------------- Creation and Destruction Functions ---------------------------------------*/ #undef __FUNCT__ #define __FUNCT__ "FieldClassMapCreateTriangular2D" /*@C FieldClassMapCreateTriangular2D - This function creates a class map for the given grid. Collective on Grid Input Parameters: + grid - The underlying grid for the ordering . numFields - The number of fields in the ordering - fields - The fields in the ordering Output Parameter: . map - The map Level: beginner .keywords: class, field class, class map, create .seealso: FieldClassMapCreate(), FieldClassMapDestroy() @*/ int FieldClassMapCreateTriangular2D(Grid grid, int numFields, int *fields, FieldClassMap *map) { MPI_Comm comm; ParameterDict dict; int numTotalFields, f; int ierr; PetscFunctionBegin; ierr = GridGetNumFields(grid, &numTotalFields); CHKERRQ(ierr); if (numFields > numTotalFields) { SETERRQ2(PETSC_ERR_ARG_WRONG, "Invalid number %d of fields, grid only has %d", numFields, numTotalFields); } for(f = 0; f < numFields; f++) { if ((fields[f] < 0) || (fields[f] >= numTotalFields)) { SETERRQ1(PETSC_ERR_ARG_WRONG, "Invalid field number %d", fields[f]); } } ierr = PetscObjectGetComm((PetscObject) grid, &comm); CHKERRQ(ierr); ierr = FieldClassMapCreate(comm, map); CHKERRQ(ierr); ierr = PetscObjectGetComm((PetscObject) grid, &comm); CHKERRQ(ierr); ierr = ParameterDictCreate(comm, &dict); CHKERRQ(ierr); ierr = ParameterDictSetInteger(dict, "numFields", numFields); CHKERRQ(ierr); ierr = ParameterDictSetObject(dict, "fields", fields); CHKERRQ(ierr); ierr = ParameterDictSetObject(dict, "grid", grid); CHKERRQ(ierr); ierr = PetscObjectSetParameterDict((PetscObject) *map, dict); CHKERRQ(ierr); ierr = ParameterDictDestroy(dict); CHKERRQ(ierr); ierr = FieldClassMapSetType(*map, CLASS_MAP_TRIANGULAR_2D); CHKERRQ(ierr); PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "FieldClassMapDestroy_Triangular_2D" int FieldClassMapDestroy_Triangular_2D(FieldClassMap map) { PetscFunctionBegin; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "FieldClassMapConstrain_Triangular_2D" int FieldClassMapConstrain_Triangular_2D(FieldClassMap map, Grid grid, PetscTruth useBC, PetscTruth useConst, FieldClassMap *newMap) { FieldClassMap cm; Mesh mesh; Partition part; int numBd = grid->numBd; int numBC = grid->numBC; GridBC *gBC = grid->bc; int numPointBC = grid->numPointBC; GridBC *pBC = grid->pointBC; int numFields = map->numFields; int *fields = map->fields; int numNodes = map->numNodes; int numOverlapNodes = map->numOverlapNodes; int numClasses = map->numClasses; int *classes = map->classes; int ***localClassMap, ***classMap; PetscTruth isConst; int f, g, field, comp, node, bd, oldBd, bc, marker, nclass, newNClass, oldNClass; int ierr; PetscFunctionBegin; ierr = FieldClassMapCreate(map->comm, &cm); CHKERRQ(ierr); ierr = PetscMemcpy(cm->ops, map->ops, sizeof(FieldClassMapOps)); CHKERRQ(ierr); ierr = PetscStrallocpy(map->serialize_name, &cm->serialize_name); CHKERRQ(ierr); ierr = GridGetMesh(grid, &mesh); CHKERRQ(ierr); cm->numFields = numFields; cm->numNodes = numNodes; cm->numOverlapNodes = numOverlapNodes; cm->numGhostNodes = cm->numOverlapNodes - cm->numNodes; ierr = PetscMalloc(numFields * sizeof(int), &cm->fields); CHKERRQ(ierr); ierr = PetscMemcpy(cm->fields, fields, numFields * sizeof(int)); CHKERRQ(ierr); /* classMap[numBd+numPointBC+1][numClasses][numFields]: The classMap[][][] structure is organized as follows. For every boundary, we determine the classes which are present on that boundary. For each class, we create a new class which does not contain the constrained fields. The classMap[][][] structure has for each boundary flag_0, flag_1, \ldots, flag_numFields-1 flag_0, flag_1, \ldots, flag_numFields-1 ... flag_0, flag_1, \ldots, flag_numFields-1 where a positive flag indicates that the field is constrained in that class, and a zero indicates no change. Point boundary conditions are treated like additional boundaries, and since we only allow one constraint, the last position is used for the constraint. */ cm->mapSize = numBd + numPointBC + 1; cm->numOldClasses = numClasses; ierr = PetscMalloc(cm->mapSize * sizeof(int **), &localClassMap); CHKERRQ(ierr); ierr = PetscMalloc(cm->mapSize * sizeof(int **), &classMap); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscMalloc(numClasses * sizeof(int *), &localClassMap[bd]); CHKERRQ(ierr); ierr = PetscMalloc(numClasses * sizeof(int *), &classMap[bd]); CHKERRQ(ierr); for(nclass = 0; nclass < numClasses; nclass++) { ierr = PetscMalloc(numFields * sizeof(int), &localClassMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscMalloc(numFields * sizeof(int), &classMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscMemzero(localClassMap[bd][nclass], numFields * sizeof(int)); CHKERRQ(ierr); ierr = PetscMemzero(classMap[bd][nclass], numFields * sizeof(int)); CHKERRQ(ierr); } } /* Mark constrained classes for reassignment */ for(node = 0; node < numNodes; node++) { ierr = MeshGetNodeBoundary(mesh, node, &marker); CHKERRQ(ierr); if (marker == 0) continue; nclass = classes[node]; if ((useConst == PETSC_TRUE) && (marker < 0)) { /* All constrained nodes have negative markers */ for(f = 0; f < numFields; f++) { field = fields[f]; if (grid->fields[field].isConstrained == PETSC_TRUE) { localClassMap[cm->mapSize-1][nclass][f] = 1; } } } else if ((useBC == PETSC_TRUE) && (marker > 0)) { for(bc = 0; bc < numBC; bc++) { if (gBC[bc].reduce == PETSC_FALSE) continue; if (gBC[bc].boundary == marker) { ierr = MeshGetBoundaryIndex(mesh, marker, &bd); CHKERRQ(ierr); for(f = 0; f < numFields; f++) { if (fields[f] == gBC[bc].field) { localClassMap[bd][nclass][f] = 1; break; } } } } for(bc = 0; bc < numPointBC; bc++) { if (pBC[bc].reduce == PETSC_FALSE) continue; if (pBC[bc].node == node) { for(f = 0; f < numFields; f++) { if (fields[f] == pBC[bc].field) { localClassMap[numBd+bc][nclass][f] = 1; break; } } } } } } /* Synchronize localClassMap */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { ierr = MPI_Allreduce(localClassMap[bd][nclass], classMap[bd][nclass], numFields, MPI_INT, MPI_LOR, cm->comm); CHKERRQ(ierr); } } /* Assign new classes */ ierr = PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]); CHKERRQ(ierr); for(nclass = 0; nclass < numClasses; nclass++) { cm->classMap[bd][nclass] = nclass; } } for(bd = 0, cm->numClasses = numClasses; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { for(f = 0, isConst = PETSC_FALSE; f < numFields; f++) { if (classMap[bd][nclass][f] != 0) { isConst = PETSC_TRUE; field = fields[f]; /* Map old classes to new with the condition which created it for a given field */ classMap[bd][nclass][f] = cm->numClasses; /* Check that field should be constrained */ if ((bd == cm->mapSize-1) && (grid->fields[field].isConstrained == PETSC_FALSE)) { SETERRQ1(PETSC_ERR_PLIB, "Invalid constrained field %d", field); } /* Must include previous constraints on the node */ for(g = 0; g < numFields; g++) { for(oldBd = 0; oldBd < bd; oldBd++) { for(oldNClass = 0; oldNClass < numClasses; oldNClass++) { if (classMap[oldBd][oldNClass][g] != 0) { classMap[bd][nclass][g] = cm->numClasses; break; } } } } break; } } /* Create a new class */ if (isConst == PETSC_TRUE) { cm->classMap[bd][nclass] = cm->numClasses++; } } } /* Set new classes on nodes */ ierr = PetscMalloc(numOverlapNodes * sizeof(int), &cm->classes); CHKERRQ(ierr); ierr = PetscMemcpy(cm->classes, classes, numOverlapNodes * sizeof(int)); CHKERRQ(ierr); for(node = 0; node < numOverlapNodes; node++) { ierr = MeshGetNodeBoundary(mesh, node, &marker); CHKERRQ(ierr); if (marker == 0) continue; nclass = classes[node]; if (marker < 0) { cm->classes[node] = cm->classMap[cm->mapSize-1][nclass]; } else { for(bc = 0; bc < numBC; bc++) { if (gBC[bc].reduce == PETSC_FALSE) continue; if (gBC[bc].boundary == marker) { ierr = MeshGetBoundaryIndex(mesh, marker, &bd); CHKERRQ(ierr); if (cm->classMap[bd][nclass] != nclass) { cm->classes[node] = cm->classMap[bd][nclass]; } } } /* Notice that point BC must come last since these nodes may lie on a boundary which was also constrained */ for(bc = 0; bc < numPointBC; bc++) { if (pBC[bc].reduce == PETSC_FALSE) continue; if (pBC[bc].node == node) { if (cm->classMap[numBd+bc][nclass] != nclass) { cm->classes[node] = cm->classMap[numBd+bc][nclass]; } } } } } /* Calculate new class structure */ cm->isReduced = map->isReduced; cm->isConstrained = map->isConstrained; ierr = PetscMalloc(numFields * sizeof(int *), &cm->fieldClasses); CHKERRQ(ierr); ierr = PetscMalloc(numFields * sizeof(int *), &cm->reduceFieldClasses); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs); CHKERRQ(ierr); ierr = PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int)); CHKERRQ(ierr); ierr = PetscMemzero(cm->classSizeDiffs, cm->numClasses * sizeof(int)); CHKERRQ(ierr); /* Copy old structure */ for(nclass = 0; nclass < numClasses; nclass++) { cm->classSizes[nclass] = map->classSizes[nclass]; cm->isClassConstrained[nclass] = map->isClassConstrained[nclass]; cm->classSizeDiffs[nclass] = map->classSizeDiffs[nclass]; } for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) { /* Invert the class map */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) if (cm->classMap[bd][nclass] == newNClass) break; if (nclass < numClasses) break; } if ((nclass >= numClasses) || (bd >= cm->mapSize)) { SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass); } cm->classSizes[newNClass] = map->classSizes[nclass]; cm->classSizeDiffs[newNClass] = map->classSizeDiffs[nclass]; } /* Apply constraints */ for(f = 0; f < numFields; f++) { ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]); CHKERRQ(ierr); ierr = PetscMemzero(cm->reduceFieldClasses[f], cm->numClasses * sizeof(int)); CHKERRQ(ierr); /* Copy old structure */ for(nclass = 0; nclass < numClasses; nclass++) { cm->fieldClasses[f][nclass] = map->fieldClasses[f][nclass]; if (map->reduceFieldClasses) { cm->reduceFieldClasses[f][nclass] = map->reduceFieldClasses[f][nclass]; } } /* Remove constrained fields from new classes */ for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) { /* Invert the class map */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) if (cm->classMap[bd][nclass] == newNClass) break; if (nclass < numClasses) break; } if ((nclass >= numClasses) || (bd >= cm->mapSize)) { SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass); } /* Check every BC for constraints on this field/class */ cm->fieldClasses[f][newNClass] = map->fieldClasses[f][nclass]; for(bd = 0; bd < cm->mapSize; bd++) { if (classMap[bd][nclass][f] == newNClass) { /* New classes can be redefined by another BC to be a higher number, but do not operate on the existing new class with that BC (hence the second check) */ if (cm->classMap[bd][nclass] != newNClass) { SETERRQ3(PETSC_ERR_PLIB, "Invalid bc %d constraining class %d to %d", bd, nclass, newNClass); } /* If the field is constrained, it has no values on these nodes */ cm->fieldClasses[f][newNClass] = 0; if (bd < cm->mapSize-1) { cm->isReduced = PETSC_TRUE; cm->reduceFieldClasses[f][newNClass] = 1; } /* Subtract the degrees of freedom of the constrained field for each BC */ ierr = GridGetFieldComponents(grid, fields[f], &comp); CHKERRQ(ierr); cm->classSizes[newNClass] -= comp; if (cm->classSizes[newNClass] < 0) { SETERRQ2(PETSC_ERR_PLIB, "Invalid size for class %d (derived from class %d)", newNClass, nclass); } /* Handle user constraints separately from BC */ if (bd == cm->mapSize-1) { cm->isConstrained = PETSC_TRUE; /* This class is constrained */ cm->isClassConstrained[newNClass] = 1; /* There are this many components in the new field */ cm->classSizeDiffs[newNClass] += grid->fields[fields[f]].constraintCompDiff + comp; } } } } } /* Cleanup */ if (cm->isReduced == PETSC_FALSE) { for(f = 0; f < map->numFields; f++) { ierr = PetscFree(cm->reduceFieldClasses[f]); CHKERRQ(ierr); } ierr = PetscFree(cm->reduceFieldClasses); CHKERRQ(ierr); } for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { ierr = PetscFree(localClassMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscFree(classMap[bd][nclass]); CHKERRQ(ierr); } ierr = PetscFree(localClassMap[bd]); CHKERRQ(ierr); ierr = PetscFree(classMap[bd]); CHKERRQ(ierr); } ierr = PetscFree(localClassMap); CHKERRQ(ierr); ierr = PetscFree(classMap); CHKERRQ(ierr); /* Communicate ghost classes */ ierr = MeshGetPartition(mesh, &part); CHKERRQ(ierr); ierr = PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]); CHKERRQ(ierr); PetscLogObjectMemory(cm, (cm->mapSize + numFields*2) * sizeof(int *) + (numFields + cm->numOldClasses*cm->mapSize + cm->numClasses*(numFields*2 + 3) + numOverlapNodes) * sizeof(int)); *newMap = cm; PetscFunctionReturn(0); } #undef __FUNCT__ #define __FUNCT__ "FieldClassMapReduce_Triangular_2D" int FieldClassMapReduce_Triangular_2D(FieldClassMap map, Grid grid, FieldClassMap *newMap) { FieldClassMap cm; Mesh mesh; Partition part; int numBd = grid->numBd; int numBC = grid->numBC; GridBC *gBC = grid->bc; int numPointBC = grid->numPointBC; GridBC *pBC = grid->pointBC; int numFields = map->numFields; int *fields = map->fields; int numNodes = map->numNodes; int numOverlapNodes = map->numOverlapNodes; int numClasses = map->numClasses; int *classes = map->classes; int ***localClassMap, ***classMap; PetscTruth isConst; int f, g, field, comp, node, bd, bc, marker, nclass, newNClass; int ierr; PetscFunctionBegin; ierr = FieldClassMapCreate(map->comm, &cm); CHKERRQ(ierr); ierr = PetscMemcpy(cm->ops, map->ops, sizeof(FieldClassMapOps)); CHKERRQ(ierr); ierr = PetscStrallocpy(map->serialize_name, &cm->serialize_name); CHKERRQ(ierr); ierr = GridGetMesh(grid, &mesh); CHKERRQ(ierr); cm->numNodes = numNodes; cm->numOverlapNodes = numOverlapNodes; cm->numGhostNodes = cm->numOverlapNodes - cm->numNodes; ierr = PetscMalloc(numFields * sizeof(int), &cm->fields); CHKERRQ(ierr); /* classMap[numBd+numPointBC][numClasses][numFields]: The classMap[][][] structure is organized as follows. For every boundary, we determine the classes which are present on that boundary. For each class, we create a new class which does not contain the constrained fields. The classMap[][][] structure has for each boundary flag_0, flag_1, \ldots, flag_numFields-1 flag_0, flag_1, \ldots, flag_numFields-1 ... flag_0, flag_1, \ldots, flag_numFields-1 where a positive flag indicates that the field is constrained in that class, and a zero indicates no change. Point boundary conditions are treated like additional boundaries. */ cm->mapSize = numBd + numPointBC; cm->numOldClasses = numClasses; ierr = PetscMalloc(cm->mapSize * sizeof(int **), &localClassMap); CHKERRQ(ierr); ierr = PetscMalloc(cm->mapSize * sizeof(int **), &classMap); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscMalloc(numClasses * sizeof(int *), &localClassMap[bd]); CHKERRQ(ierr); ierr = PetscMalloc(numClasses * sizeof(int *), &classMap[bd]); CHKERRQ(ierr); for(nclass = 0; nclass < numClasses; nclass++) { ierr = PetscMalloc(numFields * sizeof(int), &localClassMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscMalloc(numFields * sizeof(int), &classMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscMemzero(localClassMap[bd][nclass], numFields * sizeof(int)); CHKERRQ(ierr); ierr = PetscMemzero(classMap[bd][nclass], numFields * sizeof(int)); CHKERRQ(ierr); } } /* Mark constrained classes for reassignment */ for(node = 0; node < numNodes; node++) { ierr = MeshGetNodeBoundary(mesh, node, &marker); CHKERRQ(ierr); if (marker == 0) continue; nclass = classes[node]; if (marker > 0) { for(bc = 0; bc < numBC; bc++) { if (gBC[bc].reduce == PETSC_FALSE) continue; if (gBC[bc].boundary == marker) { ierr = MeshGetBoundaryIndex(mesh, marker, &bd); CHKERRQ(ierr); for(f = 0; f < numFields; f++) { if (fields[f] == gBC[bc].field) { localClassMap[bd][nclass][f] = 1; break; } } } } for(bc = 0; bc < numPointBC; bc++) { if (pBC[bc].reduce == PETSC_FALSE) continue; if (pBC[bc].node == node) { for(f = 0; f < numFields; f++) { if (fields[f] == pBC[bc].field) { localClassMap[numBd+bc][nclass][f] = 1; break; } } } } } } /* Synchronize localClassMap */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { ierr = MPI_Allreduce(localClassMap[bd][nclass], classMap[bd][nclass], numFields, MPI_INT, MPI_LOR, cm->comm); CHKERRQ(ierr); } } /* Assign new classes and build field list */ ierr = PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]); CHKERRQ(ierr); for(nclass = 0; nclass < numClasses; nclass++) { cm->classMap[bd][nclass] = nclass; } } cm->numFields = 0; for(bd = 0, cm->numClasses = numClasses; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { for(f = 0, isConst = PETSC_FALSE; f < numFields; f++) { if (classMap[bd][nclass][f] != 0) { isConst = PETSC_TRUE; field = fields[f]; /* Add to list of reduced fields */ for(g = 0; g < cm->numFields; g++) if (field == cm->fields[g]) break; if (g == cm->numFields) cm->fields[cm->numFields++] = field; } } /* Create a new class */ if (isConst == PETSC_TRUE) { cm->classMap[bd][nclass] = cm->numClasses++; } } } /* Set new classes on nodes */ ierr = PetscMalloc(numOverlapNodes * sizeof(int), &cm->classes); CHKERRQ(ierr); ierr = PetscMemcpy(cm->classes, classes, numOverlapNodes * sizeof(int)); CHKERRQ(ierr); for(node = 0; node < numOverlapNodes; node++) { ierr = MeshGetNodeBoundary(mesh, node, &marker); CHKERRQ(ierr); if (marker == 0) continue; nclass = classes[node]; for(bc = 0; bc < numBC; bc++) { if (gBC[bc].reduce == PETSC_FALSE) continue; if (gBC[bc].boundary == marker) { ierr = MeshGetBoundaryIndex(mesh, marker, &bd); CHKERRQ(ierr); cm->classes[node] = cm->classMap[bd][nclass]; } } /* Notice that point BC must come last since these nodes may lie on a boundary which was also constrained */ for(bc = 0; bc < numPointBC; bc++) { if (pBC[bc].reduce == PETSC_FALSE) continue; if (pBC[bc].node == node) { cm->classes[node] = cm->classMap[numBd+bc][nclass]; } } } /* Calculate new class structure */ cm->isReduced = PETSC_TRUE; cm->isConstrained = map->isConstrained; ierr = PetscMalloc(cm->numFields * sizeof(int *), &cm->fieldClasses); CHKERRQ(ierr); ierr = PetscMalloc(cm->numFields * sizeof(int *), &cm->reduceFieldClasses); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs); CHKERRQ(ierr); ierr = PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int)); CHKERRQ(ierr); ierr = PetscMemzero(cm->classSizeDiffs, cm->numClasses * sizeof(int)); CHKERRQ(ierr); /* Copy old structure */ for(nclass = 0; nclass < numClasses; nclass++) { cm->isClassConstrained[nclass] = map->isClassConstrained[nclass]; cm->classSizeDiffs[nclass] = map->classSizeDiffs[nclass]; } /* Apply constraints */ for(f = 0; f < cm->numFields; f++) { ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]); CHKERRQ(ierr); ierr = PetscMemzero(cm->fieldClasses[f], cm->numClasses * sizeof(int)); CHKERRQ(ierr); /* Copy old structure */ for(nclass = 0; nclass < numClasses; nclass++) { cm->reduceFieldClasses[f][nclass] = map->fieldClasses[f][nclass]; if (map->reduceFieldClasses) { cm->fieldClasses[f][nclass] = map->reduceFieldClasses[f][nclass]; } } /* Remove constrained fields from new classes */ for(newNClass = numClasses; newNClass < cm->numClasses; newNClass++) { /* Invert the class map */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) if (cm->classMap[bd][nclass] == newNClass) break; if (nclass < numClasses) break; } if ((nclass >= numClasses) || (bd >= cm->mapSize)) { SETERRQ1(PETSC_ERR_PLIB, "Unable to locate class %d in class map", newNClass); } /* Check every BC for constraints on this field/class */ cm->reduceFieldClasses[f][newNClass] = map->fieldClasses[f][nclass]; for(bd = 0; bd < cm->mapSize; bd++) { /* New classes can be redefined by another BC to be a higher number, but do not operate on the existing new class with that BC (hence the second check) */ if ((classMap[bd][nclass][f] == 1) && (cm->classMap[bd][nclass] <= newNClass)) { /* If the field is constrained, it has no values on these nodes */ cm->fieldClasses[f][newNClass] = 1; cm->reduceFieldClasses[f][newNClass] = 0; } } } } /* Setup class sizes */ ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes); CHKERRQ(ierr); ierr = PetscMemzero(cm->classSizes, cm->numClasses * sizeof(int)); CHKERRQ(ierr); for(nclass = 0; nclass < cm->numClasses; nclass++) { for(f = 0; f < cm->numFields; f++) { field = cm->fields[f]; if (cm->fieldClasses[f][nclass]) { ierr = GridGetFieldComponents(grid, field, &comp); CHKERRQ(ierr); cm->classSizes[nclass] += comp; } } } /* Cleanup */ for(bd = 0; bd < cm->mapSize; bd++) { for(nclass = 0; nclass < numClasses; nclass++) { ierr = PetscFree(localClassMap[bd][nclass]); CHKERRQ(ierr); ierr = PetscFree(classMap[bd][nclass]); CHKERRQ(ierr); } ierr = PetscFree(localClassMap[bd]); CHKERRQ(ierr); ierr = PetscFree(classMap[bd]); CHKERRQ(ierr); } ierr = PetscFree(localClassMap); CHKERRQ(ierr); ierr = PetscFree(classMap); CHKERRQ(ierr); /* Communicate ghost classes */ ierr = MeshGetPartition(mesh, &part); CHKERRQ(ierr); ierr = PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]); CHKERRQ(ierr); PetscLogObjectMemory(cm, (cm->mapSize + cm->numFields*2) * sizeof(int *) + (numFields + cm->numOldClasses*cm->mapSize + cm->numClasses*(cm->numFields*2 + 3) + numOverlapNodes) * sizeof(int)); *newMap = cm; PetscFunctionReturn(0); } static FieldClassMapOps cmOps = {0, FieldClassMapConstrain_Triangular_2D, FieldClassMapReduce_Triangular_2D, FieldClassMapDestroy_Triangular_2D, 0}; EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "FieldClassMapSerialize_Triangular_2D" int FieldClassMapSerialize_Triangular_2D(MPI_Comm comm, FieldClassMap *map, PetscViewer viewer, PetscTruth store) { FieldClassMap cm; int fd; int zero = 0; int one = 0; int hasClassMap; int bd, f; int ierr; PetscFunctionBegin; ierr = PetscViewerBinaryGetDescriptor(viewer, &fd); CHKERRQ(ierr); if (store) { cm = *map; ierr = PetscBinaryWrite(fd, &cm->numFields, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, cm->fields, cm->numFields, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->numNodes, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->numGhostNodes, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->numOverlapNodes, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->numClasses, 1, PETSC_INT, 0); CHKERRQ(ierr); for(f = 0; f < cm->numFields; f++) { ierr = PetscBinaryWrite(fd, cm->fieldClasses[f], cm->numClasses, PETSC_INT, 0); CHKERRQ(ierr); } ierr = PetscBinaryWrite(fd, cm->classes, cm->numOverlapNodes, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, cm->classSizes, cm->numClasses, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->isReduced, 1, PETSC_INT, 0); CHKERRQ(ierr); if (cm->isReduced == PETSC_TRUE) { for(f = 0; f < cm->numFields; f++) { ierr = PetscBinaryWrite(fd, cm->reduceFieldClasses[f], cm->numClasses, PETSC_INT, 0); CHKERRQ(ierr); } } ierr = PetscBinaryWrite(fd, &cm->isConstrained, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, cm->isClassConstrained, cm->numClasses, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, cm->classSizeDiffs, cm->numClasses, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->mapSize, 1, PETSC_INT, 0); CHKERRQ(ierr); ierr = PetscBinaryWrite(fd, &cm->numOldClasses, 1, PETSC_INT, 0); CHKERRQ(ierr); if (cm->classMap != PETSC_NULL) { ierr = PetscBinaryWrite(fd, &one, 1, PETSC_INT, 0); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscBinaryWrite(fd, cm->classMap[bd], cm->numOldClasses, PETSC_INT, 0); CHKERRQ(ierr); } } else { ierr = PetscBinaryWrite(fd, &zero, 1, PETSC_INT, 0); CHKERRQ(ierr); } } else { /* Create the mesh context */ ierr = FieldClassMapCreate(comm, &cm); CHKERRQ(ierr); ierr = PetscMemcpy(cm->ops, &cmOps, sizeof(FieldClassMapOps)); CHKERRQ(ierr); ierr = PetscStrallocpy(CLASS_MAP_TRIANGULAR_2D, &cm->type_name); CHKERRQ(ierr); cm->data = PETSC_NULL; ierr = PetscBinaryRead(fd, &cm->numFields, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscMalloc(cm->numFields * sizeof(int), &cm->fields); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->fields, cm->numFields, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->numNodes, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->numGhostNodes, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->numOverlapNodes, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->numClasses, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscMalloc(cm->numFields * sizeof(int *), &cm->fieldClasses); CHKERRQ(ierr); for(f = 0; f < cm->numFields; f++) { ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->fieldClasses[f], cm->numClasses, PETSC_INT); CHKERRQ(ierr); } ierr = PetscMalloc(cm->numOverlapNodes * sizeof(int), &cm->classes); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->classes, cm->numOverlapNodes, PETSC_INT); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes);CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->classSizes, cm->numClasses, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->isReduced, 1, PETSC_INT); CHKERRQ(ierr); if (cm->isReduced == PETSC_TRUE) { ierr = PetscMalloc(cm->numFields * sizeof(int *), &cm->reduceFieldClasses); CHKERRQ(ierr); for(f = 0; f < cm->numFields; f++) { ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->reduceFieldClasses[f]); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->reduceFieldClasses[f], cm->numClasses, PETSC_INT); CHKERRQ(ierr); } } ierr = PetscBinaryRead(fd, &cm->isConstrained, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->isClassConstrained, cm->numClasses, PETSC_INT); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->classSizeDiffs, cm->numClasses, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->mapSize, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &cm->numOldClasses, 1, PETSC_INT); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, &hasClassMap, 1, PETSC_INT); CHKERRQ(ierr); if (hasClassMap) { ierr = PetscMalloc(cm->mapSize * sizeof(int *), &cm->classMap); CHKERRQ(ierr); for(bd = 0; bd < cm->mapSize; bd++) { ierr = PetscMalloc(cm->numOldClasses * sizeof(int), &cm->classMap[bd]); CHKERRQ(ierr); ierr = PetscBinaryRead(fd, cm->classMap[bd], cm->numOldClasses, PETSC_INT); CHKERRQ(ierr); } } PetscLogObjectMemory(cm, (cm->numFields + cm->mapSize) * sizeof(int *) + (cm->numFields*(cm->numClasses + 1) + cm->numOverlapNodes + cm->numOldClasses*cm->mapSize + cm->numClasses*3) * sizeof(int)); *map = cm; } PetscFunctionReturn(0); } EXTERN_C_END EXTERN_C_BEGIN #undef __FUNCT__ #define __FUNCT__ "FieldClassMapCreate_Triangular_2D" int FieldClassMapCreate_Triangular_2D(FieldClassMap cm) { ParameterDict dict; Grid grid; Mesh mesh; Partition part; Discretization disc, firstDisc; int *fields; int numOverlapElements, numCorners; int f, field, comp, elem, corner, node, nclass; PetscTruth match, isconst, islin, isquad; int ierr; PetscFunctionBegin; ierr = PetscMemcpy(cm->ops, &cmOps, sizeof(FieldClassMapOps)); CHKERRQ(ierr); ierr = PetscStrallocpy(CLASS_MAP_SER_TRIANGULAR_2D_BINARY, &cm->serialize_name); CHKERRQ(ierr); /* Get arguments */ ierr = PetscObjectGetParameterDict((PetscObject) cm, &dict); CHKERRQ(ierr); ierr = ParameterDictGetInteger(dict, "numFields", &cm->numFields); CHKERRQ(ierr); ierr = ParameterDictGetObject(dict, "fields", (void **) &fields); CHKERRQ(ierr); ierr = ParameterDictGetObject(dict, "grid", (void **) &grid); CHKERRQ(ierr); /* Get fields */ ierr = PetscMalloc(cm->numFields * sizeof(int), &cm->fields); CHKERRQ(ierr); ierr = PetscMemcpy(cm->fields, fields, cm->numFields * sizeof(int)); CHKERRQ(ierr); /* Get number of classes -- this is very simplistic, needs to be changed for other discretizations */ ierr = GridGetFieldDisc(grid, 0, &firstDisc); CHKERRQ(ierr); cm->numClasses = 1; for(f = 0; f < cm->numFields; f++) { ierr = GridGetFieldDisc(grid, cm->fields[f], &disc); CHKERRQ(ierr); ierr = PetscStrcmp(disc->type_name, firstDisc->type_name, &match); CHKERRQ(ierr); if (match == PETSC_FALSE) { cm->numClasses++; break; } } ierr = GridGetMesh(grid, &mesh); CHKERRQ(ierr); ierr = MeshGetPartition(mesh, &part); CHKERRQ(ierr); ierr = PartitionGetNumNodes(part, &cm->numNodes); CHKERRQ(ierr); ierr = PartitionGetNumOverlapNodes(part, &cm->numOverlapNodes); CHKERRQ(ierr); cm->numGhostNodes = cm->numOverlapNodes - cm->numNodes; ierr = PetscMalloc(cm->numOverlapNodes * sizeof(int), &cm->classes); CHKERRQ(ierr); /* Setup field class membership -- this is very simplistic, needs to be changed for other discretizations */ ierr = PetscMalloc(cm->numFields * sizeof(int *), &cm->fieldClasses); CHKERRQ(ierr); for(f = 0; f < cm->numFields; f++) { field = cm->fields[f]; ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->fieldClasses[f]); CHKERRQ(ierr); ierr = GridGetFieldDisc(grid, field, &disc); CHKERRQ(ierr); for(nclass = 0; nclass < cm->numClasses; nclass++) { if (grid->dim == 1) { ierr = PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_CONSTANT, &isconst); CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_LINEAR, &islin); CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_1D_QUADRATIC, &isquad); CHKERRQ(ierr); } else if (grid->dim == 2) { ierr = PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_2D_LINEAR, &islin); CHKERRQ(ierr); ierr = PetscTypeCompare((PetscObject) disc, DISCRETIZATION_TRIANGULAR_2D_QUADRATIC, &isquad); CHKERRQ(ierr); } /* These only work for pairs in 2D (all are fine in 1D, how do I generalize this?) */ if (isconst == PETSC_TRUE) { cm->fieldClasses[f][nclass] = (nclass == 1 ? 1 : 0); } else if (islin == PETSC_TRUE) { cm->fieldClasses[f][nclass] = (nclass == 0 ? 1 : 0); } else if (isquad == PETSC_TRUE) { cm->fieldClasses[f][nclass] = 1; } else { SETERRQ(PETSC_ERR_ARG_WRONG, "Invalid discretization type"); } } } /* Setup classes */ ierr = PetscMemzero(cm->classes, cm->numOverlapNodes * sizeof(int)); CHKERRQ(ierr); if (cm->numClasses > 1) { /* Set all midnodes to class 1 */ ierr = PartitionGetNumOverlapElements(part, &numOverlapElements); CHKERRQ(ierr); ierr = MeshGetNumCorners(mesh, &numCorners); CHKERRQ(ierr); for(elem = 0; elem < numOverlapElements; elem++) { for(corner = grid->dim+1; corner < numCorners; corner++) { ierr = MeshGetNodeFromElement(mesh, elem, corner, &node); CHKERRQ(ierr); if (cm->classes[node] == 0) cm->classes[node] = 1; } } } /* Communicate ghost classes */ ierr = PartitionGhostNodeExchange(part, INSERT_VALUES, SCATTER_FORWARD, cm->classes, &cm->classes[cm->numNodes]); CHKERRQ(ierr); /* Setup class sizes */ ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizes); CHKERRQ(ierr); ierr = PetscMemzero(cm->classSizes, cm->numClasses * sizeof(int)); CHKERRQ(ierr); for(nclass = 0; nclass < cm->numClasses; nclass++) { for(f = 0; f < cm->numFields; f++) { field = cm->fields[f]; if (cm->fieldClasses[f][nclass]) { ierr = GridGetFieldComponents(grid, field, &comp); CHKERRQ(ierr); cm->classSizes[nclass] += comp; } } } /* Initialize constraint support */ ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->isClassConstrained); CHKERRQ(ierr); ierr = PetscMalloc(cm->numClasses * sizeof(int), &cm->classSizeDiffs); CHKERRQ(ierr); ierr = PetscMemzero(cm->isClassConstrained, cm->numClasses * sizeof(int)); CHKERRQ(ierr); ierr = PetscMemzero(cm->classSizeDiffs, cm->numClasses * sizeof(int)); CHKERRQ(ierr); PetscLogObjectMemory(cm, (cm->numFields + cm->numOverlapNodes + (cm->numFields + 4)*cm->numClasses) * sizeof(int) + cm->numFields * sizeof(int *)); PetscFunctionReturn(0); } EXTERN_C_END