diff --git a/apf_sim/apfSIM.cc b/apf_sim/apfSIM.cc index a5b14a0d3..8132edfe7 100644 --- a/apf_sim/apfSIM.cc +++ b/apf_sim/apfSIM.cc @@ -542,6 +542,19 @@ class TagSIM comm = AttachDataCommu_new(unitSize/sizeof(int),0,count); PM_setMigrId(mesh,id); } + TagSIM(pParMesh m, + pMeshDataId simTag, + const char* n, + std::size_t unitSize, + int c): + count(c), + mesh(m), + id(simTag), + name(n) + { + comm = AttachDataCommu_new(unitSize/sizeof(int),0,count); + PM_setMigrId(mesh,id); + } virtual ~TagSIM() { MD_removeMeshCallback(id,CBdelete); @@ -650,6 +663,14 @@ class IntTagSIM : public TagSIM return 1; } + IntTagSIM(pParMesh m, pMeshDataId simTag, const char* name, int c): + TagSIM(m,simTag,name,sizeof(int),c) + { + MD_setMeshCallback(id,CBdelete,deleteIntCB,this); + MD_setMeshCallback(id,CBmigrateOut,pm_sendIntArray,comm); + MD_setMeshCallback(id,CBmigrateIn,pm_recvIntArray,comm); + } + IntTagSIM(pParMesh m, const char* name, int c): TagSIM(m,name,sizeof(int),c) { @@ -750,6 +771,15 @@ MeshTag* MeshSIM::createIntTag(const char* name, int size) return reinterpret_cast(tag); } +MeshTag* MeshSIM::createIntTag(const char* name, pMeshDataId simTag, int size) +{ + TagSIM* tag = new IntTagSIM(mesh,simTag,name,size); + tags.push_back(tag); + return reinterpret_cast(tag); +} + + + MeshTag* MeshSIM::createLongTag(const char* name, int size) { TagSIM* tag = new LongTagSIM(mesh,name,size); diff --git a/apf_sim/apfSIM.h b/apf_sim/apfSIM.h index dedfe020e..3d87bd4eb 100644 --- a/apf_sim/apfSIM.h +++ b/apf_sim/apfSIM.h @@ -60,6 +60,7 @@ class MeshSIM : public Mesh2 void getResidence(MeshEntity* e, Parts& residence); MeshTag* createDoubleTag(const char* name, int size); MeshTag* createIntTag(const char* name, int size); + MeshTag* createIntTag(const char* name, pMeshDataId simTag, int size); MeshTag* createLongTag(const char* name, int size); MeshTag* findTag(const char* name); void destroyTag(MeshTag* tag); diff --git a/pumi-meshes b/pumi-meshes index d03989485..7b84de7e3 160000 --- a/pumi-meshes +++ b/pumi-meshes @@ -1 +1 @@ -Subproject commit d0398948585a3a0487f0e6cc61fe591573531fc4 +Subproject commit 7b84de7e31d0d539acf83837cbce2dc0702c2bbc diff --git a/test/convert.cc b/test/convert.cc index bd27e6266..707a8d672 100644 --- a/test/convert.cc +++ b/test/convert.cc @@ -2,6 +2,7 @@ #include #include #include +#include #include #include #include @@ -11,14 +12,31 @@ #include #include #include +#include #include #include #include #include #include - +#include #include +#include + +apf::Field* convert_my_tag(apf::Mesh* m, apf::MeshTag* t) { + apf::MeshEntity* vtx; + apf::MeshIterator* it = m->begin(0); + apf::Field* f = apf::createFieldOn(m, "fathers2D_field", apf::SCALAR); + int vals[1]; + double vals_d; + while ((vtx = m->iterate(it))) { + m->getIntTag(vtx, t, vals); + vals_d = vals[0]; + apf::setScalar(f, vtx, 0, vals_d); + } + m->end(it); + return f; +} static void attachOrder(apf::Mesh* m) { @@ -54,6 +72,8 @@ const char* smb_path = NULL; int should_log = 0; int should_fix_pyramids = 1; int should_attach_order = 0; +const char* extruRootPath = NULL; +int ExtruRootId =0; bool found_bad_arg = false; void getConfig(int argc, char** argv) { @@ -64,6 +84,7 @@ void getConfig(int argc, char** argv) { {"no-pyramid-fix", no_argument, &should_fix_pyramids, 0}, {"attach-order", no_argument, &should_attach_order, 1}, {"enable-log", no_argument, &should_log, 2}, + {"model-face-root", required_argument, 0, 'e'}, {"native-model", required_argument, 0, 'n'}, {0, 0, 0, 0} // terminate the option array }; @@ -74,6 +95,7 @@ void getConfig(int argc, char** argv) { " --no-pyramid-fix Disable quad-connected pyramid tetrahedronization\n" " --attach-order Attach the Simmetrix element order as a Numbering\n" " --enable-log Enable Simmetrix logging\n" + " --model-face-root=/path/to/file ASCII input file with one integer per line listing the face ids that are the roots of mesh extrusions from SimModeler\n" " --native-model=/path/to/model Load the native Parasolid or ACIS model that the GeomSim model uses\n"; int option_index = 0; @@ -85,6 +107,9 @@ void getConfig(int argc, char** argv) { case 1: // attach order flag case 2: // enable simmetrix logging break; + case 'e': + extruRootPath = optarg; + break; case 'n': gmi_native_path = optarg; break; @@ -110,19 +135,165 @@ void getConfig(int argc, char** argv) { smb_path = argv[i++]; if (!PCU_Comm_Self()) { - printf ("fix_pyramids %d attach_order %d enable_log %d\n", - should_fix_pyramids, should_attach_order, should_log); + printf ("fix_pyramids %d attach_order %d enable_log %d extruRootPath %s\n", + should_fix_pyramids, should_attach_order, should_log, extruRootPath); printf ("native-model \'%s\' model \'%s\' simmetrix mesh \'%s\' output mesh \'%s\'\n", gmi_native_path, gmi_path, sms_path, smb_path); } } +// put the extrude tagging here which 1) loops over the mesh faces classified on the model face that is the root of the extrude +// create a tag on vertices fathers +// get the list of mesh rootfaces classified on the source geometric model face +// for each srcFace in rootfaces +// get the ids of downward adjacent vertices, store that as an array of size 3 +// get the upward adjacent region srcRgn +// call Extrusion_3DRegionsAndLayerFaces(srcRgn,...) +// for each face in the returned list of faces +// get the downward adjacent vertices of face - they will be in the same order as the srcFace ids +// set the fathers tag +// assert that the x,y coordinates of each vertex matches the srcFace vertex coordinates within some relaxed +// tolerance - sanity check my assumption that face-to-vtx adjaceny is always the same order +void addFathersTag(pGModel simModel, pParMesh sim_mesh, apf::Mesh* simApfMesh, const char* extrusionFaceFile) { + if(!extrusionFaceFile) return; + // create a tag on vertices fathers + pMeshDataId myFather = MD_newMeshDataId( "fathers2D"); + + pPList listV,listVn,regions,faces; + pFace face; + pRegion region; + pVertex vrts[4]; + int dir, err; + int count2D=0; + pGFace gface; + pGFace ExtruRootFace=NULL; + pVertex entV; + pMesh meshP= PM_mesh (sim_mesh, 0 ); + + char coordfilename[64]; + char cnnfilename[64]; + sprintf(coordfilename, "geom.crd"); + sprintf(cnnfilename, "geom.cnn"); + FILE* fcr = fopen(coordfilename, "w"); + FILE* fcn = fopen(cnnfilename, "w"); + + FILE* fid = fopen(extrusionFaceFile, "r"); // helper file that contains all faces with extrusions + assert(fid); + while(1 == fscanf(fid,"%d",&ExtruRootId)) { + fprintf(stderr,"ExtruRootId= %d \n",ExtruRootId); + //find the root face of the extrusion + GFIter gfIter=GM_faceIter(simModel); + while ( (gface=GFIter_next(gfIter))) { + int id = GEN_tag(gface); + if(id==ExtruRootId) ExtruRootFace=gface; + } + assert(ExtruRootFace != NULL); + + FIter fIter = M_classifiedFaceIter( meshP, ExtruRootFace, 0 ); // 0 says I don't want closure + while ((face = FIter_next(fIter))) { + dir=1; + listV= F_vertices(face, dir); + void *iter = 0; // Must initialize to 0 + int i=0; + while ((entV =(pVertex)PList_next(listV, &iter))) { //loop over plist of vertices + // Process each item in list + vrts[i] = (pVertex)entV; + i++; + } + int nvert=i; + PList_delete(listV); + + double coordNewPt[nvert][3]; + for(i=0; i< nvert ; i++) { + int* markedData; + if(!EN_getDataPtr((pEntity)vrts[i],myFather,(void**)&markedData)){ // not sure about marked yet + count2D++; + int* vtxData = new int[1]; + vtxData[0] = count2D; + EN_attachDataPtr((pEntity)vrts[i],myFather,(void*)vtxData); + V_coord(vrts[i],coordNewPt[i]); + + fprintf ( fcr, "%.15E %.15E %d \n", coordNewPt[i][0],coordNewPt[i][1], V_whatInType(vrts[i])); + } + } + + double coordFather[nvert][3]; + int fatherIds[4]; //store the ids of the fathers (vertices) on the root face + for(i=0; i< nvert ; i++) { + int* fatherIdPtr; + const int exists = EN_getDataPtr((pEntity)vrts[i],myFather,(void**)&fatherIdPtr); + assert(exists); + fatherIds[i] = fatherIdPtr[0]; + V_coord(vrts[i],coordFather[i]); + fprintf ( fcn, "%d ", fatherIds[i]); + } + fprintf ( fcn, "\n"); + + dir=0; // 1 fails + // get the upward adjacent region srcRgn + region = F_region(face, dir ); // 0 is the negative normal which I assume for a face on the boundary in is interior. + if(region==NULL) { // try other dir + dir=1; // 1 fails + region = F_region(face, dir ); // 0 is the negative normal which I assume for a face on the boundary in is interior. + } + + regions=PList_new(); + faces=PList_new(); + err = Extrusion_3DRegionsAndLayerFaces(region, regions, faces, 1); + if(err!=1 && !PCU_Comm_Self()) + fprintf(stderr, "Extrusion_3DRegionsAndLayerFaces returned %d for err \n", err); + + // for each face in the returned list of faces + iter=0; + pFace sonFace; + int iface=0; + dir=0; + while( (sonFace = (pFace)PList_next(faces, &iter)) ) { //loop over plist of vertices + if(iface !=0) { // root face is in the stack but we already took care of it above + // get the downward adjacent vertices of face - they will be in the same order as the srcFace ids + listVn= F_vertices(sonFace, dir); + void *iter2=0; // Must initialize to 0 + i=0; + int my2Dfath; + pVertex sonVtx; + double dist, dx, dy, distMin; + double coordSon[3]; + int iMin; + while( (sonVtx = (pVertex)PList_next(listVn, &iter2)) ) { //loop over plist of vertices + V_coord(sonVtx,coordSon); + distMin=1.0e7; + for(i=0; i< nvert; i++){ + dx=coordSon[0]-coordFather[i][0]; + dy=coordSon[1]-coordFather[i][1]; + dist=dx*dx+dy*dy; + if(dist < distMin) { + iMin=i; + distMin=dist; + } + } + my2Dfath=fatherIds[iMin]; + int* vtxData = new int[1]; + vtxData[0] = my2Dfath; + EN_attachDataPtr((pEntity)sonVtx,myFather,(void*)vtxData); + } + PList_delete(listVn); + } + iface++; + } + PList_delete(faces); + } //end root face iterator + } + apf::MeshSIM* cake = reinterpret_cast(simApfMesh); + cake->createIntTag("fathers2D", myFather, 1); +} + int main(int argc, char** argv) { MPI_Init(&argc, &argv); PCU_Comm_Init(); lion_set_verbosity(1); MS_init(); + SimAdvMeshing_start(); //for fancy BL/extrusion queries SimModel_start(); Sim_readLicenseFile(NULL); SimPartitionedMesh_start(&argc,&argv); @@ -153,7 +324,11 @@ int main(int argc, char** argv) double t1 = PCU_Time(); if(!PCU_Comm_Self()) fprintf(stderr, "read and created the simmetrix mesh in %f seconds\n", t1-t0); + apf::Mesh* simApfMesh = apf::createMesh(sim_mesh); + + addFathersTag(simModel, sim_mesh, simApfMesh, extruRootPath); + double t2 = PCU_Time(); if(!PCU_Comm_Self()) fprintf(stderr, "created the apf_sim mesh in %f seconds\n", t2-t1); diff --git a/test/testing.cmake b/test/testing.cmake index b9d7011e7..9dc958082 100644 --- a/test/testing.cmake +++ b/test/testing.cmake @@ -78,6 +78,18 @@ if(ENABLE_SIMMETRIX AND SIM_PARASOLID AND SIMMODSUITE_SimAdvMeshing_FOUND) add_test(NAME chef-BL_query-diff COMMAND diff -r run_case/4-procs_case/ good_case/4-procs_case WORKING_DIRECTORY ${MDIR}) + set(MDIR ${MESHES}/simExtrusionInfo) + mpi_test(convertExtrudedRoots 1 ${CMAKE_CURRENT_BINARY_DIR}/convert + --model-face-root=${MDIR}/ExtruRootID.txt + --native-model=${MDIR}/geom.xmt_txt + ${MDIR}/geom.smd ${MDIR}/geom.sms ${MDIR}/mdsMesh.smb + WORKING_DIRECTORY ${MDIR}) + add_test(NAME convertExtrudedRoots_diff_cnn + COMMAND diff -r geom.cnn geom_expected.cnn + WORKING_DIRECTORY ${MDIR}) + add_test(NAME convertExtrudedRoots_diff_crd + COMMAND diff -r geom.crd geom_expected.crd + WORKING_DIRECTORY ${MDIR}) endif() if(ENABLE_SIMMETRIX AND SIM_PARASOLID AND SIMMODSUITE_SimAdvMeshing_FOUND)