Beispiel #1
0
void MVertex::deleteLast()
{
  GModel *m = GModel::current();
  if(_num == m->getMaxVertexNumber())
    m->setMaxVertexNumber(m->getMaxVertexNumber() - 1);
  delete this;
}
Beispiel #2
0
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();
}
Beispiel #3
0
/***********************************************************************//**
 * @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;

}
Beispiel #4
0
/***********************************************************************//**
 * @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;

}
Beispiel #5
0
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);
	}
  }
}
Beispiel #6
0
/***********************************************************************//**
 * @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;
}
Beispiel #7
0
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;
}
Beispiel #8
0
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();
}
Beispiel #9
0
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;
  }
}
Beispiel #10
0
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;
}
Beispiel #11
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;
}
Beispiel #12
0
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;
}
Beispiel #13
0
/***********************************************************************//**
 * @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;
}
Beispiel #14
0
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 ;
}
Beispiel #15
0
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)));
  }
}
Beispiel #17
0
// 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;

}
Beispiel #18
0
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
}
Beispiel #19
0
// 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);
}
Beispiel #21
0
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));
}
Beispiel #22
0
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;
}
Beispiel #23
0
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;
}