1*5552b385SBrandon #include "petscsys.h" 2*5552b385SBrandon static const char help[] = "Test of PETSC/CAD Shape Modification Technology"; 3*5552b385SBrandon 4*5552b385SBrandon #include <petscdmplexegads.h> 5*5552b385SBrandon #include <petsc/private/hashmapi.h> 6*5552b385SBrandon 7*5552b385SBrandon static PetscErrorCode surfArea(DM dm) 8*5552b385SBrandon { 9*5552b385SBrandon DMLabel bodyLabel, faceLabel; 10*5552b385SBrandon double surfaceArea = 0., volume = 0.; 11*5552b385SBrandon PetscReal vol, centroid[3], normal[3]; 12*5552b385SBrandon PetscInt dim, cStart, cEnd, fStart, fEnd; 13*5552b385SBrandon PetscInt bodyID, faceID; 14*5552b385SBrandon MPI_Comm comm; 15*5552b385SBrandon const char *name; 16*5552b385SBrandon 17*5552b385SBrandon PetscFunctionBeginUser; 18*5552b385SBrandon PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 19*5552b385SBrandon PetscCall(PetscObjectGetName((PetscObject)dm, &name)); 20*5552b385SBrandon PetscCall(DMGetDimension(dm, &dim)); 21*5552b385SBrandon PetscCall(PetscPrintf(comm, " dim = %" PetscInt_FMT "\n", dim)); 22*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Body ID", &bodyLabel)); 23*5552b385SBrandon PetscCall(DMGetLabel(dm, "EGADS Face ID", &faceLabel)); 24*5552b385SBrandon PetscCall(DMGetCoordinatesLocalSetUp(dm)); 25*5552b385SBrandon 26*5552b385SBrandon if (dim == 2) { 27*5552b385SBrandon PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 28*5552b385SBrandon for (PetscInt ii = cStart; ii < cEnd; ++ii) { 29*5552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, ii, &faceID)); 30*5552b385SBrandon if (faceID >= 0) { 31*5552b385SBrandon PetscCall(DMPlexComputeCellGeometryFVM(dm, ii, &vol, centroid, normal)); 32*5552b385SBrandon surfaceArea += vol; 33*5552b385SBrandon } 34*5552b385SBrandon } 35*5552b385SBrandon } 36*5552b385SBrandon 37*5552b385SBrandon if (dim == 3) { 38*5552b385SBrandon PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd)); 39*5552b385SBrandon for (PetscInt ii = fStart; ii < fEnd; ++ii) { 40*5552b385SBrandon PetscCall(DMLabelGetValue(faceLabel, ii, &faceID)); 41*5552b385SBrandon if (faceID >= 0) { 42*5552b385SBrandon PetscCall(DMPlexComputeCellGeometryFVM(dm, ii, &vol, centroid, normal)); 43*5552b385SBrandon surfaceArea += vol; 44*5552b385SBrandon } 45*5552b385SBrandon } 46*5552b385SBrandon 47*5552b385SBrandon PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 48*5552b385SBrandon for (PetscInt ii = cStart; ii < cEnd; ++ii) { 49*5552b385SBrandon PetscCall(DMLabelGetValue(bodyLabel, ii, &bodyID)); 50*5552b385SBrandon if (bodyID >= 0) { 51*5552b385SBrandon PetscCall(DMPlexComputeCellGeometryFVM(dm, ii, &vol, centroid, normal)); 52*5552b385SBrandon volume += vol; 53*5552b385SBrandon } 54*5552b385SBrandon } 55*5552b385SBrandon } 56*5552b385SBrandon 57*5552b385SBrandon if (dim == 2) { 58*5552b385SBrandon PetscCall(PetscPrintf(comm, "%s Surface Area = %.6e \n\n", name, (double)surfaceArea)); 59*5552b385SBrandon } else if (dim == 3) { 60*5552b385SBrandon PetscCall(PetscPrintf(comm, "%s Volume = %.6e \n", name, (double)volume)); 61*5552b385SBrandon PetscCall(PetscPrintf(comm, "%s Surface Area = %.6e \n\n", name, (double)surfaceArea)); 62*5552b385SBrandon } 63*5552b385SBrandon PetscFunctionReturn(PETSC_SUCCESS); 64*5552b385SBrandon } 65*5552b385SBrandon 66*5552b385SBrandon int main(int argc, char *argv[]) 67*5552b385SBrandon { 68*5552b385SBrandon /* EGADSlite variables */ 69*5552b385SBrandon PetscGeom model, *bodies, *fobjs; 70*5552b385SBrandon int Nb, Nf, id; 71*5552b385SBrandon /* PETSc variables */ 72*5552b385SBrandon DM dm; 73*5552b385SBrandon MPI_Comm comm; 74*5552b385SBrandon PetscContainer modelObj, cpHashTableObj, wHashTableObj, cpCoordDataLengthObj, wDataLengthObj; 75*5552b385SBrandon Vec cntrlPtCoordsVec, cntrlPtWeightsVec; 76*5552b385SBrandon PetscScalar *cpCoordData, *wData; 77*5552b385SBrandon PetscInt cpCoordDataLength, wDataLength; 78*5552b385SBrandon PetscInt *cpCoordDataLengthPtr, *wDataLengthPtr; 79*5552b385SBrandon PetscHMapI cpHashTable, wHashTable; 80*5552b385SBrandon PetscInt Nr = 2; 81*5552b385SBrandon 82*5552b385SBrandon PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 83*5552b385SBrandon comm = PETSC_COMM_WORLD; 84*5552b385SBrandon PetscCall(DMCreate(PETSC_COMM_WORLD, &dm)); 85*5552b385SBrandon PetscCall(DMSetType(dm, DMPLEX)); 86*5552b385SBrandon PetscCall(DMPlexDistributeSetDefault(dm, PETSC_FALSE)); 87*5552b385SBrandon PetscCall(DMSetFromOptions(dm)); 88*5552b385SBrandon 89*5552b385SBrandon PetscCall(PetscObjectSetName((PetscObject)dm, "Original Surface")); 90*5552b385SBrandon PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 91*5552b385SBrandon PetscCall(surfArea(dm)); 92*5552b385SBrandon 93*5552b385SBrandon // Expose Geometry Definition Data and Calculate Surface Gradients 94*5552b385SBrandon PetscCall(DMPlexGeomDataAndGrads(dm, PETSC_FALSE)); 95*5552b385SBrandon 96*5552b385SBrandon // Get Attached EGADS model 97*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "EGADS Model", (PetscObject *)&modelObj)); 98*5552b385SBrandon if (!modelObj) PetscCall(PetscObjectQuery((PetscObject)dm, "EGADSlite Model", (PetscObject *)&modelObj)); 99*5552b385SBrandon 100*5552b385SBrandon // Get attached EGADS model (pointer) 101*5552b385SBrandon PetscCall(PetscContainerGetPointer(modelObj, (void **)&model)); 102*5552b385SBrandon 103*5552b385SBrandon // Look to see if DM has Container for Geometry Control Point Data 104*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Hash Table", (PetscObject *)&cpHashTableObj)); 105*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinates", (PetscObject *)&cntrlPtCoordsVec)); 106*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Coordinate Data Length", (PetscObject *)&cpCoordDataLengthObj)); 107*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weights Hash Table", (PetscObject *)&wHashTableObj)); 108*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data", (PetscObject *)&cntrlPtWeightsVec)); 109*5552b385SBrandon PetscCall(PetscObjectQuery((PetscObject)dm, "Control Point Weight Data Length", (PetscObject *)&wDataLengthObj)); 110*5552b385SBrandon 111*5552b385SBrandon // Get attached EGADS model Control Point and Weights Hash Tables and Data Arrays (pointer) 112*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpHashTableObj, (void **)&cpHashTable)); 113*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtCoordsVec, &cpCoordData)); 114*5552b385SBrandon PetscCall(PetscContainerGetPointer(cpCoordDataLengthObj, (void **)&cpCoordDataLengthPtr)); 115*5552b385SBrandon PetscCall(PetscContainerGetPointer(wHashTableObj, (void **)&wHashTable)); 116*5552b385SBrandon PetscCall(VecGetArrayWrite(cntrlPtWeightsVec, &wData)); 117*5552b385SBrandon PetscCall(PetscContainerGetPointer(wDataLengthObj, (void **)&wDataLengthPtr)); 118*5552b385SBrandon 119*5552b385SBrandon cpCoordDataLength = *cpCoordDataLengthPtr; 120*5552b385SBrandon wDataLength = *wDataLengthPtr; 121*5552b385SBrandon PetscCheck(cpCoordDataLength && wDataLength, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Data sizes must be positive"); 122*5552b385SBrandon 123*5552b385SBrandon // Get the number of bodies and body objects in the model 124*5552b385SBrandon PetscCall(DMPlexGetGeomModelBodies(dm, &bodies, &Nb)); 125*5552b385SBrandon 126*5552b385SBrandon // Get all FACES of the Body 127*5552b385SBrandon PetscGeom body = bodies[0]; 128*5552b385SBrandon PetscCall(DMPlexGetGeomModelBodyFaces(dm, body, &fobjs, &Nf)); 129*5552b385SBrandon 130*5552b385SBrandon // Update Control Point and Weight definitions for each surface 131*5552b385SBrandon for (PetscInt jj = 0; jj < Nf; ++jj) { 132*5552b385SBrandon PetscGeom face = fobjs[jj]; 133*5552b385SBrandon PetscInt numCntrlPnts = 0; 134*5552b385SBrandon 135*5552b385SBrandon PetscCall(DMPlexGetGeomID(dm, body, face, &id)); 136*5552b385SBrandon PetscCall(DMPlexGetGeomFaceNumOfControlPoints(dm, face, &numCntrlPnts)); 137*5552b385SBrandon 138*5552b385SBrandon // Update Control Points 139*5552b385SBrandon PetscHashIter CPiter, Witer; 140*5552b385SBrandon PetscBool CPfound, Wfound; 141*5552b385SBrandon PetscInt faceCPStartRow, faceWStartRow; 142*5552b385SBrandon 143*5552b385SBrandon PetscCall(PetscHMapIFind(cpHashTable, id, &CPiter, &CPfound)); 144*5552b385SBrandon PetscCheck(CPfound, comm, PETSC_ERR_SUP, "FACE ID not found in Control Point Hash Table"); 145*5552b385SBrandon PetscCall(PetscHMapIGet(cpHashTable, id, &faceCPStartRow)); 146*5552b385SBrandon 147*5552b385SBrandon PetscCall(PetscHMapIFind(wHashTable, id, &Witer, &Wfound)); 148*5552b385SBrandon PetscCheck(Wfound, comm, PETSC_ERR_SUP, "FACE ID not found in Control Point Weights Hash Table"); 149*5552b385SBrandon PetscCall(PetscHMapIGet(wHashTable, id, &faceWStartRow)); 150*5552b385SBrandon 151*5552b385SBrandon for (PetscInt ii = 0; ii < numCntrlPnts; ++ii) { 152*5552b385SBrandon if (ii == 4) { 153*5552b385SBrandon // Update Control Points - Change the location of the center control point of the faces 154*5552b385SBrandon // Note :: Modification geometry requires knowledge of how the geometry is defined. 155*5552b385SBrandon cpCoordData[faceCPStartRow + (3 * ii) + 0] = 2.0 * cpCoordData[faceCPStartRow + (3 * ii) + 0]; 156*5552b385SBrandon cpCoordData[faceCPStartRow + (3 * ii) + 1] = 2.0 * cpCoordData[faceCPStartRow + (3 * ii) + 1]; 157*5552b385SBrandon cpCoordData[faceCPStartRow + (3 * ii) + 2] = 2.0 * cpCoordData[faceCPStartRow + (3 * ii) + 2]; 158*5552b385SBrandon } else { 159*5552b385SBrandon // Do Nothing 160*5552b385SBrandon // Note: Could use section the change location of other face control points. 161*5552b385SBrandon } 162*5552b385SBrandon } 163*5552b385SBrandon } 164*5552b385SBrandon PetscCall(DMPlexFreeGeomObject(dm, fobjs)); 165*5552b385SBrandon 166*5552b385SBrandon // Modify Control Points of Geometry 167*5552b385SBrandon PetscCall(PetscObjectSetName((PetscObject)dm, "Modified Surface")); 168*5552b385SBrandon // TODO Wrap EG_saveModel() in a Plex viewer to manage file access 169*5552b385SBrandon PetscCall(DMPlexModifyGeomModel(dm, comm, cpCoordData, wData, PETSC_FALSE, PETSC_TRUE, "newModel.stp")); 170*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtCoordsVec, &cpCoordData)); 171*5552b385SBrandon PetscCall(VecRestoreArrayWrite(cntrlPtWeightsVec, &wData)); 172*5552b385SBrandon 173*5552b385SBrandon // Inflate Mesh to Geometry 174*5552b385SBrandon PetscCall(DMPlexInflateToGeomModel(dm, PETSC_FALSE)); 175*5552b385SBrandon PetscCall(surfArea(dm)); 176*5552b385SBrandon 177*5552b385SBrandon // Output .hdf5 file 178*5552b385SBrandon PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 179*5552b385SBrandon 180*5552b385SBrandon for (PetscInt r = 0; r < Nr; ++r) { 181*5552b385SBrandon char name[PETSC_MAX_PATH_LEN]; 182*5552b385SBrandon 183*5552b385SBrandon // Perform refinement on the Mesh attached to the new geometry 184*5552b385SBrandon PetscCall(DMSetFromOptions(dm)); 185*5552b385SBrandon PetscCall(PetscSNPrintf(name, PETSC_MAX_PATH_LEN, "Modified Surface refinement %" PetscInt_FMT, r)); 186*5552b385SBrandon PetscCall(PetscObjectSetName((PetscObject)dm, name)); 187*5552b385SBrandon PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 188*5552b385SBrandon PetscCall(surfArea(dm)); 189*5552b385SBrandon } 190*5552b385SBrandon 191*5552b385SBrandon PetscCall(DMDestroy(&dm)); 192*5552b385SBrandon PetscCall(PetscFinalize()); 193*5552b385SBrandon return 0; 194*5552b385SBrandon } 195*5552b385SBrandon 196*5552b385SBrandon /*TEST 197*5552b385SBrandon build: 198*5552b385SBrandon requires: egads 199*5552b385SBrandon 200*5552b385SBrandon # Use -dm_view hdf5:mesh_shapeMod_sphere.h5 to view the mesh 201*5552b385SBrandon test: 202*5552b385SBrandon suffix: sphere_shapeMod 203*5552b385SBrandon requires: datafilespath 204*5552b385SBrandon temporaries: newModel.stp 205*5552b385SBrandon args: -dm_plex_filename ${DATAFILESPATH}/meshes/cad/sphere_example.stp \ 206*5552b385SBrandon -dm_refine -dm_plex_geom_print_model 1 -dm_plex_geom_shape_opt 1 207*5552b385SBrandon 208*5552b385SBrandon TEST*/ 209