From 96fc2c5c140c39edc1dade8d9ff5583bf3509a7b Mon Sep 17 00:00:00 2001
From: Christophe Geuzaine <cgeuzaine@ulg.ac.be>
Date: Mon, 24 Mar 2008 20:51:04 +0000
Subject: [PATCH] fine-tune MED mesh I/O (saveAll, read points, etc.)

---
 Fltk/Callbacks.cpp    |   4 +-
 Geo/GModel.h          |   3 +-
 Geo/GModelIO_MED.cpp  | 118 ++++++++++++++++++++++++++----------------
 Parser/CreateFile.cpp |   4 +-
 4 files changed, 80 insertions(+), 49 deletions(-)

diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 9259a39df7..337d58dd83 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.573 2008-03-23 21:42:56 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.574 2008-03-24 20:51:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -664,7 +664,7 @@ int _save_options(const char *name){ return options_dialog(name); }
 int _save_geo(const char *name){ return geo_dialog(name); }
 int _save_cgns(const char *name){ CreateOutputFile(name, FORMAT_CGNS); return 1; }
 int _save_unv(const char *name){ return unv_dialog(name); }
-int _save_med(const char *name){ CreateOutputFile(name, FORMAT_MED); return 1; }
+int _save_med(const char *name){ return generic_mesh_dialog(name, "MED Options", FORMAT_MED); }
 int _save_mesh(const char *name){ return generic_mesh_dialog(name, "MESH Options", FORMAT_MESH); }
 int _save_bdf(const char *name){ return bdf_dialog(name); }
 int _save_p3d(const char *name){ return generic_mesh_dialog(name, "P3D Options", FORMAT_P3D); }
diff --git a/Geo/GModel.h b/Geo/GModel.h
index f075f0e7f9..94702b258a 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -261,7 +261,8 @@ class GModel
 
   // Med interface ("Modele d'Echange de Donnees")
   int readMED(const std::string &name);
-  int writeMED(const std::string &name, double scalingFactor=1.0);
+  int writeMED(const std::string &name, 
+	       bool saveAll=false, double scalingFactor=1.0);
 };
 
 #endif
diff --git a/Geo/GModelIO_MED.cpp b/Geo/GModelIO_MED.cpp
index 788cc6d385..9a85f4c48e 100644
--- a/Geo/GModelIO_MED.cpp
+++ b/Geo/GModelIO_MED.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO_MED.cpp,v 1.13 2008-03-24 06:39:13 geuzaine Exp $
+// $Id: GModelIO_MED.cpp,v 1.14 2008-03-24 20:51:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -31,6 +31,7 @@
 #include <cstring>
 #include "MElement.h"
 #include "MVertex.h"
+#include "discreteVertex.h"
 
 extern "C" {
 #include <med.h>
@@ -83,7 +84,7 @@ static void writeElementsMED(med_idt &fid, char *meshName,
     Msg(GERROR, "Could not write elements");
 }
 
-int GModel::writeMED(const std::string &name, double scalingFactor)
+int GModel::writeMED(const std::string &name, bool saveAll, double scalingFactor)
 {
   med_idt fid = MEDouvrir((char*)name.c_str(), MED_CREATION);
   if(fid < 0) {
@@ -106,9 +107,12 @@ int GModel::writeMED(const std::string &name, double scalingFactor)
     return 0;
   }
   
-  // renumber all the vertices in a continuous sequence (MED
+  // if there are no physicals we save all the elements
+  if(noPhysicalGroups()) saveAll = true;
+
+  // renumber the vertices we will save in a continuous sequence (MED
   // connectivity is given in terms of vertex indices)
-  renumberMeshVertices(true);
+  renumberMeshVertices(saveAll);
 
   // fill a vector containing all the geometrical entities in the model
   std::vector<GEntity*> entities;
@@ -128,24 +132,26 @@ int GModel::writeMED(const std::string &name, double scalingFactor)
     // create one family per elementary entity, with one group per
     // physical entity and no attributes
     for(unsigned int i = 0; i < entities.size(); i++){
-      int num = - (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]->physicals[j]);
-	std::ostringstream gs;
-	gs << entities[i]->dim() << "D_" << tmp;
-	if(tmp.empty()) gs << entities[i]->physicals[j];
-	groupName += "G_" + gs.str();
-	groupName.resize((j + 1) * 80, ' ');
+      if(saveAll || entities[i]->physicals.size()){
+	int num = - (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]->physicals[j]);
+	  std::ostringstream gs;
+	  gs << entities[i]->dim() << "D_" << tmp;
+	  if(tmp.empty()) gs << entities[i]->physicals[j];
+	  groupName += "G_" + gs.str();
+	  groupName.resize((j + 1) * 80, ' ');
+	}
+	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)
+	  Msg(GERROR, "Could not create MED family %d", num);
       }
-      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)
-	Msg(GERROR, "Could not create MED family %d", num);
     }
   }
   
@@ -165,6 +171,10 @@ int GModel::writeMED(const std::string &name, double scalingFactor)
 	}
       }
     }
+    if(num.empty()){
+      Msg(GERROR, "No nodes to write in MED mesh");
+      return 0;
+    }
     char coordName[3 * MED_TAILLE_PNOM + 1] = 
       "x               y               z               ";
     char coordUnit[3 * MED_TAILLE_PNOM + 1] = 
@@ -183,52 +193,61 @@ int GModel::writeMED(const std::string &name, double scalingFactor)
     { // points
       std::vector<med_int> num, conn, fam;
       for(viter it = firstVertex(); it != lastVertex(); it++){
-	num.push_back(++ele);
-	conn.push_back((*it)->mesh_vertices[0]->getNum());
-	fam.push_back(families[*it]);
+	if(saveAll || (*it)->physicals.size()){
+	  num.push_back(++ele);
+	  conn.push_back((*it)->mesh_vertices[0]->getNum());
+	  fam.push_back(families[*it]);
+	}
       }
       writeElementsMED(fid, meshName, num, conn, fam, MED_POINT1);
     }
     { // lines
       std::vector<med_int> num, conn, fam;
       for(eiter it = firstEdge(); it != lastEdge(); it++)
-	fillElementsMED(families[*it], (*it)->lines, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->lines, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // triangles
       std::vector<med_int> num, conn, fam;
       for(fiter it = firstFace(); it != lastFace(); it++)
-	fillElementsMED(families[*it], (*it)->triangles, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->triangles, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // quads
       std::vector<med_int> num, conn, fam;
       for(fiter it = firstFace(); it != lastFace(); it++)
-	fillElementsMED(families[*it], (*it)->quadrangles, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->quadrangles, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // tets
       std::vector<med_int> num, conn, fam;
       for(riter it = firstRegion(); it != lastRegion(); it++)
-	fillElementsMED(families[*it], (*it)->tetrahedra, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->tetrahedra, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // hexas
       std::vector<med_int> num, conn, fam;
       for(riter it = firstRegion(); it != lastRegion(); it++)
-	fillElementsMED(families[*it], (*it)->hexahedra, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->hexahedra, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // prisms
       std::vector<med_int> num, conn, fam;
       for(riter it = firstRegion(); it != lastRegion(); it++)
-	fillElementsMED(families[*it], (*it)->prisms, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->prisms, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
     { // pyramids
       std::vector<med_int> num, conn, fam;
       for(riter it = firstRegion(); it != lastRegion(); it++)
-	fillElementsMED(families[*it], (*it)->pyramids, ele, num, conn, fam, typ);
+	if(saveAll || (*it)->physicals.size())
+	  fillElementsMED(families[*it], (*it)->pyramids, ele, num, conn, fam, typ);
       writeElementsMED(fid, meshName, num, conn, fam, typ);
     }
   }
@@ -255,8 +274,7 @@ int GModel::readMED(const std::string &name)
     return 0;
   }
   if(numMeshes > 1)
-    Msg(WARNING, "There are %d meshes in the MED file: reading only the first",
-	numMeshes);
+    Msg(WARNING, "Reading mesh 1 of %d (ignoring the other)", numMeshes);
 
   // read mesh info
   char meshName[MED_TAILLE_NOM + 1], meshDesc[MED_TAILLE_DESC + 1];
@@ -327,22 +345,34 @@ int GModel::readMED(const std::string &name)
     std::vector<med_int> eleTags(numEle);
     if(MEDnumLire(fid, meshName, &eleTags[0], numEle, MED_MAILLE, type) < 0)
       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 + k] - 1];
-      MElement *e = factory.create(mshType, v, eleTags.empty() ? 0 : eleTags[j]);
-      if(e) elements[-fam[j]].push_back(e);
+    if(numNodPerEle == 1){ // special case for points
+      for(int j = 0; j < numEle; j++){    
+	GVertex *v = getVertexByTag(-fam[j]);
+	if(!v){
+	  v = new discreteVertex(this, -fam[j]);
+	  add(v);
+	}
+	v->mesh_vertices.push_back(verts[conn[j] - 1]);
+      }
+    }
+    else{
+      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 + k] - 1];
+	MElement *e = factory.create(mshType, v, eleTags.empty() ? 0 : eleTags[j]);
+	if(e) elements[-fam[j]].push_back(e);
+      }
+      _storeElementsInEntities(elements);
     }
-    _storeElementsInEntities(elements);	
   }
   _associateEntityWithMeshVertices();
   for(unsigned int i = 0; i < verts.size(); i++){
     GEntity *ge = verts[i]->onWhat();
-    if(ge) ge->mesh_vertices.push_back(verts[i]);
-    else delete verts[i]; // delete all unused vertices
+    if(ge && ge->dim()) ge->mesh_vertices.push_back(verts[i]);
+    if(!ge) delete verts[i]; // delete unused vertices
   }
 
   // read family info
diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp
index 6891fb0d38..0e5e709be9 100644
--- a/Parser/CreateFile.cpp
+++ b/Parser/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.27 2008-03-23 21:42:57 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.28 2008-03-24 20:51:04 geuzaine Exp $
 //
 // Copyright (C) 1997-2008 C. Geuzaine, J.-F. Remacle
 //
@@ -186,7 +186,7 @@ void CreateOutputFile(const char *filename, int format)
     break;
 
   case FORMAT_MED:
-    GModel::current()->writeMED(name, CTX.mesh.scaling_factor);
+    GModel::current()->writeMED(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
     break;
 
   case FORMAT_POS:
-- 
GitLab