diff --git a/Fltk/Callbacks.cpp b/Fltk/Callbacks.cpp
index 64f91c91d0bb70ea00f27408428fd849e3f0cddd..e0589192a932c3b3abfa6d4a26da3feadb759d3e 100644
--- a/Fltk/Callbacks.cpp
+++ b/Fltk/Callbacks.cpp
@@ -1,4 +1,4 @@
-// $Id: Callbacks.cpp,v 1.458 2006-08-31 21:29:18 geuzaine Exp $
+// $Id: Callbacks.cpp,v 1.459 2006-09-02 22:24:23 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -608,6 +608,7 @@ static char *file_types =
   "\tGmsh geometry (*.geo)"
   "\tGmsh mesh (*.msh)"
   "\tGmsh post-processing (*.pos)"
+  "\tI-deas universal mesh (*.unv)"
   "\tMedit mesh (*.mesh)"
   "\tNastran bulk data file (*.bdf)"
   "\tSTL surface mesh (*.stl)"
@@ -667,8 +668,7 @@ int _save_pos(char *name)
 
 int _save_unv(char *name)
 {
-  CreateOutputFile(name, FORMAT_UNV);
-  return 1;
+  return unv_dialog(name);
 }
 
 int _save_mesh(char *name)
@@ -750,6 +750,7 @@ int _save_auto(char *name)
   switch(GuessFileFormatFromFileName(name)){
   case FORMAT_OPT     : return _save_options(name);
   case FORMAT_MSH     : return _save_msh(name);
+  case FORMAT_UNV     : return _save_unv(name);
   case FORMAT_STL     : return _save_stl(name);
   case FORMAT_PS      : return _save_ps(name);
   case FORMAT_EPS     : return _save_eps(name);
diff --git a/Fltk/GUI_Extras.cpp b/Fltk/GUI_Extras.cpp
index 5088927cd92c9c74971d1b81f6e4f6eac267d50f..b55e30c392a3b791c2b9023f28bdd1bd73fd9418 100644
--- a/Fltk/GUI_Extras.cpp
+++ b/Fltk/GUI_Extras.cpp
@@ -1,4 +1,4 @@
-// $Id: GUI_Extras.cpp,v 1.22 2006-08-31 23:01:11 geuzaine Exp $
+// $Id: GUI_Extras.cpp,v 1.23 2006-09-02 22:24:23 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -676,6 +676,61 @@ int msh_dialog(char *name)
   return 0;
 }
 
+// save unv dialog
+
+int unv_dialog(char *name)
+{
+  struct _unv_dialog{
+    Fl_Window *window;
+    Fl_Check_Button *b;
+    Fl_Button *ok, *cancel;
+  };
+  static _unv_dialog *dialog = NULL;
+
+  const int BH = 2 * CTX.fontsize + 1;
+  const int BB = 7 * CTX.fontsize;
+  const int WB = 7;
+
+  if(!dialog){
+    dialog = new _unv_dialog;
+    int h = 3 * WB + 2 * BH, w = 2 * BB + 3 * WB, y = WB;
+    // not a "Dialog_Window" since it is modal 
+    dialog->window = new Fl_Double_Window(w, h, "UNV Options");
+    dialog->window->box(GMSH_WINDOW_BOX);
+    dialog->b = new Fl_Check_Button(WB, y, 2 * BB + WB, BH, "Save all (ignore physicals)"); y += BH;
+    dialog->b->type(FL_TOGGLE_BUTTON);
+    dialog->b->down_box(GMSH_TOGGLE_BOX);
+    dialog->b->selection_color(GMSH_TOGGLE_COLOR);
+    dialog->ok = new Fl_Return_Button(WB, y + WB, BB, BH, "OK");
+    dialog->cancel = new Fl_Button(2 * WB + BB, y + WB, BB, BH, "Cancel");
+    dialog->window->set_modal();
+    dialog->window->end();
+    dialog->window->hotspot(dialog->window);
+  }
+  
+  dialog->b->value(CTX.mesh.save_all);
+  dialog->window->show();
+
+  while(dialog->window->shown()){
+    Fl::wait();
+    for (;;) {
+      Fl_Widget* o = Fl::readqueue();
+      if (!o) break;
+      if (o == dialog->ok) {
+	opt_mesh_save_all(0, GMSH_SET | GMSH_GUI, dialog->b->value());
+	CreateOutputFile(name, FORMAT_UNV);
+	dialog->window->hide();
+	return 1;
+      }
+      if (o == dialog->window || o == dialog->cancel){
+	dialog->window->hide();
+	return 0;
+      }
+    }
+  }
+  return 0;
+}
+
 // save stl dialog
 
 int stl_dialog(char *name)
diff --git a/Fltk/GUI_Extras.h b/Fltk/GUI_Extras.h
index d4b161b97db0fce1a8f20395ef54055812c00a2f..569e47da2a97149d462305b5e3ca1e290a4489a6 100644
--- a/Fltk/GUI_Extras.h
+++ b/Fltk/GUI_Extras.h
@@ -35,6 +35,7 @@ int generic_bitmap_dialog(char *filename, char *title, int format);
 int gl2ps_dialog(char *filename, char *title, int format);
 int options_dialog(char *filename);
 int msh_dialog(char *filename);
+int unv_dialog(char *filename);
 int stl_dialog(char *filename);
 
 #endif
diff --git a/Geo/GModel.h b/Geo/GModel.h
index 19781f713800d249f79f4d4a27771273bea6933c..fb7c00dcba05318db2a0e96ad5e0291e09f209eb 100644
--- a/Geo/GModel.h
+++ b/Geo/GModel.h
@@ -133,7 +133,8 @@ class GModel
   int writeVRML(const std::string &name, double scalingFactor=1.0);
 
   // IO for I-deas universal mesh format
-  int writeUNV(const std::string &name, double scalingFactor=1.0);
+  int readUNV(const std::string &name);
+  int writeUNV(const std::string &name, bool saveAll=false, double scalingFactor=1.0);
 
   // IO for Medit (INRIA) mesh format
   int readMESH(const std::string &name);
diff --git a/Geo/GModelIO.cpp b/Geo/GModelIO.cpp
index 95c54545322a8088f633be6df74a5522ac2e50f9..7e0ee8cd6a783f38bc479396a9ca752abc2da2fe 100644
--- a/Geo/GModelIO.cpp
+++ b/Geo/GModelIO.cpp
@@ -1,4 +1,4 @@
-// $Id: GModelIO.cpp,v 1.36 2006-09-01 01:56:26 geuzaine Exp $
+// $Id: GModelIO.cpp,v 1.37 2006-09-02 22:24:24 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -176,23 +176,23 @@ static void storePhysicalTagsInEntities(GModel *m, int dim,
 static int getNumVerticesForElementTypeMSH(int type)
 {
   switch (type) {
-  case PNT : return 1;
-  case LGN1: return 2;
-  case LGN2: return 2 + 1;
-  case TRI1: return 3;
-  case TRI2: return 3 + 3;
-  case QUA1: return 4;
-  case QUA2: return 4 + 4 + 1;
-  case TET1: return 4;
-  case TET2: return 4 + 6;
-  case HEX1: return 8;
-  case HEX2: return 8 + 12 + 6 + 1;
-  case PRI1: return 6;
-  case PRI2: return 6 + 9 + 3;
-  case PYR1: return 5;
-  case PYR2: return 5 + 8 + 1;
+  case PNT  : return 1;
+  case LGN1 : return 2;
+  case LGN2 : return 2 + 1;
+  case TRI1 : return 3;
+  case TRI2 : return 3 + 3;
+  case QUA1 : return 4;
+  case QUA2 : return 4 + 4 + 1;
+  case TET1 : return 4;
+  case TET2 : return 4 + 6;
+  case HEX1 : return 8;
+  case HEX2 : return 8 + 12 + 6 + 1;
+  case PRI1 : return 6;
+  case PRI2 : return 6 + 9 + 3;
+  case PYR1 : return 5;
+  case PYR2 : return 5 + 8 + 1;
   default: 
-    Msg(GERROR, "Unknown type of element for MSH format");
+    Msg(GERROR, "Unknown type of element %d", type);
     return 0;
   }
 }
@@ -1105,30 +1105,104 @@ int GModel::writeVRML(const std::string &name, double scalingFactor)
   return 1;
 }
 
-static void addInGroupOfNodesUNV(FILE *fp, std::set<int> &nodes, int num)
+int GModel::readUNV(const std::string &name)
 {
-  std::set<int>::iterator it = nodes.find(num);
-  if(it == nodes.end()){
-    nodes.insert(num);
-    fprintf(fp, "%10d%10d%2d%2d%2d%2d%2d%2d\n", num, 1, 0, 1, 0, 0, 0, 0);
-    fprintf(fp, "   0.0000000000000000D+00   1.0000000000000000D+00"
-	    "   0.0000000000000000D+00\n");
-    fprintf(fp, "   0.0000000000000000D+00   0.0000000000000000D+00"
-	    "   0.0000000000000000D+00\n");
-    fprintf(fp, "%10d%10d%10d%10d%10d%10d\n", 0, 0, 0, 0, 0, 0);
+  FILE *fp = fopen(name.c_str(), "r");
+  if(!fp){
+    Msg(GERROR, "Unable to open file '%s'", name.c_str());
+    return 0;
+  }
+
+  char buffer[256];
+  std::map<int, MVertex*> vertices;
+  std::map<int, std::vector<MVertex*> > points;
+  std::map<int, std::vector<MElement*> > elements[7];
+  std::map<int, std::map<int, std::string> > physicals[4];
+
+  while(!feof(fp)) {
+    if(!fgets(buffer, sizeof(buffer), fp)) break;
+    if(!strncmp(buffer, "    -1", 6)){
+      if(!fgets(buffer, sizeof(buffer), fp)) break;      
+      if(!strncmp(buffer, "    -1", 6))
+	if(!fgets(buffer, sizeof(buffer), fp)) break;
+      int record = 0;
+      sscanf(buffer, "%d", &record);
+      if(record == 2411){ // nodes
+	while(fgets(buffer, sizeof(buffer), fp)){
+	  if(!strncmp(buffer, "    -1", 6)) break;
+	  int num, dum;
+	  if(sscanf(buffer, "%d %d %d %d", &num, &dum, &dum, &dum) != 4) break;
+	  if(!fgets(buffer, sizeof(buffer), fp)) break;
+	  double x, y, z;
+	  for(unsigned int i = 0; i < strlen(buffer); i++)
+	    if(buffer[i] == 'D') buffer[i] = 'E';
+	  if(sscanf(buffer, "%lf %lf %lf", &x, &y, &z) != 3) break;
+	  vertices[num] = new MVertex(x, y, z);
+	}
+      }
+      else if(record == 2412){ // elements
+	while(fgets(buffer, sizeof(buffer), fp)){
+	  if(strlen(buffer) < 3) continue; // possible line ending after last fscanf
+	  if(!strncmp(buffer, "    -1", 6)) break;
+	  int num, type, elementary, physical, color, numNodes;
+	  if(sscanf(buffer, "%d %d %d %d %d %d", &num, &type, &elementary, &physical, 
+		    &color, &numNodes) != 6) break;
+	  if(elementary < 0) elementary = 1;
+	  if(physical < 0) physical = 0;
+	  if(type >= 21 && type <= 24){ // beam elements
+	    if(!fgets(buffer, sizeof(buffer), fp)) break;
+	    int dum;
+	    if(sscanf(buffer, "%d %d %d", &dum, &dum, &dum) != 3) break;
+	  }
+	  int n[30];
+	  for(int i = 0; i < numNodes; i++) if(!fscanf(fp, "%d", &n[i])) break;
+	  int type_msh = 0;
+	  switch(type){
+	  case 11: case 21: case 22: case 31:                   type_msh = LGN1; break;
+	  case 23: case 24: case 32:                            type_msh = LGN2; break;
+	  case 41: case 51: case 61: case 74: case 81: case 91: type_msh = TRI1; break;
+	  case 42: case 52: case 62: case 72: case 82: case 92: type_msh = TRI2; break;
+	  case 44: case 54: case 64: case 71: case 84: case 94: type_msh = QUA1; break;
+	  case 45: case 55: case 65: case 75: case 85: case 95: type_msh = QUA2; break;
+	  case 111:                                             type_msh = TET1; break;
+	  case 118:                                             type_msh = TET2; break;
+	  case 104: case 115:                                   type_msh = HEX1; break;
+	  case 105: case 116:                                   type_msh = HEX2; break;
+	  case 101: case 112:                                   type_msh = PRI1; break;
+	  case 102: case 113:                                   type_msh = PRI2; break;
+	  }
+	  if(type_msh && getNumVerticesForElementTypeMSH(type_msh) == numNodes)
+	    createElementMSH(this, num, type_msh, physical, elementary, 0, 
+			     n, vertices, points, elements, physicals);
+	}
+      }
+    }
   }
+  
+  for(int i = 0; i < (int)(sizeof(elements)/sizeof(elements[0])); i++) 
+    storeElementsInEntities(this, elements[i]);
+  associateEntityWithVertices(this);
+  storeVerticesInEntities(vertices);
+  for(int i = 0; i < 4; i++)  
+    storePhysicalTagsInEntities(this, i, physicals[i]);
+
+  fclose(fp);
+  return 1;
 }
 
 template<class T>
-static void addInGroupOfNodesUNV(FILE *fp, std::set<int> &nodes, 
-				 std::vector<T*> &elements)
+static void writeElementsUNV(FILE *fp, const std::vector<T*> &ele, int saveAll, 
+			     int &num, int elementary, std::vector<int> &physicals)
 {
-  for(unsigned int i = 0; i < elements.size(); i++)
-    for(int j = 0; j < elements[i]->getNumVertices(); j++)
-      addInGroupOfNodesUNV(fp, nodes, elements[i]->getVertex(j)->getNum());
+  for(unsigned int i = 0; i < ele.size(); i++)
+    if(saveAll)
+      ele[i]->writeUNV(fp, ++num, elementary, 0);
+    else
+      for(unsigned int j = 0; j < physicals.size(); j++)
+	ele[i]->writeUNV(fp, ++num, elementary, physicals[j]);
 }
 
-int GModel::writeUNV(const std::string &name, double scalingFactor)
+int GModel::writeUNV(const std::string &name, bool saveAll, double scalingFactor)
 {
   FILE *fp = fopen(name.c_str(), "w");
   if(!fp){
@@ -1136,9 +1210,12 @@ int GModel::writeUNV(const std::string &name, double scalingFactor)
     return 0;
   }
 
+  // if there are no physicals we save all the elements
+  if(noPhysicalGroups()) saveAll = true;
+
   renumberMeshVertices();
 
-  // Nodes
+  // nodes
   fprintf(fp, "%6d\n", -1);
   fprintf(fp, "%6d\n", 2411);
   for(viter it = firstVertex(); it != lastVertex(); ++it)
@@ -1155,70 +1232,24 @@ int GModel::writeUNV(const std::string &name, double scalingFactor)
       (*it)->mesh_vertices[i]->writeUNV(fp, scalingFactor);
   fprintf(fp, "%6d\n", -1);  
 
-  // Elements
+  // elements
   fprintf(fp, "%6d\n", -1);
   fprintf(fp, "%6d\n", 2412);
+  int num = 0;
   for(eiter it = firstEdge(); it != lastEdge(); ++it){
-    for(unsigned int i = 0; i < (*it)->lines.size(); i++)
-      (*it)->lines[i]->writeUNV(fp, (*it)->tag());
+    writeElementsUNV(fp, (*it)->lines, saveAll, num, (*it)->tag(), (*it)->physicals);
   }
   for(fiter it = firstFace(); it != lastFace(); ++it){
-    for(unsigned int i = 0; i < (*it)->triangles.size(); i++)
-      (*it)->triangles[i]->writeUNV(fp, (*it)->tag());
-    for(unsigned int i = 0; i < (*it)->quadrangles.size(); i++)
-      (*it)->quadrangles[i]->writeUNV(fp, (*it)->tag());
+    writeElementsUNV(fp, (*it)->triangles, saveAll, num, (*it)->tag(), (*it)->physicals);
+    writeElementsUNV(fp, (*it)->quadrangles, saveAll, num, (*it)->tag(), (*it)->physicals);
   }
   for(riter it = firstRegion(); it != lastRegion(); ++it){
-    for(unsigned int i = 0; i < (*it)->tetrahedra.size(); i++)
-      (*it)->tetrahedra[i]->writeUNV(fp, (*it)->tag());
-    for(unsigned int i = 0; i < (*it)->hexahedra.size(); i++)
-      (*it)->hexahedra[i]->writeUNV(fp, (*it)->tag());
-    for(unsigned int i = 0; i < (*it)->prisms.size(); i++)
-      (*it)->prisms[i]->writeUNV(fp, (*it)->tag());
+    writeElementsUNV(fp, (*it)->tetrahedra, saveAll, num, (*it)->tag(), (*it)->physicals);
+    writeElementsUNV(fp, (*it)->hexahedra, saveAll, num, (*it)->tag(), (*it)->physicals);
+    writeElementsUNV(fp, (*it)->prisms, saveAll, num, (*it)->tag(), (*it)->physicals);
   }
   fprintf(fp, "%6d\n", -1);
 
-  std::map<int, std::vector<GEntity*> > physicals[4];
-  getPhysicalGroups(physicals);
-
-  for(int dim = 0; dim < 4; dim++){
-    std::map<int, std::vector<GEntity*> >::const_iterator it = physicals[dim].begin();
-    for(; it != physicals[dim].end(); ++it){
-      // Group of nodes
-      fprintf(fp, "%6d\n", -1);
-      fprintf(fp, "%6d\n", 790);
-      fprintf(fp, "%10d%10d\n", it->first, 1);
-      fprintf(fp, "LOAD SET %2d\n", 1);
-      std::set<int> nodes;
-      for(unsigned int i = 0; i < it->second.size(); i++){
-	// we could also do this using the mesh_vertices of the entity
-	// and all the entities in the closure
-	GVertex *v;
-	switch(dim){
-	case 0: 
-	  v = (GVertex*)it->second[i];
-	  for(unsigned int j = 0; j < v->mesh_vertices.size(); j++)
-	    addInGroupOfNodesUNV(fp, nodes, v->mesh_vertices[j]->getNum());
-	  break;
-	case 1: 
-	  addInGroupOfNodesUNV(fp, nodes, ((GEdge*)it->second[i])->lines);
-	  break;
-	case 2: 
-	  addInGroupOfNodesUNV(fp, nodes, ((GFace*)it->second[i])->triangles);
-	  addInGroupOfNodesUNV(fp, nodes, ((GFace*)it->second[i])->quadrangles);
-	  break;
-	case 3: 
-	  addInGroupOfNodesUNV(fp, nodes, ((GRegion*)it->second[i])->tetrahedra);
-	  addInGroupOfNodesUNV(fp, nodes, ((GRegion*)it->second[i])->hexahedra);
-	  addInGroupOfNodesUNV(fp, nodes, ((GRegion*)it->second[i])->prisms);
-	  addInGroupOfNodesUNV(fp, nodes, ((GRegion*)it->second[i])->pyramids);
-	  break;
-	}
-      }
-      fprintf(fp, "%6d\n", -1);
-    }
-  }
-
   fclose(fp);
   return 1;
 }
diff --git a/Geo/MElement.cpp b/Geo/MElement.cpp
index b3474ed8f5bfe926ed559d610d9e81be33c00444..1a6d564489a81b4a6ebc4f3438f06d2d799f71d3 100644
--- a/Geo/MElement.cpp
+++ b/Geo/MElement.cpp
@@ -1,4 +1,4 @@
-// $Id: MElement.cpp,v 1.13 2006-09-01 01:56:26 geuzaine Exp $
+// $Id: MElement.cpp,v 1.14 2006-09-02 22:24:24 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -250,26 +250,27 @@ void MElement::writeVRML(FILE *fp)
   fprintf(fp, "-1,\n");
 }
 
-void MElement::writeUNV(FILE *fp, int elementary)
+void MElement::writeUNV(FILE *fp, int num, int elementary, int physical)
 {
-  // if necessary, change the ordering of the vertices to get positive
-  // volume
-  setVolumePositive();
-
-  int n = getNumVertices();
   int type = getTypeForUNV();
-
-  fprintf(fp, "%10d%10d%10d%10d%10d%10d\n",
-	  _num, type, elementary, elementary, 7, n);
-  if(type == 21 || type == 24) // BEAM or BEAM2
-    fprintf(fp, "%10d%10d%10d\n", 0, 0, 0);
-  for(int k = 0; k < n; k++) {
-    fprintf(fp, "%10d", getVertex(k)->getNum());
-    if(k % 8 == 7)
+  if(type){
+    setVolumePositive();
+    int n = getNumVertices();
+    int physical_property = elementary;
+    int material_property = physical;
+    int color = 7;
+    fprintf(fp, "%10d%10d%10d%10d%10d%10d\n",
+	    num ? num : _num, type, physical_property, material_property, color, n);
+    if(type == 21 || type == 24) // linear beam or parabolic beam
+      fprintf(fp, "%10d%10d%10d\n", 0, 0, 0);
+    for(int k = 0; k < n; k++) {
+      fprintf(fp, "%10d", getVertex(k)->getNum());
+      if(k % 8 == 7)
+	fprintf(fp, "\n");
+    }
+    if(n - 1 % 8 != 7)
       fprintf(fp, "\n");
   }
-  if(n - 1 % 8 != 7)
-    fprintf(fp, "\n");
 }
 
 void MElement::writeMESH(FILE *fp, int elementary)
@@ -288,7 +289,7 @@ void MElement::writeBDF(FILE *fp, int elementary)
     for(int i = 0; i < n; i++)
       fprintf(fp, ",%d", getVertex(i)->getNum());
     if(n == 2) // CBAR
-      fprintf(fp, ",1.,1.,1.");
+      fprintf(fp, ",0.,0.,0.");
     fprintf(fp, "\n");
   }
 }
diff --git a/Geo/MElement.h b/Geo/MElement.h
index 0645fd93a9d4a1ae2bfcb90f1b196b35e9de0b0c..b32c665acb93bf46b5ea341ec8e342954a908b57 100644
--- a/Geo/MElement.h
+++ b/Geo/MElement.h
@@ -132,13 +132,12 @@ class MElement
   // IO routines
   virtual void writeMSH(FILE *fp, double version=1.0, bool binary=false, 
 			int num=0, int elementary=1, int physical=1);
-  virtual void writePOS(FILE *fp, double scalingFactor=1.0,
-			int elementary=1);
+  virtual void writePOS(FILE *fp, double scalingFactor=1.0, int elementary=1);
   virtual void writeSTL(FILE *fp, bool binary=false, double scalingFactor=1.0);
   virtual void writeVRML(FILE *fp);
-  virtual void writeUNV(FILE *fp, int elementary);
-  virtual void writeMESH(FILE *fp, int elementary);
-  virtual void writeBDF(FILE *fp, int elementary);
+  virtual void writeUNV(FILE *fp, int num=0, int elementary=1, int physical=1);
+  virtual void writeMESH(FILE *fp, int elementary=1);
+  virtual void writeBDF(FILE *fp, int elementary=1);
   virtual int getTypeForMSH() = 0;
   virtual int getTypeForUNV() = 0;
   virtual char *getStringForPOS() = 0;
@@ -168,7 +167,7 @@ class MLine : public MElement {
   virtual int getNumFaces(){ return 0; }
   virtual MFace getFace(int num){ throw; }
   int getTypeForMSH(){ return LGN1; }
-  int getTypeForUNV(){ return 21; } // BEAM
+  int getTypeForUNV(){ return 21; } // linear beam
   char *getStringForPOS(){ return "SL"; }
   char *getStringForBDF(){ return "CBAR"; }
 };
@@ -203,7 +202,7 @@ class MLine2 : public MLine {
     return MEdge(i0 < 2 ? _v[i0] : _vs[i0 - 2], i1 < 2 ? _v[i1] : _vs[i1 - 2]);
   }
   int getTypeForMSH(){ return LGN2; }
-  int getTypeForUNV(){ return 24; } // BEAM2
+  int getTypeForUNV(){ return 24; } // parabolic beam
   char *getStringForPOS(){ return "SL2"; }
   char *getStringForBDF(){ return 0; }
 };
@@ -243,7 +242,7 @@ class MTriangle : public MElement {
     return MFace(_v[0], _v[1], _v[2]); 
   }
   int getTypeForMSH(){ return TRI1; }
-  int getTypeForUNV(){ return 91; } // THINSHLL
+  int getTypeForUNV(){ return 91; } // thin shell linear triangle
   char *getStringForPOS(){ return "ST"; }
   char *getStringForBDF(){ return "CTRIA3"; }
 };
@@ -297,7 +296,7 @@ class MTriangle2 : public MTriangle {
 		 i2 < 3 ? _v[i2] : _vs[i2 - 3]);
   }
   int getTypeForMSH(){ return TRI2; }
-  int getTypeForUNV(){ return 92; } // THINSHLL2
+  int getTypeForUNV(){ return 92; } // thin shell parabolic triangle
   char *getStringForPOS(){ return "ST2"; }
   char *getStringForBDF(){ return "CTRIA6"; }
 };
@@ -328,7 +327,7 @@ class MQuadrangle : public MElement {
   virtual int getNumFaces(){ return 1; }
   virtual MFace getFace(int num){ return MFace(_v[0], _v[1], _v[2], _v[3]); }
   int getTypeForMSH(){ return QUA1; }
-  int getTypeForUNV(){ return 94; } // QUAD
+  int getTypeForUNV(){ return 94; } // thin shell linear quadrilateral
   char *getStringForPOS(){ return "SQ"; }
   char *getStringForBDF(){ return "CQUAD4"; }
 };
@@ -356,7 +355,7 @@ class MQuadrangle2 : public MQuadrangle {
   inline int getNumFaceVertices(){ return 1; }
   // TODO: edgeRep, faceRep
   int getTypeForMSH(){ return QUA2; }
-  int getTypeForUNV(){ return 95; } // ???? QUAD2
+  int getTypeForUNV(){ return 95; } // thin shell parabolic quadrilateral
   char *getStringForPOS(){ return "SQ2"; }
   char *getStringForBDF(){ return 0; }
 };
@@ -392,7 +391,7 @@ class MTetrahedron : public MElement {
 		 _v[trifaces_tetra[num][2]]);
   }
   int getTypeForMSH(){ return TET1; }
-  int getTypeForUNV(){ return 111; } // SOLIDFEM
+  int getTypeForUNV(){ return 111; } // solid linear tetrahedron
   char *getStringForPOS(){ return "SS"; }
   char *getStringForBDF(){ return "CTETRA"; }
   virtual double getVolume()
@@ -444,7 +443,7 @@ class MTetrahedron2 : public MTetrahedron {
   inline int getNumEdgeVertices(){ return 6; }
   // TODO: edgeRep, faceRep
   int getTypeForMSH(){ return TET2; }
-  int getTypeForUNV(){ return 118; } // SOLIDFEM2
+  int getTypeForUNV(){ return 118; } // solid parabolic tetrahedron
   char *getStringForPOS(){ return "SS2"; }
   char *getStringForBDF(){ return 0; }
   void setVolumePositive()
@@ -492,7 +491,7 @@ class MHexahedron : public MElement {
 		 _v[quadfaces_hexa[num][3]]);
   }
   int getTypeForMSH(){ return HEX1; }
-  int getTypeForUNV(){ return 115; } // BRICK
+  int getTypeForUNV(){ return 115; } // solid linear brick
   char *getStringForPOS(){ return "SH"; }
   char *getStringForBDF(){ return "CHEXA"; }
   virtual int getVolumeSign()
@@ -550,7 +549,7 @@ class MHexahedron2 : public MHexahedron {
   inline int getNumVolumeVertices(){ return 1; }
   // TODO: edgeRep, faceRep
   int getTypeForMSH(){ return HEX2; }
-  int getTypeForUNV(){ return 116; } // ???? BRICK2
+  int getTypeForUNV(){ return 116; } // solid parabolic brick
   char *getStringForPOS(){ return "SH2"; }
   char *getStringForBDF(){ return 0; }
   void setVolumePositive()
@@ -608,7 +607,7 @@ class MPrism : public MElement {
 		   _v[quadfaces_prism[num - 2][3]]);
   }
   int getTypeForMSH(){ return PRI1; }
-  int getTypeForUNV(){ return 112; } // WEDGE
+  int getTypeForUNV(){ return 112; } // solid linear wedge
   char *getStringForPOS(){ return "SI"; }
   char *getStringForBDF(){ return "CPENTA"; }
   virtual int getVolumeSign()
@@ -662,7 +661,7 @@ class MPrism2 : public MPrism {
   inline int getNumFaceVertices(){ return 3; }
   // TODO: edgeRep, faceRep
   int getTypeForMSH(){ return PRI2; }
-  int getTypeForUNV(){ return 113; } // ???? WEDGE2
+  int getTypeForUNV(){ return 113; } // solid parabolic wedge
   char *getStringForPOS(){ return "SI2"; }
   char *getStringForBDF(){ return 0; }
   void setVolumePositive()
@@ -716,7 +715,7 @@ class MPyramid : public MElement {
 		   _v[quadfaces_pyramid[num - 4][3]]);
   }
   int getTypeForMSH(){ return PYR1; }
-  int getTypeForUNV(){ throw; }
+  int getTypeForUNV(){ return 0; }
   char *getStringForPOS(){ return "SY"; }
   char *getStringForBDF(){ return 0; }
   virtual int getVolumeSign()
@@ -768,7 +767,7 @@ class MPyramid2 : public MPyramid {
   inline int getNumFaceVertices(){ return 1; }
   // TODO: edgeRep, faceRep
   int getTypeForMSH(){ return PYR2; }
-  int getTypeForUNV(){ throw; }
+  int getTypeForUNV(){ return 0; }
   char *getStringForPOS(){ return "SY2"; }
   char *getStringForBDF(){ return 0; }
   void setVolumePositive()
diff --git a/Geo/MVertex.cpp b/Geo/MVertex.cpp
index bae513d7f2ee4f83400fcb94a9c3662c32442578..2875fff59882da0576cc89b3bd50fdac9251e81b 100644
--- a/Geo/MVertex.cpp
+++ b/Geo/MVertex.cpp
@@ -1,4 +1,4 @@
-// $Id: MVertex.cpp,v 1.7 2006-08-31 21:29:18 geuzaine Exp $
+// $Id: MVertex.cpp,v 1.8 2006-09-02 22:24:24 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -67,7 +67,10 @@ void MVertex::writeVRML(FILE *fp, double scalingFactor)
 
 void MVertex::writeUNV(FILE *fp, double scalingFactor)
 {
-  fprintf(fp, "%10d%10d%10d%10d\n", _num, 1, 1, 11);
+  int coord_sys = 1;
+  int displacement_coord_sys = 1;
+  int color = 11;
+  fprintf(fp, "%10d%10d%10d%10d\n", _num, coord_sys, displacement_coord_sys, color);
   // hack to print the numbers with "D+XX" exponents
   char tmp[128];
   sprintf(tmp, "%25.16E%25.16E%25.16E\n", x() * scalingFactor, 
diff --git a/Parser/CreateFile.cpp b/Parser/CreateFile.cpp
index 6b59d1e9fbfcdfcccb5999491ec3a30d2cb5ce79..9bd386e43ed18a1a9f5f276cb72ca4a3693aeb38 100644
--- a/Parser/CreateFile.cpp
+++ b/Parser/CreateFile.cpp
@@ -1,4 +1,4 @@
-// $Id: CreateFile.cpp,v 1.6 2006-08-31 21:29:18 geuzaine Exp $
+// $Id: CreateFile.cpp,v 1.7 2006-09-02 22:24:24 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -158,7 +158,7 @@ void CreateOutputFile(char *filename, int format)
     break;
 
   case FORMAT_UNV:
-    GMODEL->writeUNV(name, CTX.mesh.scaling_factor);
+    GMODEL->writeUNV(name, CTX.mesh.save_all, CTX.mesh.scaling_factor);
     break;
 
   case FORMAT_MESH:
diff --git a/Parser/OpenFile.cpp b/Parser/OpenFile.cpp
index d66ca18aa004d80b9eb3ae509165234ed9eeb2c5..a239547d42192de7ffd34ba5b5cd9eeae6b1ce97 100644
--- a/Parser/OpenFile.cpp
+++ b/Parser/OpenFile.cpp
@@ -1,4 +1,4 @@
-// $Id: OpenFile.cpp,v 1.119 2006-08-31 21:29:18 geuzaine Exp $
+// $Id: OpenFile.cpp,v 1.120 2006-09-02 22:24:24 geuzaine Exp $
 //
 // Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
 //
@@ -285,6 +285,9 @@ int MergeProblem(char *name, int warn_if_missing)
   if(!strcmp(ext, ".stl") || !strcmp(ext, ".STL")){
     status = GMODEL->readSTL(name, CTX.mesh.stl_distance_tol);
   }
+  else if(!strcmp(ext, ".unv") || !strcmp(ext, ".UNV")){
+    status = GMODEL->readUNV(name);
+  }
   else if(!strcmp(ext, ".wrl") || !strcmp(ext, ".WRL") || 
 	  !strcmp(ext, ".vrml") || !strcmp(ext, ".VRML") ||
 	  !strcmp(ext, ".iv") || !strcmp(ext, ".IV")){