void MVertex::deleteLast() { GModel *m = GModel::current(); if(_num == m->getMaxVertexNumber()) m->setMaxVertexNumber(m->getMaxVertexNumber() - 1); delete this; }
int main(int argc, char **argv) { GmshInitialize(argc, argv); GmshSetOption("Mesh", "Algorithm", 5.); GmshSetOption("General", "Terminal", 1.); GModel *m = new GModel(); m->readMSH("bunny.msh"); m->fillVertexArrays(); std::vector<GEntity*> entities; m->getEntities(entities); for(unsigned int i = 0; i < entities.size(); i++){ GEntity *ge = entities[i]; printf("coucou entite %d (dimension %d)\n", ge->tag(), ge->dim()); if(ge->va_triangles) printf(" j'ai un va de triangles: %d vertex\n", ge->va_triangles->getNumVertices()); if(ge->va_lines) printf(" j'ai un va de lignes: %d vertex\n", ge->va_lines->getNumVertices()); } delete m; GmshFinalize(); }
/***********************************************************************//** * @brief Test unbinned optimizer ***************************************************************************/ void TestGCTAOptimize::test_unbinned_optimizer(void) { // Declare observations GObservations obs; GCTAObservation run; // Load unbinned CTA observation test_try("Load unbinned CTA observation"); try { run.load_unbinned(cta_events); run.response(cta_irf,cta_caldb); obs.append(run); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Load models from XML file obs.models(cta_model_xml); // Perform LM optimization double fit_results[] = {83.6331, 0, 22.0145, 0, 5.656246512e-16, 1.91458426e-17, -2.484100472, -0.02573396361, 300000, 0, 1, 0, 2.993705325, 0.03572658413, 6.490832107e-05, 1.749021094e-06, -1.833584022, -0.01512223495, 1000000, 0, 1, 0}; test_try("Perform LM optimization"); try { GOptimizerLM opt; opt.max_iter(100); obs.optimize(opt); test_try_success(); for (int i = 0, j = 0; i < obs.models().size(); ++i) { GModel* model = obs.models()[i]; for (int k = 0; k < model->size(); ++k) { GModelPar& par = (*model)[k]; std::string msg = "Verify optimization result for " + par.print(); test_value(par.real_value(), fit_results[j++], 5.0e-5, msg); test_value(par.real_error(), fit_results[j++], 5.0e-5, msg); } } } catch (std::exception &e) { test_try_failure(e); } // Exit test return; }
/***********************************************************************//** * @brief Test binned optimizer ***************************************************************************/ void TestGCTAOptimize::test_binned_optimizer(void) { // Declare observations GObservations obs; GCTAObservation run; // Load binned CTA observation test_try("Load binned CTA observation"); try { run.load_binned(cta_cntmap); run.response(cta_irf,cta_caldb); obs.append(run); test_try_success(); } catch (std::exception &e) { test_try_failure(e); } // Load models from XML file obs.models(cta_model_xml); // Perform LM optimization double fit_results[] = {83.6331, 0, 22.0145, 0, 5.616410411e-16, 1.904730785e-17, -2.481781246, -0.02580905077, 300000, 0, 1, 0, 2.933677595, 0.06639644824, 6.550723074e-05, 1.945714239e-06, -1.833781187, -0.0161464076, 1000000, 0, 1, 0}; test_try("Perform LM optimization"); try { GOptimizerLM opt; opt.max_iter(100); obs.optimize(opt); test_try_success(); for (int i = 0, j = 0; i < obs.models().size(); ++i) { GModel* model = obs.models()[i]; for (int k = 0; k < model->size(); ++k) { GModelPar& par = (*model)[k]; std::string msg = "Verify optimization result for " + par.print(); test_value(par.real_value(), fit_results[j++], 5.0e-5, msg); test_value(par.real_error(), fit_results[j++], 5.0e-5, msg); } } } catch (std::exception &e) { test_try_failure(e); } // Exit test return; }
void Filler::treat_model(){ GRegion* gr; GModel* model = GModel::current(); GModel::riter it; for(it=model->firstRegion();it!=model->lastRegion();it++) { gr = *it; if(gr->getNumMeshElements()>0){ treat_region(gr); } } }
/***********************************************************************//** * @brief Model function evaluation for gradient computation * * @param[in] x Function value. ***************************************************************************/ double GObservation::model_func::eval(double x) { // Get non-const model pointer (circumvent const correctness) GModel* model = const_cast<GModel*>(m_model); // Set value (*model)[m_ipar].value(x); // Compute model value double value = model->eval(*m_event, *m_parent); // Return value return value; }
void collapseSmallEdges(GModel &gm) { return; // gm.renumberMeshVertices(true); std::list<GFace*> faces; for (GModel::fiter fit = gm.firstFace(); fit != gm.lastFace(); fit++){ faces.push_back(*fit); } BDS_Mesh *pm = gmsh2BDS(faces); outputScalarField(pm->triangles, "all.pos", 0); for (GModel::eiter eit = gm.firstEdge(); eit != gm.lastEdge(); eit++){ } delete pm; }
void gcm::Geo2MeshLoader::createMshFile(string fileName, float tetrSize) { Engine& engine = Engine::getInstance(); if( engine.getNumberOfWorkers() > 1 ) { if( engine.getRank() != 0 ) { MPI::COMM_WORLD.Barrier(); createdFiles[fileName] = true; return; } } /* * TODO@ashevtsov: I don't really understand the meaning of all these options, values * have been guessed to get a mesh with acceptable tetrahedra sizes. * In future need to undestand GMsh meshing algorithms and set these options correctly. */ LOG_DEBUG("loadGeoScriptFile (" << fileName << "): will mesh with H = " << tetrSize); GmshSetOption("General", "Terminal", 1.0); GmshSetOption("General", "Verbosity", engine.getGmshVerbosity()); GmshSetOption("Mesh", "CharacteristicLengthMin", tetrSize); GmshSetOption("Mesh", "CharacteristicLengthMax", tetrSize); GmshSetOption("Mesh", "Optimize", 1.0); GModel gmshModel; gmshModel.setFactory ("Gmsh"); gmshModel.readGEO (fileName); LOG_INFO("Creating mesh using gmsh library"); gmshModel.mesh (3); gmshModel.writeMSH (getMshFileName(fileName)); createdFiles[fileName] = true; if (engine.getNumberOfWorkers() > 1) MPI::COMM_WORLD.Barrier(); }
MVertex::MVertex(double x, double y, double z, GEntity *ge, int num) : _visible(1), _order(1), _x(x), _y(y), _z(z), _ge(ge) { #if defined(_OPENMP) #pragma omp critical #endif { // we should make GModel a mandatory argument to the constructor GModel *m = GModel::current(); if(num){ _num = num; m->setMaxVertexNumber(std::max(m->getMaxVertexNumber(), _num)); } else{ m->setMaxVertexNumber(m->getMaxVertexNumber() + 1); _num = m->getMaxVertexNumber(); } _index = num; } }
int GModel::readMED(const std::string &name) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0) { Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } med_int v[3], vf[3]; MEDversionDonner(&v[0], &v[1], &v[2]); MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); Msg::Info("Reading MED file V%d.%d.%d using MED library V%d.%d.%d", vf[0], vf[1], vf[2], v[0], v[1], v[2]); if(vf[0] < 2 || (vf[0] == 2 && vf[1] < 2)){ Msg::Error("Cannot read MED file older than V2.2"); return 0; } std::vector<std::string> meshNames; for(int i = 0; i < MEDnMaa(fid); i++){ char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim, nStep; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, i + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, i + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } meshNames.push_back(meshName); } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } int ret = 1; for(unsigned int i = 0; i < meshNames.size(); i++){ // we use the filename as a kind of "partition" indicator, allowing to // complete a model part by part (used e.g. in DDM, since MED does not store // a partition index) GModel *m = findByName(meshNames[i], name); if(!m) m = new GModel(meshNames[i]); ret = m->readMED(name, i); if(!ret) return 0; } return ret; } int GModel::readMED(const std::string &name, int meshIndex) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_LECTURE); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } int numMeshes = MEDnMaa(fid); if(meshIndex >= numMeshes){ Msg::Info("Could not find mesh %d in MED file", meshIndex); return 0; } checkPointMaxNumbers(); GModel::setCurrent(this); // make sure we increment max nums in this model // read mesh info char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1]; med_int spaceDim, nStep = 1; med_maillage meshType; #if (MED_MAJOR_NUM == 3) med_int meshDim; char dtUnit[MED_SNAME_SIZE + 1]; char axisName[3 * MED_SNAME_SIZE + 1], axisUnit[3 * MED_SNAME_SIZE + 1]; med_sorting_type sortingType; med_axis_type axisType; if(MEDmeshInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshDim, &meshType, meshDesc, dtUnit, &sortingType, &nStep, &axisType, axisName, axisUnit) < 0){ #else if(MEDmaaInfo(fid, meshIndex + 1, meshName, &spaceDim, &meshType, meshDesc) < 0){ #endif Msg::Error("Unable to read mesh information"); return 0; } // FIXME: we should support multi-step MED3 meshes (probably by // storing each mesh as a separate model, with a naming convention // e.g. meshName_step%d). This way we could also handle multi-mesh // time sequences in MED3. if(nStep > 1) Msg::Warning("Discarding %d last meshes in multi-step MED mesh", nStep - 1); setName(meshName); setFileName(name); if(meshType == MED_NON_STRUCTURE){ Msg::Info("Reading %d-D unstructured mesh <<%s>>", spaceDim, meshName); } else{ Msg::Error("Reading structured MED meshes is not supported"); return 0; } med_int vf[3]; MEDversionLire(fid, &vf[0], &vf[1], &vf[2]); // read nodes #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord, geoTransform; med_int numNodes = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, MED_COORDINATE, MED_NO_CMODE, &changeOfCoord, &geoTransform); #else med_int numNodes = MEDnEntMaa(fid, meshName, MED_COOR, MED_NOEUD, MED_NONE, MED_NOD); #endif if(numNodes < 0){ Msg::Error("Could not read number of MED nodes"); return 0; } if(numNodes == 0){ Msg::Error("No nodes in MED mesh"); return 0; } std::vector<MVertex*> verts(numNodes); std::vector<med_float> coord(spaceDim * numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeCoordinateRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_FULL_INTERLACE, &coord[0]) < 0){ #else std::vector<char> coordName(spaceDim * MED_TAILLE_PNOM + 1); std::vector<char> coordUnit(spaceDim * MED_TAILLE_PNOM + 1); med_repere rep; if(MEDcoordLire(fid, meshName, spaceDim, &coord[0], MED_FULL_INTERLACE, MED_ALL, 0, 0, &rep, &coordName[0], &coordUnit[0]) < 0){ #endif Msg::Error("Could not read MED node coordinates"); return 0; } std::vector<med_int> nodeTags(numNodes); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_NODE, MED_NO_GEOTYPE, &nodeTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &nodeTags[0], numNodes, MED_NOEUD, MED_NONE) < 0) #endif nodeTags.clear(); for(int i = 0; i < numNodes; i++) verts[i] = new MVertex(coord[spaceDim * i], (spaceDim > 1) ? coord[spaceDim * i + 1] : 0., (spaceDim > 2) ? coord[spaceDim * i + 2] : 0., 0, nodeTags.empty() ? 0 : nodeTags[i]); // read elements (loop over all possible MSH element types) for(int mshType = 0; mshType < MSH_NUM_TYPE; mshType++){ med_geometrie_element type = msh2medElementType(mshType); if(type == MED_NONE) continue; #if (MED_MAJOR_NUM == 3) med_bool changeOfCoord; med_bool geoTransform; med_int numEle = MEDmeshnEntity(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_CONNECTIVITY, MED_NODAL, &changeOfCoord, &geoTransform); #else med_int numEle = MEDnEntMaa(fid, meshName, MED_CONN, MED_MAILLE, type, MED_NOD); #endif if(numEle <= 0) continue; int numNodPerEle = type % 100; std::vector<med_int> conn(numEle * numNodPerEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshElementConnectivityRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, &conn[0]) < 0){ #else if(MEDconnLire(fid, meshName, spaceDim, &conn[0], MED_FULL_INTERLACE, 0, MED_ALL, MED_MAILLE, type, MED_NOD) < 0){ #endif Msg::Error("Could not read MED elements"); return 0; } std::vector<med_int> fam(numEle, 0); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityFamilyNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &fam[0]) < 0){ #else if(MEDfamLire(fid, meshName, &fam[0], numEle, MED_MAILLE, type) < 0){ #endif Msg::Info("No family number for elements: using 0 as default family number"); } std::vector<med_int> eleTags(numEle); #if (MED_MAJOR_NUM == 3) if(MEDmeshEntityNumberRd(fid, meshName, MED_NO_DT, MED_NO_IT, MED_CELL, type, &eleTags[0]) < 0) #else if(MEDnumLire(fid, meshName, &eleTags[0], numEle, MED_MAILLE, type) < 0) #endif eleTags.clear(); std::map<int, std::vector<MElement*> > elements; MElementFactory factory; for(int j = 0; j < numEle; j++){ std::vector<MVertex*> v(numNodPerEle); for(int k = 0; k < numNodPerEle; k++) v[k] = verts[conn[numNodPerEle * j + med2mshNodeIndex(type, k)] - 1]; MElement *e = factory.create(mshType, v, eleTags.empty() ? 0 : eleTags[j]); if(e) elements[-fam[j]].push_back(e); } _storeElementsInEntities(elements); } _associateEntityWithMeshVertices(); _storeVerticesInEntities(verts); // read family info med_int numFamilies = MEDnFam(fid, meshName); if(numFamilies < 0){ Msg::Error("Could not read MED families"); return 0; } for(int i = 0; i < numFamilies; i++){ #if (MED_MAJOR_NUM == 3) med_int numAttrib = (vf[0] == 2) ? MEDnFamily23Attribute(fid, meshName, i + 1) : 0; med_int numGroups = MEDnFamilyGroup(fid, meshName, i + 1); #else med_int numAttrib = MEDnAttribut(fid, meshName, i + 1); med_int numGroups = MEDnGroupe(fid, meshName, i + 1); #endif if(numAttrib < 0 || numGroups < 0){ Msg::Error("Could not read MED groups or attributes"); return 0; } std::vector<med_int> attribId(numAttrib + 1); std::vector<med_int> attribVal(numAttrib + 1); std::vector<char> attribDes(MED_TAILLE_DESC * numAttrib + 1); std::vector<char> groupNames(MED_TAILLE_LNOM * numGroups + 1); char familyName[MED_TAILLE_NOM + 1]; med_int familyNum; #if (MED_MAJOR_NUM == 3) if(vf[0] == 2){ // MED2 file if(MEDfamily23Info(fid, meshName, i + 1, familyName, &attribId[0], &attribVal[0], &attribDes[0], &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED2 family %d", i + 1); continue; } } else{ if(MEDfamilyInfo(fid, meshName, i + 1, familyName, &familyNum, &groupNames[0]) < 0){ Msg::Error("Could not read info for MED3 family %d", i + 1); continue; } } #else if(MEDfamInfo(fid, meshName, i + 1, familyName, &familyNum, &attribId[0], &attribVal[0], &attribDes[0], &numAttrib, &groupNames[0], &numGroups) < 0){ Msg::Error("Could not read info for MED family %d", i + 1); continue; } #endif // family tags are unique (for all dimensions) GEntity *ge; if((ge = getRegionByTag(-familyNum))){} else if((ge = getFaceByTag(-familyNum))){} else if((ge = getEdgeByTag(-familyNum))){} else ge = getVertexByTag(-familyNum); if(ge){ elementaryNames[std::pair<int, int>(ge->dim(), -familyNum)] = familyName; if(numGroups > 0){ for(int j = 0; j < numGroups; j++){ char tmp[MED_TAILLE_LNOM + 1]; strncpy(tmp, &groupNames[j * MED_TAILLE_LNOM], MED_TAILLE_LNOM); tmp[MED_TAILLE_LNOM] = '\0'; // don't use same physical number across dimensions, as e.g. getdp // does not support this int pnum = setPhysicalName(tmp, ge->dim(), getMaxPhysicalNumber(-1) + 1); if(std::find(ge->physicals.begin(), ge->physicals.end(), pnum) == ge->physicals.end()) ge->physicals.push_back(pnum); } } } } // check if we need to read some post-processing data later #if (MED_MAJOR_NUM == 3) bool postpro = (MEDnField(fid) > 0) ? true : false; #else bool postpro = (MEDnChamp(fid, 0) > 0) ? true : false; #endif if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return postpro ? 2 : 1; } template<class T> static void fillElementsMED(med_int family, std::vector<T*> &elements, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element &type) { if(elements.empty()) return; type = msh2medElementType(elements[0]->getTypeForMSH()); if(type == MED_NONE){ Msg::Warning("Unsupported element type in MED format"); return; } for(unsigned int i = 0; i < elements.size(); i++){ elements[i]->setVolumePositive(); for(int j = 0; j < elements[i]->getNumVertices(); j++) conn.push_back(elements[i]->getVertex(med2mshNodeIndex(type, j))->getIndex()); fam.push_back(family); } } static void writeElementsMED(med_idt &fid, char *meshName, std::vector<med_int> &conn, std::vector<med_int> &fam, med_geometrie_element type) { if(fam.empty()) return; #if (MED_MAJOR_NUM == 3) if(MEDmeshElementWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_CELL, type, MED_NODAL, MED_FULL_INTERLACE, (med_int)fam.size(), &conn[0], MED_FALSE, 0, MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else if(MEDelementsEcr(fid, meshName, (med_int)3, &conn[0], MED_FULL_INTERLACE, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size(), MED_MAILLE, type, MED_NOD) < 0) #endif Msg::Error("Could not write MED elements"); } int GModel::writeMED(const std::string &name, bool saveAll, double scalingFactor) { med_idt fid = MEDouvrir((char*)name.c_str(), MED_CREATION); if(fid < 0){ Msg::Error("Unable to open file '%s'", name.c_str()); return 0; } // write header if(MEDfichDesEcr(fid, (char*)"MED file generated by Gmsh") < 0){ Msg::Error("Unable to write MED descriptor"); return 0; } char *meshName = (char*)getName().c_str(); // Gmsh always writes 3D unstructured meshes #if (MED_MAJOR_NUM == 3) char dtUnit[MED_SNAME_SIZE + 1] = ""; char axisName[3 * MED_SNAME_SIZE + 1] = ""; char axisUnit[3 * MED_SNAME_SIZE + 1] = ""; if(MEDmeshCr(fid, meshName, 3, 3, MED_UNSTRUCTURED_MESH, "Mesh created with Gmsh", dtUnit, MED_SORT_DTIT, MED_CARTESIAN, axisName, axisUnit) < 0){ #else if(MEDmaaCr(fid, meshName, 3, MED_NON_STRUCTURE, (char*)"Mesh created with Gmsh") < 0){ #endif Msg::Error("Could not create MED mesh"); return 0; } // if there are no physicals we save all the elements if(noPhysicalGroups()) saveAll = true; // index the vertices we save in a continuous sequence (MED // connectivity is given in terms of vertex indices) indexMeshVertices(saveAll); // get a vector containing all the geometrical entities in the // model (the ordering of the entities must be the same as the one // used during the indexing of the vertices) std::vector<GEntity*> entities; getEntities(entities); std::map<GEntity*, int> families; // write the families { // always create a "0" family, with no groups or attributes #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, "F_0", 0, 0, "") < 0) #else if(MEDfamCr(fid, meshName, (char*)"F_0", 0, 0, 0, 0, 0, 0, 0) < 0) #endif Msg::Error("Could not create MED family 0"); // create one family per elementary entity, with one group per // physical entity and no attributes for(unsigned int i = 0; i < entities.size(); i++){ if(saveAll || entities[i]->physicals.size()){ int num = - ((int)families.size() + 1); families[entities[i]] = num; std::ostringstream fs; fs << entities[i]->dim() << "D_" << entities[i]->tag(); std::string familyName = "F_" + fs.str(); std::string groupName; for(unsigned j = 0; j < entities[i]->physicals.size(); j++){ std::string tmp = getPhysicalName (entities[i]->dim(), entities[i]->physicals[j]); if(tmp.empty()){ // create unique name std::ostringstream gs; gs << entities[i]->dim() << "D_" << entities[i]->physicals[j]; groupName += "G_" + gs.str(); } else groupName += tmp; groupName.resize((j + 1) * MED_TAILLE_LNOM, ' '); } #if (MED_MAJOR_NUM == 3) if(MEDfamilyCr(fid, meshName, familyName.c_str(), (med_int)num, (med_int)entities[i]->physicals.size(), groupName.c_str()) < 0) #else if(MEDfamCr(fid, meshName, (char*)familyName.c_str(), (med_int)num, 0, 0, 0, 0, (char*)groupName.c_str(), (med_int)entities[i]->physicals.size()) < 0) #endif Msg::Error("Could not create MED family %d", num); } } } // write the nodes { std::vector<med_float> coord; std::vector<med_int> fam; for(unsigned int i = 0; i < entities.size(); i++){ for(unsigned int j = 0; j < entities[i]->mesh_vertices.size(); j++){ MVertex *v = entities[i]->mesh_vertices[j]; if(v->getIndex() >= 0){ coord.push_back(v->x() * scalingFactor); coord.push_back(v->y() * scalingFactor); coord.push_back(v->z() * scalingFactor); fam.push_back(0); // we never create node families } } } if(fam.empty()){ Msg::Error("No nodes to write in MED mesh"); return 0; } #if (MED_MAJOR_NUM == 3) if(MEDmeshNodeWr(fid, meshName, MED_NO_DT, MED_NO_IT, 0., MED_FULL_INTERLACE, (med_int)fam.size(), &coord[0], MED_FALSE, "", MED_FALSE, 0, MED_TRUE, &fam[0]) < 0) #else char coordName[3 * MED_TAILLE_PNOM + 1] = "x y z "; char coordUnit[3 * MED_TAILLE_PNOM + 1] = "unknown unknown unknown "; if(MEDnoeudsEcr(fid, meshName, (med_int)3, &coord[0], MED_FULL_INTERLACE, MED_CART, coordName, coordUnit, 0, MED_FAUX, 0, MED_FAUX, &fam[0], (med_int)fam.size()) < 0) #endif Msg::Error("Could not write nodes"); } // write the elements { { // points med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(viter it = firstVertex(); it != lastVertex(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->points, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // lines med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(eiter it = firstEdge(); it != lastEdge(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->lines, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // triangles med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->triangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // quads med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(fiter it = firstFace(); it != lastFace(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->quadrangles, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // tets med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->tetrahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // hexas med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->hexahedra, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // prisms med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->prisms, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } { // pyramids med_geometrie_element typ = MED_NONE; std::vector<med_int> conn, fam; for(riter it = firstRegion(); it != lastRegion(); it++) if(saveAll || (*it)->physicals.size()) fillElementsMED(families[*it], (*it)->pyramids, conn, fam, typ); writeElementsMED(fid, meshName, conn, fam, typ); } } if(MEDfermer(fid) < 0){ Msg::Error("Unable to close file '%s'", (char*)name.c_str()); return 0; } return 1; } #else int GModel::readMED(const std::string &name) { Msg::Error("Gmsh must be compiled with MED support to read '%s'", name.c_str()); return 0; }
/***********************************************************************//** * @brief Run maximum likelihood analysis * * The following analysis steps are performed: * 1. Read the parameters (and write them into logger) * 2. Load observation * 3. Setup models for optimizing * 4. Optimize model (and write result into logger) ***************************************************************************/ void ctlike::run(void) { // Switch screen logging on in debug mode if (logDebug()) { log.cout(true); } // Get parameters get_parameters(); // Write parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Set energy dispersion flag for all CTA observations and save old // values in save_edisp vector std::vector<bool> save_edisp; save_edisp.assign(m_obs.size(), false); for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { save_edisp[i] = obs->response()->apply_edisp(); obs->response()->apply_edisp(m_apply_edisp); } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Optimize model parameters using LM optimizer optimize_lm(); // Store Npred double npred = m_obs.npred(); // Store models for which TS should be computed std::vector<std::string> ts_srcs; GModels models_orig = m_obs.models(); for (int i = 0; i < models_orig.size(); ++i) { GModel* model = models_orig[i]; if (model->tscalc()) { ts_srcs.push_back(model->name()); } } // Compute TS values if requested if (!ts_srcs.empty()) { // Store original maximum likelihood and models double logL_src = m_logL; GModels models = m_obs.models(); // Fix spatial parameters if requested if (m_fix_spat_for_ts) { // Loop over all models for (int i = 0; i < models.size(); ++i) { // Continue only if model is skymodel GModelSky* sky= dynamic_cast<GModelSky*>(models[i]); if (sky != NULL) { // Fix spatial parameters GModelSpatial* spatial = sky->spatial(); for (int j = 0; j < spatial->size(); j++) { (*spatial)[j].fix(); } // endfor: looped over spatial parameters } // endif: there was a sky model } // endfor: looped over models } // endif: spatial parameter should be fixed // Loop over stored models, remove source and refit for (int i = 0; i < ts_srcs.size(); ++i) { models.remove(ts_srcs[i]); m_obs.models(models); double logL_nosrc = reoptimize_lm(); double ts = 2.0 * (logL_src-logL_nosrc); models_orig[ts_srcs[i]]->ts(ts); models = models_orig; } // Restore best fit values m_obs.models(models_orig); } // Compute number of observed events in all observations double num_events = 0.0; for (int i = 0; i < m_obs.size(); ++i) { double data = m_obs[i]->events()->number(); if (data >= 0.0) { num_events += data; } } // Write results into logger if (logTerse()) { log << std::endl; log.header1("Maximum likelihood optimisation results"); log << *m_opt << std::endl; log << gammalib::parformat("Maximum log likelihood"); log << gammalib::str(m_logL,3) << std::endl; log << gammalib::parformat("Observed events (Nobs)"); log << gammalib::str(num_events, 3) << std::endl; log << gammalib::parformat("Predicted events (Npred)"); log << gammalib::str(npred, 3); log << " (Nobs - Npred = "; log << gammalib::str(num_events-npred); log << ")" << std::endl; log << m_obs.models() << std::endl; } // Restore energy dispersion flag for all CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { obs->response()->apply_edisp(save_edisp[i]); } } // Return return; }
PView *GMSH_BubblesPlugin::execute(PView *v) { double shrink = (double)BubblesOptions_Number[0].def; std::string fileName = BubblesOptions_String[0].def; FILE *fp = Fopen(fileName.c_str(), "w"); if(!fp){ Msg::Error("Could not open output file '%s'", fileName.c_str()); return v; } GModel *m = GModel::current(); int p = m->getMaxElementaryNumber(0) + 1; int l = m->getMaxElementaryNumber(1) + 1; int s = m->getMaxElementaryNumber(2) + 1; int ll = s, ps = 1; SBoundingBox3d bbox = m->bounds(); double lc = norm(SVector3(bbox.max(), bbox.min())) / 100; fprintf(fp, "lc = %g;\n", lc); for(GModel::viter vit = m->firstVertex(); vit != m->lastVertex(); vit++) (*vit)->writeGEO(fp, "lc"); for(GModel::eiter eit = m->firstEdge(); eit != m->lastEdge(); eit++) (*eit)->writeGEO(fp); for(GModel::fiter fit = m->firstFace(); fit != m->lastFace(); fit++){ (*fit)->writeGEO(fp); fprintf(fp, "Delete { Surface {%d}; }\n", (*fit)->tag()); int sbeg = s; int llbeg = ll; // compute vertex-to-triangle_barycenter map std::map<MVertex*, std::vector<SPoint3> > v2t; for(unsigned int i = 0; i < (*fit)->triangles.size(); i++) for(int j = 0; j < 3; j++) v2t[(*fit)->triangles[i]->getVertex(j)].push_back((*fit)->triangles[i]->barycenter()); // add boundary vertices in map to get cells "closer" to the boundary for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ MVertex *v = it->first; if(v->onWhat() && v->onWhat()->dim() < 2) it->second.push_back(SPoint3(it->first->x(), it->first->y(), it->first->z())); } for(std::map<MVertex*, std::vector<SPoint3> >::iterator it = v2t.begin(); it != v2t.end(); it++){ if(it->second.size() > 2){ // get barycenter of cell boundary points and order them SPoint3 bc; for(unsigned int i = 0; i < it->second.size(); i++) bc += it->second[i]; bc *= 1. / (double)it->second.size(); compareAngle comp(bc); std::sort(it->second.begin(), it->second.end(), comp); // shrink cells if(shrink){ for(unsigned int i = 0; i < it->second.size(); i++){ double dir[3] = {it->second[i].x() - bc.x(), it->second[i].y() - bc.y(), it->second[i].z() - bc.z()}; it->second[i][0] -= shrink * dir[0]; it->second[i][1] -= shrink * dir[1]; it->second[i][2] -= shrink * dir[2]; } } // create b-spline bounded surface for each cell int nump = it->second.size(); for(int i = 0; i < nump; i++){ SPoint3 &b(it->second[i]); fprintf(fp, "Point(%d) = {%.16g, %.16g, %.16g, lc};\n", p++, b.x(), b.y(), b.z()); } fprintf(fp, "BSpline(%d) = {", l++); for(int i = nump - 1; i >= 0; i--) fprintf(fp, "%d,", p - i - 1); fprintf(fp, "%d};\n", p - nump); fprintf(fp, "Line Loop(%d) = {%d};\n", ll++, l - 1); fprintf(fp, "Plane Surface(%d) = {%d};\n", s++, ll - 1); } } fprintf(fp, "Physical Surface(%d) = {%d:%d};\n", ps++, sbeg, s - 1); fprintf(fp, "Plane Surface(%d) = {%d, %d:%d};\n", s++, (*fit)->tag(), llbeg, ll - 1); fprintf(fp, "Physical Surface(%d) = {%d};\n", ps++, s - 1); } fclose(fp); return v; }
/***********************************************************************//** * @brief Computes ***************************************************************************/ void cterror::run(void) { // If we're in debug mode then all output is also dumped on the screen if (logDebug()) { log.cout(true); } // Get task parameters get_parameters(); // Write parameters into logger if (logTerse()) { log_parameters(); log << std::endl; } // Set energy dispersion flag for all CTA observations and save old // values in save_edisp vector std::vector<bool> save_edisp; save_edisp.assign(m_obs.size(), false); for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { save_edisp[i] = obs->response()->apply_edisp(); obs->response()->apply_edisp(m_apply_edisp); } } // Write observation(s) into logger if (logTerse()) { log << std::endl; if (m_obs.size() > 1) { log.header1("Observations"); } else { log.header1("Observation"); } log << m_obs << std::endl; } // Write header if (logTerse()) { log << std::endl; log.header1("Compute best-fit likelihood"); } // Optimize and save best log-likelihood m_obs.optimize(m_opt); m_obs.errors(m_opt); m_best_logL = m_obs.logL(); // Store optimizer for later recovery GOptimizerLM best_opt = m_opt; // Write optimised model into logger if (logTerse()) { log << m_opt << std::endl; log << gammalib::parformat("Maximum log likelihood"); log << gammalib::str(m_best_logL,3) << std::endl; log << m_obs.models() << std::endl; } // Continue only if source model exists if (m_obs.models().contains(m_srcname)) { // Save best fitting models GModels models_best = m_obs.models(); // Get pointer on model GModel* model = models_best[m_srcname]; // Get number of parameters int npars = model->size(); // Loop over parameters of sky model for (int i = 0; i < npars; ++i) { // Skip parameter if it is fixed if (model->at(i).is_fixed()) { continue; } // Initialise with best fitting models m_obs.models(models_best); // Get pointer on model parameter GModels& current_models = const_cast<GModels&>(m_obs.models()); m_model_par = &(current_models[m_srcname]->at(i)); // Extract current value m_value = m_model_par->factor_value(); // Compute parameter bracketing double parmin = std::max(m_model_par->factor_min(), m_value - 10.0*m_model_par->factor_error()); double parmax = std::min(m_model_par->factor_max(), m_value + 10.0*m_model_par->factor_error()); // Write header if (logTerse()) { log << std::endl; log.header1("Compute error for source \""+m_srcname+"\"" " parameter \""+m_model_par->name()+"\""); log << gammalib::parformat("Confidence level"); log << m_confidence*100.0 << "%" << std::endl; log << gammalib::parformat("Log-likelihood difference"); log << m_dlogL << std::endl; log << gammalib::parformat("Initial factor range"); log << "["; log << parmin; log << ", "; log << parmax; log << "]" << std::endl; } // Compute lower boundary double value_lo = error_bisection(parmin, m_value); // Write lower parameter value if (logTerse()) { log << gammalib::parformat("Lower parameter factor"); log << value_lo << std::endl; } // Compute upper boundary double value_hi = error_bisection(m_value, parmax); // Write upper parameter value if (logTerse()) { log << gammalib::parformat("Upper parameter factor"); log << value_hi << std::endl; } // Compute errors double error = 0.5 * (value_hi - value_lo); double error_neg = m_value - value_lo; double error_pos = value_hi - m_value; //double error_max = std::max(value_hi-m_value, m_value-value_lo); //double error_min = std::min(value_hi-m_value, m_value-value_lo); // Write errors if (logTerse()) { log << gammalib::parformat("Error from curvature"); log << m_model_par->error(); log << " " << m_model_par->unit() << std::endl; log << gammalib::parformat("Error from profile"); log << std::abs(error*m_model_par->scale()); log << " " << m_model_par->unit() << std::endl; log << gammalib::parformat("Negative profile error"); log << std::abs(error_neg*m_model_par->scale()); log << " " << m_model_par->unit() << std::endl; log << gammalib::parformat("Positive profile error"); log << std::abs(error_pos*m_model_par->scale()); log << " " << m_model_par->unit() << std::endl; } // Save error result model->at(i).factor_error(error); } // endfor: looped over spectral parameters // Restore best fitting models (now with new errors computed) m_obs.models(models_best); } // endif: source model exists // Recover optimizer m_opt = best_opt; // Restore energy dispersion flag for all CTA observations for (int i = 0; i < m_obs.size(); ++i) { GCTAObservation* obs = dynamic_cast<GCTAObservation*>(m_obs[i]); if (obs != NULL) { obs->response()->apply_edisp(save_edisp[i]); } } // Return return; }
PView *GMSH_CVTRemeshPlugin::execute(PView *v) { //TODO normalization GModel* m = GModel::current() ; std::vector<double> vertices ; std::vector<unsigned int> faces ; unsigned int offset = 0 ; for(GModel::fiter it = m->firstFace(); it != m->lastFace(); ++it) { (*it)->buildSTLTriangulation() ; for(unsigned int i = 0; i < (*it)->stl_vertices.size(); ++i) { GPoint p = (*it)->point((*it)->stl_vertices[i]) ; vertices.push_back(p.x()) ; vertices.push_back(p.y()) ; vertices.push_back(p.z()) ; } for(unsigned int i = 0; i < (*it)->stl_triangles.size(); ++i) { faces.push_back((*it)->stl_triangles[i]+offset) ; } offset += (*it)->stl_vertices.size() ; } Revoropt::MeshBuilder<3> mesh ; mesh.swap_vertices(vertices) ; mesh.swap_faces(faces) ; double mesh_center[3] ; double mesh_scale ; Revoropt::normalize_mesh(&mesh, mesh_center, &mesh_scale) ; double nradius = (double)CVTRemeshOptions_Number[5].def ; //normals std::vector<double> normals(3*mesh.vertices_size()) ; Revoropt::full_robust_vertex_normals(&mesh,nradius,normals.data()) ; //lifted vertices std::vector<double> lifted_vertices(6*mesh.vertices_size(), 0) ; for(unsigned int vertex = 0; vertex < mesh.vertices_size(); ++vertex) { std::copy( mesh.vertex(vertex), mesh.vertex(vertex)+3, lifted_vertices.data()+6*vertex ) ; std::copy( normals.data()+3*vertex, normals.data()+3*vertex+3, lifted_vertices.data()+6*vertex+3 ) ; } //setup lifted mesh Revoropt::ROMeshWrapper<3,6> lifted_mesh( lifted_vertices.data(), lifted_vertices.size()/6, &mesh ) ; //triangle weight factor double twfactor = (double)CVTRemeshOptions_Number[3].def ; //face ratios std::vector<double> triangle_weights(lifted_mesh.faces_size()) ; if(twfactor > 0) { for(unsigned int f = 0; f < lifted_mesh.faces_size(); ++f) { //vertices of the initial triangle const unsigned int* fverts = mesh.face(f) ; //positions const double* x[3] ; for(int i=0; i<3; ++i) { x[i] = lifted_mesh.vertex(fverts[i]) ; } //ratio double ratio = 1 ; //vectors typedef Eigen::Matrix<double,3,1> Vector3 ; Eigen::Map<const Vector3> v0(x[0]) ; Eigen::Map<const Vector3> v1(x[1]) ; Eigen::Map<const Vector3> v2(x[2]) ; //triangle frame Vector3 U = (v1-v0) ; const double U_len = U.norm() ; if(U_len > 0) { U /= U_len ; Vector3 H = (v2-v0) ; H = H - H.dot(U)*U ; const double H_len = H.norm() ; if(H_len > 0) { //we know that the triangle is not flat H /= H_len ; //gradient of the barycentric weights in the triangle Eigen::Matrix<double,3,2> bar_grads ; bar_grads(2,0) = 0 ; bar_grads(2,1) = 1/H_len ; //gradient norms of every normal component for(int i = 0; i < 2; ++i) { //reference frame for the vertex Eigen::Map<const Vector3> vi0(x[(i+1)%3]) ; Eigen::Map<const Vector3> vi1(x[(i+2)%3]) ; Eigen::Map<const Vector3> vi2(x[ i ]) ; Vector3 Ui = (vi1-vi0) ; Ui /= Ui.norm() ; Vector3 Hi = (vi2-vi0) ; Hi = Hi - Hi.dot(Ui)*Ui ; const double Hi_invlen = 1/Hi.norm() ; Hi *= Hi_invlen ; bar_grads(i,0) = Hi.dot(U)*Hi_invlen ; bar_grads(i,1) = Hi.dot(H)*Hi_invlen ; } //gradient of each component of the normal Eigen::Map<const Vector3> n0(x[0]+3) ; Eigen::Map<const Vector3> n1(x[1]+3) ; Eigen::Map<const Vector3> n2(x[2]+3) ; Eigen::Matrix<double,3,2> n_grads = Eigen::Matrix<double,3,2>::Zero() ; n_grads = n0*bar_grads.row(0) ; n_grads += n1*bar_grads.row(1) ; n_grads += n2*bar_grads.row(2) ; //maximal gradient norm double g_max = n_grads.row(0).dot(n_grads.row(0)) ; double g_other = n_grads.row(1).dot(n_grads.row(1)) ; g_max = g_max > g_other ? g_max : g_other ; g_other = n_grads.row(2).dot(n_grads.row(2)) ; g_max = g_max > g_other ? g_max : g_other ; if(g_max == g_max) { //prevent nan ratio += g_max ; } } } triangle_weights[f] = pow(ratio,twfactor) ; } } //normal factor double nfactor = (double)CVTRemeshOptions_Number[2].def ; ; //weight the normal component by the provided factor for(unsigned int i = 0; i<lifted_mesh.vertices_size(); ++i) { double* v = lifted_vertices.data() + 6*i ; v[3]*= nfactor ; v[4]*= nfactor ; v[5]*= nfactor ; } //number of sites unsigned int nsites = (unsigned int)CVTRemeshOptions_Number[0].def ; //lifted sites std::vector<double> lifted_sites(6*nsites) ; if(twfactor > 0) { Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >( &lifted_mesh, nsites, lifted_sites.data(), triangle_weights.data() ) ; } else { Revoropt::generate_random_sites< Revoropt::ROMesh<3,6> >( &lifted_mesh, nsites, lifted_sites.data() ) ; } //setup the cvt minimizer Revoropt::CVT::DirectMinimizer< Revoropt::ROMesh<3,6> > cvt ; cvt.set_sites(lifted_sites.data(), nsites) ; cvt.set_mesh(&lifted_mesh) ; if(twfactor > 0) { cvt.set_triangle_weights(triangle_weights.data()) ; } //setup the callback SolverCallback callback ; //number of iterations unsigned int niter = (unsigned int)CVTRemeshOptions_Number[1].def ; ; unsigned int aniso_niter = std::min<unsigned int>(10,niter) ; //solver status int status = 0 ; //isotropic iterations if(niter > 10) { aniso_niter = std::max(aniso_niter,niter*10/100) ; cvt.set_anisotropy(1) ; status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(niter-aniso_niter, &callback) ; } //anisotropic iterations if(niter > 0) { //tangent space anisotropy double tanisotropy = (double)CVTRemeshOptions_Number[4].def ; ; //anisotropic iterations cvt.set_anisotropy(tanisotropy) ; status = cvt.minimize<Revoropt::Solver::AlgLBFGS>(aniso_niter, &callback) ; } //rdt std::vector<unsigned int> rdt_triangles ; Revoropt::RDTBuilder< Revoropt::ROMesh<3,6> > build_rdt(rdt_triangles) ; Revoropt::RVD< Revoropt::ROMesh<3,6> > rvd ; rvd.set_sites(lifted_sites.data(), nsites) ; rvd.set_mesh(&lifted_mesh) ; rvd.compute(build_rdt) ; GFace* res_face = new discreteFace(m, m->getMaxElementaryNumber(2)+1) ; m->add(res_face) ; //scale back and transfer to gmsh std::vector<MVertex*> m_verts(nsites) ; for(unsigned int i = 0; i < nsites; ++i) { m_verts[i] = new MVertex( lifted_sites[6*i ]*mesh_scale + mesh_center[0], lifted_sites[6*i+1]*mesh_scale + mesh_center[1], lifted_sites[6*i+2]*mesh_scale + mesh_center[2] ) ; res_face->addMeshVertex(m_verts[i]) ; } for(unsigned int i = 0; i < rdt_triangles.size()/3; ++i) { res_face->addTriangle( new MTriangle( m_verts[rdt_triangles[3*i ]], m_verts[rdt_triangles[3*i+1]], m_verts[rdt_triangles[3*i+2]] ) ) ; } res_face->setAllElementsVisible(true) ; return v ; }
int main(int argc,char *argv[]) { if(argc < 6){ printf("Usage: %s file lx ly lz rmax [levels=1] [refcs=1]\n", argv[0]); printf("where\n"); printf(" 'file' contains a CAD model\n"); printf(" 'lx', 'ly' and 'lz' are the sizes of the elements along the" " x-, y- and z-axis at the coarsest level\n"); printf(" 'rmax' is the radius of the largest sphere that can be inscribed" " in the structure\n"); printf(" 'levels' sets the number of levels in the grid\n"); printf(" 'refcs' selects if curved surfaces should be refined\n"); return -1; } GmshInitialize(); GmshSetOption("General", "Terminal", 1.); GmshMergeFile(argv[1]); double lx = atof(argv[2]), ly = atof(argv[3]), lz = atof(argv[4]); double rmax = atof(argv[5]); int levels = (argc > 6) ? atof(argv[6]) : 1; int refineCurvedSurfaces = (argc > 7) ? atof(argv[7]) : 1; // minimum distance between points in the cloud at the coarsest // level double sampling = std::min(rmax, std::min(lx, std::min(ly, lz))); // radius of the "tube" created around parts to refine at the // coarsest level double rtube = std::max(lx, std::max(ly, lz)) * 2.; GModel *gm = GModel::current(); std::vector<SPoint3> points; Msg::Info("Filling coarse point cloud on surfaces"); for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) (*fit)->fillPointCloud(sampling, &points); Msg::Info(" %d points in the surface cloud", (int)points.size()); std::vector<SPoint3> refinePoints; if(levels > 1){ double s = sampling / pow(2., levels - 1); Msg::Info("Filling refined point cloud on curves and curved surfaces"); for (GModel::eiter eit = gm->firstEdge(); eit != gm->lastEdge(); eit++) fillPointCloud(*eit, s, refinePoints); // FIXME: refine this by computing e.g. "mean" curvature if(refineCurvedSurfaces){ for (GModel::fiter fit = gm->firstFace(); fit != gm->lastFace(); fit++) if((*fit)->geomType() != GEntity::Plane) (*fit)->fillPointCloud(2 * s, &refinePoints); } Msg::Info(" %d points in the refined cloud", (int)refinePoints.size()); } SBoundingBox3d bb; for(unsigned int i = 0; i < points.size(); i++) bb += points[i]; for(unsigned int i = 0; i < refinePoints.size(); i++) bb += refinePoints[i]; bb.scale(1.21, 1.21, 1.21); SVector3 range = bb.max() - bb.min(); int NX = range.x() / lx; int NY = range.y() / ly; int NZ = range.z() / lz; if(NX < 2) NX = 2; if(NY < 2) NY = 2; if(NZ < 2) NZ = 2; Msg::Info(" bounding box min: %g %g %g -- max: %g %g %g", bb.min().x(), bb.min().y(), bb.min().z(), bb.max().x(), bb.max().y(), bb.max().z()); Msg::Info(" Nx=%d Ny=%d Nz=%d", NX, NY, NZ); cartesianBox<double> box(bb.min().x(), bb.min().y(), bb.min().z(), SVector3(range.x(), 0, 0), SVector3(0, range.y(), 0), SVector3(0, 0, range.z()), NX, NY, NZ, levels); Msg::Info("Inserting active cells in the cartesian grid"); Msg::Info(" level %d", box.getLevel()); for (unsigned int i = 0; i < points.size(); i++) insertActiveCells(points[i].x(), points[i].y(), points[i].z(), rmax, box); cartesianBox<double> *parent = &box, *child; while((child = parent->getChildBox())){ Msg::Info(" level %d", child->getLevel()); for(unsigned int i = 0; i < refinePoints.size(); i++) insertActiveCells(refinePoints[i].x(), refinePoints[i].y(), refinePoints[i].z(), rtube / pow(2., (levels - child->getLevel())), *child); parent = child; } // remove child cells that do not entirely fill parent cell or for // which there is no parent neighbor; then remove parent cells that // have children Msg::Info("Removing cells to match X-FEM mesh topology constraints"); removeBadChildCells(&box); removeParentCellsWithChildren(&box); // we generate duplicate nodes at this point so we can easily access // cell values at each level; we will clean up by renumbering after // filtering Msg::Info("Initializing nodal values in the cartesian grid"); box.createNodalValues(); Msg::Info("Computing levelset on the cartesian grid"); computeLevelset(gm, box); Msg::Info("Removing cells outside the structure"); removeOutsideCells(&box); Msg::Info("Renumbering mesh vertices across levels"); box.renumberNodes(); bool decomposeInSimplex = false; box.writeMSH("yeah.msh", decomposeInSimplex); Msg::Info("Done!"); GmshFinalize(); }
void carveHole(GRegion *gr, int num, double distance, std::vector<int> &surfaces) { Msg::Info("Carving hole %d from surface %d at distance %g", num, surfaces[0], distance); GModel *m = gr->model(); // add all points from carving surfaces into kdtree int numnodes = 0; for(unsigned int i = 0; i < surfaces.size(); i++){ GFace *gf = m->getFaceByTag(surfaces[i]); if(!gf){ Msg::Error("Unknown carving surface %d", surfaces[i]); return; } numnodes += gf->mesh_vertices.size(); } ANNpointArray kdnodes = annAllocPts(numnodes, 3); int k = 0; for(unsigned int i = 0; i < surfaces.size(); i++){ GFace *gf = m->getFaceByTag(surfaces[i]); for(unsigned int j = 0; j < gf->mesh_vertices.size(); j++){ kdnodes[k][0] = gf->mesh_vertices[j]->x(); kdnodes[k][1] = gf->mesh_vertices[j]->y(); kdnodes[k][2] = gf->mesh_vertices[j]->z(); k++; } } ANNkd_tree *kdtree = new ANNkd_tree(kdnodes, numnodes, 3); // remove the volume elements that are within 'distance' of the // carved surface carveHole(gr->tetrahedra, distance, kdtree); carveHole(gr->hexahedra, distance, kdtree); carveHole(gr->prisms, distance, kdtree); carveHole(gr->pyramids, distance, kdtree); delete kdtree; annDeallocPts(kdnodes); // TODO: remove any interior elements left inside the carved surface // (could shoot a line from each element's barycenter and count // intersections o see who's inside) // generate discrete boundary mesh of the carved hole GFace *gf = m->getFaceByTag(num); if(!gf) return; std::set<MFace, Less_Face> faces; std::list<GFace*> f = gr->faces(); for(std::list<GFace*>::iterator it = f.begin(); it != f.end(); it++){ addFaces((*it)->triangles, faces); addFaces((*it)->quadrangles, faces); } addFaces(gr->tetrahedra, faces); addFaces(gr->hexahedra, faces); addFaces(gr->prisms, faces); addFaces(gr->pyramids, faces); std::set<MVertex*> verts; for(std::set<MFace, Less_Face>::iterator it = faces.begin(); it != faces.end(); it++){ for(int i = 0; i < it->getNumVertices(); i++){ it->getVertex(i)->setEntity(gf); verts.insert(it->getVertex(i)); } if(it->getNumVertices() == 3) gf->triangles.push_back(new MTriangle(it->getVertex(0), it->getVertex(1), it->getVertex(2))); else if(it->getNumVertices() == 4) gf->quadrangles.push_back(new MQuadrangle(it->getVertex(0), it->getVertex(1), it->getVertex(2), it->getVertex(3))); } }
// The function that tests whether a 2D surface is a lateral of a valid QuadToTri // region and whether there are conflicts. If surface is not part of valid QuadToTri region // or if there are QuadToTri conflicts, return 0. Note that RemoveDuplicateSurfaces() // makes this DIFFICULT. Also, the tri_quad_flag determins whether the surface // should be meshed with triangles or quadrangles: // tri_quad_values: 0 = no override, 1 = mesh as quads, 2 = mesh as triangles. // Added 2010-12-09. int IsValidQuadToTriLateral(GFace *face, int *tri_quad_flag, bool *detectQuadToTriLateral ) { (*tri_quad_flag) = 0; (*detectQuadToTriLateral) = false; GModel *model = face->model(); ExtrudeParams *ep = face->meshAttributes.extrude; if( !ep || !ep->mesh.ExtrudeMesh || !ep->geo.Mode == EXTRUDED_ENTITY ){ Msg::Error("In IsValidQuadToTriLateral(), face %d is not a structured extrusion.", face->tag() ); return 0; } GEdge *face_source = model->getEdgeByTag( std::abs( ep->geo.Source ) ); if( !face_source ){ Msg::Error("In IsValidQuadToTriLateral(), face %d has no source edge.", face->tag() ); } // It seems the member pointers to neighboring regions for extruded lateral faces are not set. // For now, have to loop through // ALL the regions to see if the presently considered face belongs to the region and if // any neighboring region is QUADTRI. // The following loop will find all the regions that the face bounds, and determine // whether the face is a lateral of the region (including whether the region is even extruded). // After that information is determined, function can test for QuadToTri neighbor conflicts. std::vector<GRegion *> lateral_regions; std::vector<GRegion *> adjacent_regions; int numRegions = 0; int numLateralRegions = 0; numRegions = GetNeighborRegionsOfFace(face, adjacent_regions); for( int i_reg = 0; i_reg < numRegions; i_reg++ ){ GRegion *region = adjacent_regions[i_reg]; // is region in the current model's region's or is it deleted? if( !FindVolume( ( region->tag() ) ) ) continue; // is the region mesh extruded? if( !region->meshAttributes.extrude || ( region->meshAttributes.extrude && !region->meshAttributes.extrude->mesh.ExtrudeMesh ) ) continue; if( region->meshAttributes.extrude->geo.Mode != EXTRUDED_ENTITY ) continue; // Test whether the face is a lateral if( IsSurfaceALateralForRegion(region, face) ){ lateral_regions.push_back(region); numLateralRegions++; if( region->meshAttributes.extrude->mesh.QuadToTri ) (*detectQuadToTriLateral) = true; } } // MAIN test of whether this is even a quadToTri extrusion lateral // the only return 0 path that is NOT an error if( !(*detectQuadToTriLateral) ) return 0; // now will start conflict checks if(numRegions > 2){ Msg::Error("In IsValidQuadToTriLateral(), too many regions adjacent to surface %d.", face->tag() ); return 0; } bool detect_conflict = false; // Set the tri_quad_flag that lets ExtrudeMesh override ep->Recombine; // tri_quad_values: 0 = no override, 1 = mesh as quads, 2 = mesh as triangles. // if this face is a free surface: if( adjacent_regions.size() == 1 ){ if( lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_NOVERTS_1_RECOMB || lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_ADDVERTS_1_RECOMB ){ (*tri_quad_flag) = 1; } if( lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_NOVERTS_1 || lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_ADDVERTS_1 ){ (*tri_quad_flag) = 2; } else (*tri_quad_flag) = 0; } else if( adjacent_regions.size() > 1 ){ GRegion *adj_region = NULL; ExtrudeParams *adj_ep = NULL; if( lateral_regions[0] == adjacent_regions[0] ) adj_region = adjacent_regions[1]; else adj_region = adjacent_regions[0]; adj_ep = adj_region->meshAttributes.extrude; // if Neighbor is Transfinite, go with the default, non-QuadTri recombine for this surface if( adj_region && adj_region->meshAttributes.method == MESH_TRANSFINITE ) (*tri_quad_flag) = 0; // if a neighbor // has no extrusion structure, // don't even consider QuadToTri Recomb on this face. else if( adj_region && !(adj_ep && adj_ep->mesh.ExtrudeMesh) ) (*tri_quad_flag) = 2; // This face is the source face of a second // neighboring extrusion. else if( adj_ep && adj_ep->mesh.ExtrudeMesh && model->getFaceByTag( std::abs( adj_ep->geo.Source ) ) == face ){ if( lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_NOVERTS_1_RECOMB || lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_ADDVERTS_1_RECOMB ) (*tri_quad_flag) = 1; else if( lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_NOVERTS_1 || lateral_regions[0]->meshAttributes.extrude->mesh.QuadToTri == QUADTRI_ADDVERTS_1 ) (*tri_quad_flag) = 2; else (*tri_quad_flag) = 0; } // if both neighbors are structured but none of the previous apply: else if( adj_ep && adj_ep->mesh.ExtrudeMesh ){ if( (adj_ep && !adj_ep->mesh.QuadToTri && adj_ep->mesh.Recombine) || (ep && !ep->mesh.QuadToTri && ep->mesh.Recombine) ) (*tri_quad_flag) = 1; else if( (adj_ep && !adj_ep->mesh.QuadToTri && !adj_ep->mesh.Recombine) || (ep && !ep->mesh.QuadToTri && !ep->mesh.Recombine) ) (*tri_quad_flag) = 2; // if both are quadToTri ALWAYS try to recombine else if( ep->mesh.QuadToTri && adj_ep && adj_ep->mesh.QuadToTri ) (*tri_quad_flag) = 1; else (*tri_quad_flag) = 0; } // any other adjacent surface, just default to the QuadToTri region's non-QuadToTri // default recombination method. Any mistakes at this point are not this feature's. else (*tri_quad_flag) = 0; } // if this executes, there's a mistake here : else{ detect_conflict = true; (*tri_quad_flag) = 0; } if( detect_conflict ) return 0; else return 1; }
void GMSH_SimplePartitionPlugin::run() { #if defined(HAVE_MESH) int numSlicesX = (int)SimplePartitionOptions_Number[0].def; int numSlicesY = (int)SimplePartitionOptions_Number[1].def; int numSlicesZ = (int)SimplePartitionOptions_Number[2].def; int createTopology = (int)SimplePartitionOptions_Number[3].def; std::vector<std::string> exprX(1), exprY(1), exprZ(1); exprX[0] = SimplePartitionOptions_String[0].def; exprY[0] = SimplePartitionOptions_String[1].def; exprZ[0] = SimplePartitionOptions_String[2].def; GModel *m = GModel::current(); if(!m->getNumMeshElements()){ Msg::Error("Plugin(SimplePartition) requires a mesh"); return; } if(numSlicesX < 1 || numSlicesY < 1 || numSlicesZ < 1){ Msg::Error("Number of slices should be strictly positive"); return; } m->unpartitionMesh(); SBoundingBox3d bbox = m->bounds(); double pminX = bbox.min()[0], pmaxX = bbox.max()[0]; double pminY = bbox.min()[1], pmaxY = bbox.max()[1]; double pminZ = bbox.min()[2], pmaxZ = bbox.max()[2]; std::vector<double> ppX(numSlicesX + 1); std::vector<double> ppY(numSlicesY + 1); std::vector<double> ppZ(numSlicesZ + 1); std::vector<std::string> variables(1, "t"); std::vector<double> values(1), res(1); { mathEvaluator f(exprX, variables); for(int p = 0; p <= numSlicesX; p++) { double t = values[0] = (double)p / (double)numSlicesX; if(f.eval(values, res)) t = res[0]; ppX[p] = pminX + t * (pmaxX - pminX); } } bool emptyX = (ppX[0] == ppX[numSlicesX]); { mathEvaluator f(exprY, variables); for(int p = 0; p <= numSlicesY; p++) { double t = values[0] = (double)p / (double)numSlicesY; if(f.eval(values, res)) t = res[0]; ppY[p] = pminY + t * (pmaxY - pminY); } } bool emptyY = (ppY[0] == ppY[numSlicesY]); { mathEvaluator f(exprZ, variables); for(int p = 0; p <= numSlicesZ; p++) { double t = values[0] = (double)p / (double)numSlicesZ; if(f.eval(values, res)) t = res[0]; ppZ[p] = pminZ + t * (pmaxZ - pminZ); } } bool emptyZ = (ppZ[0] == ppZ[numSlicesZ]); std::vector<GEntity *> entities; m->getEntities(entities); hashmap<MElement *, unsigned int> elmToPartition; for(std::size_t i = 0; i < entities.size(); i++) { GEntity *ge = entities[i]; for(std::size_t j = 0; j < ge->getNumMeshElements(); j++) { MElement *e = ge->getMeshElement(j); SPoint3 point = e->barycenter(); int part = 0; for(int kx = 0; kx < numSlicesX; kx++) { if(part) break; for(int ky = 0; ky < numSlicesY; ky++) { if(part) break; for(int kz = 0; kz < numSlicesZ; kz++) { if(part) break; if((emptyX || (kx == 0 && ppX[0] == point[0]) || (ppX[kx] < point[0] && point[0] <= ppX[kx + 1])) && (emptyY || (ky == 0 && ppY[0] == point[1]) || (ppY[ky] < point[1] && point[1] <= ppY[ky + 1])) && (emptyZ || (kz == 0 && ppZ[0] == point[2]) || (ppZ[kz] < point[2] && point[2] <= ppZ[kz + 1]))){ part = kx * numSlicesY * numSlicesZ + ky * numSlicesZ + kz + 1; elmToPartition.insert(std::pair<MElement *, unsigned int>(e, part)); e->setPartition(part); // this will be removed } } } } } } opt_mesh_partition_create_topology(0, GMSH_SET | GMSH_GUI, createTopology); int ier = PartitionUsingThisSplit(m, numSlicesX * numSlicesY * numSlicesZ, elmToPartition); if(!ier) { opt_mesh_color_carousel(0, GMSH_SET | GMSH_GUI, 3.); CTX::instance()->mesh.changed = ENT_ALL; } #else Msg::Error("Gmsh must be compiled with Mesh support to partition meshes"); #endif }
// The function that tests whether a surface is a QuadToTri top surface and whether // there are conflicts. If surface is not a top for a valid QuadToTri region or if // there are QuadToTri conflicts, return 0. // if the surface turns out to be the source of a toroidal loop extrusion (which will then // NOT have geo.Mode == COPIED_ENTITY), return 2 (this will require special meshing considerations). // Note that RemoveDuplicateSurfaces() makes this DIFFICULT. // Also, the type of QuadToTri interface is placed into the // pointer argument quadToTri. . // Added 2010-12-09. int IsValidQuadToTriTop(GFace *face, int *quadToTri, bool *detectQuadToTriTop) { (*quadToTri) = NO_QUADTRI; (*detectQuadToTriTop) = false; int is_toroidal_quadtri = 0; GModel *model = face->model(); // First thing is first: determine if this is a toroidal quadtri extrusion. if so, can skip the rest // It seems the member pointers to neighboring regions for extruded top faces are not set. // For now, have to loop through // ALL the regions to see if the presently considered face belongs to the region. // The following loop will find all the regions that the face bounds, and determine // whether the face is a top face of the region (including whether the region is even extruded). // After that information is determined, function can test for QuadToTri neighbor conflicts. // first determine if this is toroidal quadtotri is_toroidal_quadtri = IsInToroidalQuadToTri(face); if( is_toroidal_quadtri ) (*detectQuadToTriTop) = true; else{ std::vector<GRegion *> top_regions; std::vector<GRegion *> adjacent_regions; std::vector<GRegion *> all_regions; int numRegions = 0; int numTopRegions = 0; std::set<GRegion *, GEntityLessThan>::iterator itreg; for( itreg = model->firstRegion(); itreg != model->lastRegion(); itreg++ ) all_regions.push_back( (*itreg) ); for(unsigned int i_reg = 0; i_reg < all_regions.size(); i_reg++ ){ // save time if( numRegions >= 2 ) break; GRegion *region = all_regions[i_reg]; // is region in the current model's regions or is it deleted? if( !FindVolume( ( region->tag() ) ) ) continue; // does face belong to region? std::list<GFace *> region_faces = std::list<GFace *>( region->faces() ); if( std::find( region_faces.begin(), region_faces.end(), face ) != region_faces.end() ){ adjacent_regions.push_back(region); numRegions++; } else continue; // is region a structured extruded? if( !(region->meshAttributes.extrude && region->meshAttributes.extrude->mesh.ExtrudeMesh && region->meshAttributes.extrude->geo.Mode == EXTRUDED_ENTITY) ) continue; // Test whether the face is a top for the region if( IsSurfaceATopForRegion(region, face) ){ top_regions.push_back(region); numTopRegions++; if( region->meshAttributes.extrude->mesh.QuadToTri ) (*detectQuadToTriTop) = true; } } // MAIN test of whether this is even a quadToTri extrusion lateral // the only return 0 path that is NOT an error if( !(*detectQuadToTriTop) ) return 0; ExtrudeParams *ep = face->meshAttributes.extrude; if(!ep && !is_toroidal_quadtri){ Msg::Error("In IsValidQuadToTriTop(), no extrude info for surface %d.", face->tag() ); return 0; } if( ep->geo.Mode != COPIED_ENTITY ){ Msg::Error("In IsValidQuadToTriTop(), surface %d is not copied from source.", face->tag() ); return 0; } if( ep->mesh.QuadToTri == 0){ Msg::Error("In IsValidQuadToTriTop(), surface %d was determined to be the top surface " "for a QuadToTri extrusion, but does not have QuadToTri parameters set within itself.", face->tag() ); return 0; } GFace *face_source = model->getFaceByTag(std::abs(ep->geo.Source)); if(!face_source){ Msg::Error("In IsValidQuadToTriTop(), unknown source face number %d.", face->meshAttributes.extrude->geo.Source); return 0; } if(numRegions > 2){ Msg::Error("In IsValidQuadToTriTop(), too many regions adjacent to surface %d.", face->tag() ); return 0; } if( top_regions.size() ){ (*quadToTri) = top_regions[0]->meshAttributes.extrude->mesh.QuadToTri; } // Make sure that face is the top for only one region. if not, then there will likely // be conflicts (two regions extruded into each other). if( top_regions.size() > 1 ){ Msg::Error("In IsValidQuadToTriTop(), QuadToTri top surface %d identified as top " "surface for more than one region. Likely conflict.", face->tag() ); return 0; } } // end of else that executes if NOT toroidal extrusion // this is technically redundant...but if changes are made, it's good to keep this here at the end for safety if( !(*detectQuadToTriTop) ) return 0; if( !is_toroidal_quadtri ) return 1; else if( is_toroidal_quadtri == 1 ) { return 2;} // for toroidal extrusion else return 3; }
MarkeredSurface MarkeredSurfaceGeoGenerator::generate(string fileName, real size) { Engine& engine = Engine::getInstance(); LOG_INFO("Generating markered surface from Geo file " << fileName); GmshSetOption("General", "Terminal", 1.0); GmshSetOption("General", "Verbosity", engine.getGmshVerbosity()); GmshSetOption("General", "ExpertMode", 1.0); GModel gmshModel; gmshModel.setFactory("Gmsh"); gmshModel.readGEO(fileName); float clmin, clmax; if (size > 0) { clmin = size*0.8; clmax = size*1.2; } else { auto _min = gmshModel.bounds().min(); auto _max = gmshModel.bounds().max(); auto d1 = _max.x() - _min.x(); auto d2 = _max.y() - _min.y(); auto d3 = _max.z() - _min.z(); if ((d1/d2 >= 0.8) && (d1/d2 <= 1.2) && (d1/d3 >= 0.8) && (d1/d3 <= 1.2)) { auto d = gmshModel.bounds().diag(); clmin = d/80; clmax = d/60; } else { auto d = min({d1, d2, d3}); clmin = d/10; clmax = d/5; } } GmshSetOption("Mesh", "CharacteristicLengthMin", clmin); GmshSetOption("Mesh", "CharacteristicLengthMax", clmax); gmshModel.mesh(2); vector<GEntity*> entities; gmshModel.getEntities(entities); auto nverts = gmshModel.getNumMeshVertices(); vector<CalcNode> markers; vector<TriangleFirstOrder> faces; vector<int> regions; int *newVertNums = new int[nverts+1]; for (int i = 0; i <= nverts; i++) newVertNums[i] = -1; MVertex* verts[3]; int nf = 0; int nv = 0; for (auto e: entities) { if (e->geomType() == GEntity::RuledSurface || e->geomType() == GEntity::Plane) { regions.push_back(e->getNumMeshElements()); for (unsigned int i = 0; i < e->getNumMeshElements(); i++) { auto elem = e->getMeshElement(i); assert_eq(elem->getNumFaces(), 1); auto face = elem->getFace(0); for (int j = 0; j < 3; j++) verts[j] = face.getVertex(j); int v[3]; for (int j = 0; j < 3; j++) { if (newVertNums[verts[j]->getNum()] == -1) { newVertNums[verts[j]->getNum()] = nv; markers.push_back(CalcNode(nv, vector3r(verts[j]->x(), verts[j]->y(), verts[j]->z()))); nv++; } v[j] = newVertNums[verts[j]->getNum()]; } faces.push_back(TriangleFirstOrder(nf++, v)); } } } assert_gt(markers.size(), 0); assert_gt(faces.size(), 0); delete[] newVertNums; return MarkeredSurface(markers, faces, regions); }
void drawContext::drawMesh() { if(!CTX::instance()->mesh.draw) return; // make sure to flag any model-dependent post-processing view as // changed if the underlying mesh has, before resetting the changed // flag if(CTX::instance()->mesh.changed){ for(unsigned int i = 0; i < GModel::list.size(); i++) for(unsigned int j = 0; j < PView::list.size(); j++) if(PView::list[j]->getData()->hasModel(GModel::list[i])) PView::list[j]->setChanged(true); } glPointSize((float)CTX::instance()->mesh.pointSize); gl2psPointSize((float)(CTX::instance()->mesh.pointSize * CTX::instance()->print.epsPointSizeFactor)); glLineWidth((float)CTX::instance()->mesh.lineWidth); gl2psLineWidth((float)(CTX::instance()->mesh.lineWidth * CTX::instance()->print.epsLineWidthFactor)); if(CTX::instance()->mesh.lightTwoSide) glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); else glLightModelf(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE); if(!CTX::instance()->clipWholeElements){ for(int i = 0; i < 6; i++) if(CTX::instance()->mesh.clip & (1 << i)) glEnable((GLenum)(GL_CLIP_PLANE0 + i)); else glDisable((GLenum)(GL_CLIP_PLANE0 + i)); } for(unsigned int i = 0; i < GModel::list.size(); i++){ GModel *m = GModel::list[i]; m->fillVertexArrays(); if(m->getVisibility() && isVisible(m)){ int status = m->getMeshStatus(); if(status >= 0) std::for_each(m->firstVertex(), m->lastVertex(), drawMeshGVertex(this)); if(status >= 1) std::for_each(m->firstEdge(), m->lastEdge(), drawMeshGEdge(this)); if(status >= 2){ beginFakeTransparency(); std::for_each(m->firstFace(), m->lastFace(), drawMeshGFace(this)); endFakeTransparency(); } if(status >= 3) std::for_each(m->firstRegion(), m->lastRegion(), drawMeshGRegion(this)); } } CTX::instance()->mesh.changed = 0; for(int i = 0; i < 6; i++) glDisable((GLenum)(GL_CLIP_PLANE0 + i)); }
bool OptHOM::addBndObjGrad(double factor, double &Obj, alglib::real_1d_array &gradObj) { // set the mesh to its present position std::vector<SPoint3> xyz,uvw; mesh.getGEntityPositions(xyz,uvw); mesh.updateGEntityPositions(); //could be better (e.g. store the model in the Mesh:: datastrucure) GModel *gm = GModel::current(); // for all model edges, compute the error between the geometry and the mesh maxDistCAD = 0.0; double distCAD = 0.0; for (GModel::eiter it = gm->firstEdge(); it != gm->lastEdge(); ++it){ // do not do straight lines if ((*it)->geomType() == GEntity::Line)continue; // look at all mesh lines std::vector<bool> doWeCompute((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->lines[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->lines[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; continue; } } } std::vector<double> dist((*it)->lines.size()); for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ // compute the distance from the geometry to the mesh dist[i] = MLineGEdgeDistance ( (*it)->lines[i] , *it ); maxDistCAD = std::max(maxDistCAD,dist[i]); distCAD += dist [i] * factor; } } // be clever to compute the derivative : iterate on all // Distance = \sum_{lines} Distance (line, GEdge) // For a high order vertex, we compute the derivative only by // recomputing the distance to one only line const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->lines.size(); i++){ if (doWeCompute[i]){ for (int j=2 ; j<(*it)->lines[i]->getNumVertices() ; j++){ MVertex *v = (*it)->lines[i]->getVertex(j); int index = mesh.getFreeVertexStartIndex(v); // printf("%d %d (%d %d)\n",v->getNum(),index,v->onWhat()->tag(),v->onWhat()->dim()); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double dist2 = MLineGEdgeDistance ( (*it)->lines[i] , *it ); double deriv = (dist2 - dist[i])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); // printf("%g %g %g\n",dist[i],dist2, MLineGEdgeDistance ( (*it)->lines[i] , *it )); // get the index of the vertex gradObj[index] += deriv * factor; } } } // printf("done\n"); // For a low order vertex classified on the GEdge, we recompute // two distances for the two MLines connected to the vertex for (unsigned int i=0;i<(*it)->lines.size()-1; i++){ MVertex *v = (*it)->lines[i]->getVertex(1); int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ double t; v->getParameter(0,t); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = (*it)->point(t+eps); v->setParameter(0,t+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); MLine *l1 = (*it)->lines[i]; MLine *l2 = (*it)->lines[i+1]; // printf("%d %d -- %d %d\n",l1->getVertex(0)->getNum(),l1->getVertex(1)->getNum(),l2->getVertex(0)->getNum(),l2->getVertex(1)->getNum()); double deriv = (MLineGEdgeDistance ( l1 , *it ) - dist[i]) /eps + (MLineGEdgeDistance ( l2 , *it ) - dist[i+1])/eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t); gradObj[index] += deriv * factor; } } } } // printf("computing distance : 1D part %12.5E\n",distCAD); // now the 3D part ! std::vector<std::vector<SVector3> > gsfT; computeGradSFAtNodes ( (*gm->firstFace())->triangles[0],gsfT); std::map<MVertex*,SVector3> normalsToCAD; for(GModel::fiter it = gm->firstFace(); it != gm->lastFace(); ++it){ // do not do plane surfaces if ((*it)->geomType() == GEntity::Plane)continue; std::map<MTriangle*,double> dist; std::vector<bool> doWeCompute((*it)->triangles.size()); for (unsigned int i=0;i<(*it)->triangles.size(); i++){ doWeCompute[i] = false; for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ int index = mesh.getFreeVertexStartIndex((*it)->triangles[i]->getVertex(j)); if (index >=0){ doWeCompute[i] = true; } } if (doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ MVertex *v = (*it)->triangles[i]->getVertex(j); if (normalsToCAD.find(v) == normalsToCAD.end()){ SPoint2 p_cad; reparamMeshVertexOnFace(v, *it, p_cad); SVector3 tg_cad = (*it)->normal(p_cad); tg_cad.normalize(); normalsToCAD[v] = tg_cad; } } } } for (unsigned int i=0;i<(*it)->triangles.size(); i++){ // compute the distance from the geometry to the mesh if(doWeCompute[i]){ const double d = MFaceGFaceDistanceOld((*it)->triangles[i], *it, &gsfT, &normalsToCAD); dist[(*it)->triangles[i]] = d; maxDistCAD = std::max(maxDistCAD,d); distCAD += d * factor; } } // be clever again to compute the derivatives const double eps = 1.e-6; for (unsigned int i=0;i<(*it)->triangles.size(); i++){ if(doWeCompute[i]){ for (unsigned int j=0;j<(*it)->triangles[i]->getNumVertices(); j++){ // for (; itm !=v2t.end(); ++itm){ MVertex *v = (*it)->triangles[i]->getVertex(j); if(v->onWhat()->dim() == 1){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; GEdge *ge = v->onWhat()->cast2Edge(); double t_; v->getParameter(0,t_); SPoint3 pp (v->x(),v->y(),v->z()); GPoint gp = ge->point(t_+eps); v->setParameter(0,t_+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); const double distT = dist[t]; double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,t_); gradObj[index] += deriv * factor; } } if(v->onWhat() == *it){ int index = mesh.getFreeVertexStartIndex(v); if (index >= 0){ MTriangle *t = (*it)->triangles[i]; double uu,vv; v->getParameter(0,uu); v->getParameter(1,vv); SPoint3 pp (v->x(),v->y(),v->z()); const double distT = dist[t]; GPoint gp = (*it)->point(uu+eps,vv); v->setParameter(0,uu+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); double deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(0,uu); gradObj[index] += deriv * factor; gp = (*it)->point(uu,vv+eps); v->setParameter(1,vv+eps); v->setXYZ(gp.x(),gp.y(),gp.z()); deriv = (MFaceGFaceDistanceOld(t, *it, &gsfT, &normalsToCAD) - distT) /eps; v->setXYZ(pp.x(),pp.y(),pp.z()); v->setParameter(1,vv); gradObj[index+1] += deriv * factor; } } } } } } mesh.updateGEntityPositions(xyz,uvw); Obj +=distCAD; // printf("computing distance : 2D part %12.5E\n",distCAD); // printf("%22.15E\n",distCAD); return true; }
bool PView::readMSH(const std::string &fileName, int fileIndex) { FILE *fp = Fopen(fileName.c_str(), "rb"); if(!fp){ Msg::Error("Unable to open file '%s'", fileName.c_str()); return false; } GModel *model = GModel::current(); if(model->empty()){ Msg::Error("Model is empty: please load a mesh before loading the dataset"); fclose(fp); return false; } char str[256] = "XXX"; int index = -1; bool binary = false, swap = false; while(1) { while(str[0] != '$'){ if(!fgets(str, sizeof(str), fp) || feof(fp)) break; } if(feof(fp)) break; if(!strncmp(&str[1], "MeshFormat", 10)) { double version; if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } int format, size; if(sscanf(str, "%lf %d %d", &version, &format, &size) != 3){ fclose(fp); return false; } if(format){ binary = true; Msg::Info("View data is in binary format"); int one; if(fread(&one, sizeof(int), 1, fp) != 1){ fclose(fp); return 0; } if(one != 1){ swap = true; Msg::Info("Swapping bytes from binary file"); } } } else if(!strncmp(&str[1], "InterpolationScheme", 19)){ std::string name; if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } name = ExtractDoubleQuotedString(str, sizeof(str)); Msg::Info("Reading interpolation scheme '%s'", name.c_str()); PViewData::removeInterpolationScheme(name); int numTypes; if(fscanf(fp, "%d", &numTypes) != 1){ fclose(fp); return false; } for(int i = 0; i < numTypes; i++){ int type, numMatrices; if(fscanf(fp, "%d %d", &type, &numMatrices) != 2){ fclose(fp); return false; } for(int j = 0; j < numMatrices; j++){ int m, n; if(fscanf(fp, "%d %d", &m, &n) != 2){ fclose(fp); return false; } fullMatrix<double> mat(m, n); for(int k = 0; k < m; k++){ for(int l = 0; l < n; l++){ double d; if(fscanf(fp, "%lf", &d) != 1){ fclose(fp); return false; } mat.set(k, l, d); } } PViewData::addMatrixToInterpolationScheme(name, type, mat); } } } else if(!strncmp(&str[1], "NodeData", 8) || !strncmp(&str[1], "ElementData", 11) || !strncmp(&str[1], "ElementNodeData", 15)) { index++; if(fileIndex < 0 || fileIndex == index){ PViewDataGModel::DataType type; if(!strncmp(&str[1], "NodeData", 8)) type = PViewDataGModel::NodeData; else if(!strncmp(&str[1], "ElementData", 11)) type = PViewDataGModel::ElementData; else type = PViewDataGModel::ElementNodeData; int numTags; // string tags std::string viewName, interpolationScheme; if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(sscanf(str, "%d", &numTags) != 1){ fclose(fp); return false; } for(int i = 0; i < numTags; i++){ if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(i == 0) viewName = ExtractDoubleQuotedString(str, sizeof(str)); else if(i == 1) interpolationScheme = ExtractDoubleQuotedString(str, sizeof(str)); } // double tags double time = 0.; if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(sscanf(str, "%d", &numTags) != 1){ fclose(fp); return false; } for(int i = 0; i < numTags; i++){ if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(i == 0){ if(sscanf(str, "%lf", &time) != 1){ fclose(fp); return false; } } } // integer tags int timeStep = 0, numComp = 0, numEnt = 0, partition = 0; if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(sscanf(str, "%d", &numTags) != 1){ fclose(fp); return false; } for(int i = 0; i < numTags; i++){ if(!fgets(str, sizeof(str), fp)){ fclose(fp); return false; } if(i == 0){ if(sscanf(str, "%d", &timeStep) != 1){ fclose(fp); return false; } } else if(i == 1){ if(sscanf(str, "%d", &numComp) != 1){ fclose(fp); return false; } } else if(i == 2){ if(sscanf(str, "%d", &numEnt) != 1){ fclose(fp); return false; } } else if(i == 3){ if(sscanf(str, "%d", &partition) != 1){ fclose(fp); return false; } } } // either get existing viewData, or create new one PView *p = getViewByName(viewName, timeStep, partition); PViewDataGModel *d = 0; if(p) d = dynamic_cast<PViewDataGModel*>(p->getData()); bool create = d ? false : true; if(create) d = new PViewDataGModel(type); if(!d->readMSH(viewName, fileName, fileIndex, fp, binary, swap, timeStep, time, partition, numComp, numEnt, interpolationScheme)){ Msg::Error("Could not read data in msh file"); if(create) delete d; fclose(fp); return false; } else{ d->setName(viewName); d->setFileName(fileName); d->setFileIndex(index); if(create) new PView(d); } } } do { if(!fgets(str, sizeof(str), fp) || feof(fp)) break; } while(str[0] != '$'); } fclose(fp); return true; }