Skip to content
Snippets Groups Projects
Forked from gmsh / gmsh
16815 commits behind the upstream repository.
GModelIO_MED.cpp 10.52 KiB
// $Id: GModelIO_MED.cpp,v 1.8 2008-01-20 11:39:47 geuzaine Exp $
//
// Copyright (C) 1997-2006 C. Geuzaine, J.-F. Remacle
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
// USA.
// 
// Please report all bugs and problems to <gmsh@geuz.org>.

#include "GModel.h"
#include "MElement.h"
#include "MVertex.h"
#include "MEdge.h"
#include "Message.h"

#if defined(HAVE_MED)

#include <map>
#include <string>
#include <vector>
#include <iostream>
#include <sstream>
#include "GModelIO_MED.h"

extern "C" {
#include "med.h"
}

ConversionData Data::MyConversionData;

typedef std::list<int>::const_iterator listIter;

// _____________________________________________ //
//                                               //
// Implementation  de la classe  ConversionData  //
//  ____________________________________________ //

ConversionData::ConversionData()
{ 
	// Correspondance des types GMSH et MEd
	static const med_geometrie_element ValuesTypesOfElts[] = {  MED_SEG2,    MED_TRIA3,  MED_QUAD4,   MED_TETRA4,
								    MED_HEXA8,   MED_PENTA6, MED_PYRA5,   MED_SEG3, 
								    MED_TRIA6,   MED_QUAD8,  MED_TETRA10, MED_HEXA20, 
								    MED_PENTA15, MED_PYRA13, MED_POINT1,  MED_QUAD8,
								    MED_HEXA20,  MED_PENTA15, MED_PYRA13,  MED_NONE};
		
	int i=0;
	while (ValuesTypesOfElts[i] != MED_NONE)
	{
	   typesOfElts[i+1]=ValuesTypesOfElts[i];
	   ++i;
	}

	// **************************
	// Numrotation des Noeuds
	// **************************
	//
	// line ( 1er et 2nd Ordre)
	i=1;
	while ( i!=3 ) { 
	   medVertexOrder[1].push_back(i);
	   medVertexOrder[8].push_back(i);
	   ++i;
	}
	medVertexOrder[8].push_back(3);

	// tria
	i=1;
	while ( i!=4 ) { 
	   medVertexOrder[2].push_back(i);
	   medVertexOrder[9].push_back(i);
	   ++i;
	}
	medVertexOrder[9].push_back(4);
	medVertexOrder[9].push_back(5);
	medVertexOrder[9].push_back(6);

	// quad
	i=1;
	while ( i!=5 ) { 
	   medVertexOrder[3].push_back(i);
	   medVertexOrder[10].push_back(i);
	   medVertexOrder[16].push_back(i);
	   ++i;
	}
	medVertexOrder[10].push_back(5);
	medVertexOrder[16].push_back(5);
	medVertexOrder[10].push_back(6);
	medVertexOrder[16].push_back(6);
	medVertexOrder[10].push_back(7);
	medVertexOrder[16].push_back(7);
	medVertexOrder[10].push_back(8);
	medVertexOrder[16].push_back(8);

	// tetra
	static const int OrderforTetra[] = { 1, 3, 2, 4, 0 };
	i=0;
	while ( OrderforTetra[i] != 0 ) { 
	   medVertexOrder[4].push_back(OrderforTetra[i]);
	   medVertexOrder[11].push_back(OrderforTetra[i]);
	   ++i;
	}
	static const int OrderforTetra2[] = { 7, 6 , 5, 8 , 9 , 10, 0 }; 
	i=0;
	while ( OrderforTetra2[i] != 0 ) { 
	   medVertexOrder[11].push_back(OrderforTetra2[i]);
	   ++i;
	}

	// hexa
	// le 1 MED est le 1er Gmsh,   le 2nd Med est le 4ieme Gmsh , le 3 le 6 ...
	static const int OrderforHexa[] = { 1, 5, 8,  4, 2, 6, 7, 3, 0};
	i=0;
	while (OrderforHexa[i] != 0)
	{
	   medVertexOrder[5].push_back(OrderforHexa[i]);
	   medVertexOrder[12].push_back(OrderforHexa[i]);
	   medVertexOrder[17].push_back(OrderforHexa[i]);
	   ++i;
	};
	static const int OrderforHexa2[] = { 11,18,16,10,13,19,15,16,9,17,20,14, 0 }; 
	i=0;
	while ( OrderforHexa2[i] != 0 ) { 
	   medVertexOrder[12].push_back(OrderforHexa2[i]);
	   medVertexOrder[17].push_back(OrderforHexa2[i]);
	   ++i;
	}
	// Prism
	static const int OrderforPrism[] = { 1, 3, 2, 4, 6, 5, 0};
	i=0;
	while (OrderforPrism[i] != 0)
	{
	   medVertexOrder[6].push_back(OrderforPrism[i]);
	   medVertexOrder[13].push_back(OrderforPrism[i]);
	   medVertexOrder[18].push_back(OrderforPrism[i]);
	   ++i;
	};
	static const int OrderforPrism2[] = { 8, 10, 7, 14, 13, 15, 9, 12, 11, 0};
	i=0;
	while ( OrderforPrism2[i] != 0 ) { 
	   medVertexOrder[13].push_back(OrderforPrism2[i]);
	   medVertexOrder[18].push_back(OrderforPrism2[i]);
	   ++i;
	}


	//Pyra
	static const int OrderforPyra[] = { 1, 4, 3, 2, 5, 0};
	i=0;
	while (OrderforPyra[i] != 0)
	{
	   medVertexOrder[7].push_back(OrderforPyra[i]);
	   medVertexOrder[14].push_back(OrderforPyra[i]);
	   medVertexOrder[19].push_back(OrderforPyra[i]);
	   ++i;
	};
	static const int OrderforPyra2[] = { 7, 11 ,9 , 6, 8, 13, 12 , 10, 0};
	i=0;
	while ( OrderforPyra2[i] != 0 ) { 
	   medVertexOrder[14].push_back(OrderforPyra2[i]);
	   medVertexOrder[19].push_back(OrderforPyra2[i]);
	   ++i;
	}
};


// ____________________________________ //
//                                      //
// Implementation  de la classe  MedIO  //
//  ___________________________________ //

MedIO::MedIO() : _numOfNode(1), _boolOpen(0), _meshName("monMaillage")
{ 
};

// --------------------------------------------
int MedIO::SetFile(const std::string &FileName)
// --------------------------------------------
// Open Med File
// Headers Creation in Med File 
// Mesh Creation in Med File
{
   _FileName = FileName;
   // All Meshes are 3D and unstructured Meshes
   med_err ret = 0;
   char des[MED_TAILLE_DESC+1]="Med file generated by  Gmsh";

   _fid = MEDouvrir((char *) _FileName.c_str(),MED_CREATION);
   if (_fid < 0) {
       Msg(GERROR, "Unable to open file '%s'", _FileName.c_str());
       return 0;
   }

   if (MEDfichDesEcr(_fid,des) < 0) {
       Msg(GERROR, "Unable to write descriptor in file '%s'", _FileName.c_str());
       return 0;
   }

   std::string description = "gmsh";
   if (MEDmaaCr(_fid,(char *) _meshName.c_str(),3,MED_NON_STRUCTURE,(char *) description.c_str()) < 0) 
   {
       Msg(GERROR, "Error in Mesh Creation '%s'", _FileName.c_str());
       return 0;
   }
   _boolOpen=1;
    Msg(INFO, "File Open");
   return 1;
}
 
// -------------------------------------------------
int MedIO::AddNode(MVertex* v, const int famille)
// -------------------------------------------------
{ 
    //Msg(INFO, "Creation %d", v->getNum());
   
   if ( elements.find(v->getNum()) != elements.end() ) return 1;
   coordonnees.push_back((med_float)v->x());
   coordonnees.push_back((med_float)v->y());
   coordonnees.push_back((med_float)v->z());

   numOpt.push_back(v->getNum());
   elements[v->getNum()] = _numOfNode ;
   _numOfNode = _numOfNode + 1;

   families.push_back(famille);
   numFamilles.insert(famille);
   return 1;
}

// -------------------------------
int MedIO::CreateFamilles( )
// -------------------------------
{
   numFamilles.insert(0);
   std::set<int>::const_iterator itFam;
   for (itFam = numFamilles.begin(); itFam != numFamilles.end(); ++itFam) {
	med_err CR;
	if (*itFam != 0 )
	{ std::ostringstream oss;
          oss << *itFam;
          std::string fam = "F_" + oss.str();
          std::string group = "G_" + oss.str();
	  while (group.size() < 80) group = group + " ";
          CR = MEDfamCr (_fid, (char *) _meshName.c_str(),(char *)fam.c_str(),*itFam, 0,0,0,0,(char *)group.c_str(),1);
	  CR=0;
	}
	else
	{
          std::string fam = "Famille0";
          CR = MEDfamCr (_fid, (char *) _meshName.c_str(),(char *)fam.c_str(),*itFam, 0,0,0,0,0,0);
	}
        if ( CR < 0 )
        {
            Msg(GERROR, "Error in Family Creation '%d'", *itFam );
            return 0;
         }
   }
   return 1;
}


// -------------------------------
int MedIO::CreateElemt()
// -------------------------------
{
    std::map<int,med_geometrie_element>::const_iterator eltIter = Data::MyConversionData.typesOfElts.begin();
    for ( ; eltIter != Data::MyConversionData.typesOfElts.end(); ++eltIter ) {
       med_geometrie_element typemed =(*eltIter).second;
       if (typemed == MED_POINT1) continue;
       int nbNoeudElt = typemed % 100 ;
       int nbElements = LesConn[typemed].size() / nbNoeudElt;
       if (nbElements != 0 )
           med_err CR = MEDelementsEcr (_fid, (char*) _meshName.c_str(),(med_int) 3, 
		         &LesConn[typemed][0], MED_FULL_INTERLACE,
			 NULL, MED_FAUX, NULL, MED_FAUX,
			 &famElts[typemed][0],nbElements,
			   MED_MAILLE,typemed,MED_NOD);

    }
};
// ------------------------------------------
int MedIO::Ecrit()
// ------------------------------------------
{
    if (_boolOpen != 1)
    {
        Msg(GERROR, "File not Open");
	return 0;
    }

    int nbNoeuds=coordonnees.size() / 3;
    if (nbNoeuds != families.size())
    {
        Msg(GERROR, "bad Vectors");
	return 0;
    }

    // *********************
    // Creation des Familles
    // *********************
    int CRFam = CreateFamilles();
    if ( CRFam < 0 )
    {
       Msg(GERROR, "Error in Nodes Families Creation ");
       return 0;
    }

    // *************************
    // Creation des Coordonnees
    // *************************
    char nomcoo[3*MED_TAILLE_PNOM+1] = "x               y               z               ";
    char unicoo[3*MED_TAILLE_PNOM+1] = "inconnu         inconnu         inconnu         ";

    med_err CR = MEDnoeudsEcr(_fid, (char*) _meshName.c_str(),(med_int) 3, 
		              &coordonnees[0], MED_FULL_INTERLACE, MED_CART,
		              nomcoo,unicoo, NULL, MED_FAUX, 
			      &numOpt[0], MED_VRAI, 
			      &families[0], nbNoeuds);
    Msg(INFO, "%d ", CR);
    if ( CR < 0 )
    {
       Msg(GERROR, "Error in Nodes Creation ");
       return 0;
    }
    // ***************************
    // Creation des connectivits
    // ***************************
    int CRElt = CreateElemt();
    if ( CRElt < 0 )
    {
       Msg(GERROR, "Error in Elements Creation ");
       return 0;
    }
    return 1;
}

//--------------------
int MedIO::CloseFile()
//--------------------
{
   if (MEDfermer(_fid) < 0) 
   {
       Msg(GERROR, "Unable to close file '%s'",(char * ) _FileName.c_str());
       return 0;
   }
  return 1;
}


int GModel::writeMED(const std::string &name)
{

   MedIO MedDriver = MedIO();
   int CR1 = MedDriver.SetFile(name);

   renumberMeshVertices(noPhysicalGroups());
   MedDriver.TraiteMed(vertices);
   MedDriver.TraiteMed(edges);
   MedDriver.TraiteMed(faces);
   MedDriver.TraiteMed(regions);

   int CR2 = MedDriver.Ecrit();
   int CR3 = MedDriver.CloseFile();

   return CR1 * CR2 * CR3 ;
}

#else

int GModel::writeMED(const std::string &name)
{
  Msg(GERROR, "Gmsh has to be compiled with MED support to write '%s'",
      name.c_str());
  return 0;
}

#endif                // du HAVE_LIBMED