Back to index

salome-med  6.5.0
Public Member Functions | Public Attributes | Private Member Functions | Private Attributes | Friends
SauvUtilities::IntermediateMED Struct Reference

More...

#include <SauvMedConvertor.hxx>

Collaboration diagram for SauvUtilities::IntermediateMED:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 IntermediateMED ()
 ~IntermediateMED ()
 Destructor of IntermediateMED.
NodegetNode (TID nID)
int getNbCellsOfType (TCellType type) const
const Cellinsert (TCellType type, const Cell &ma)
ParaMEDMEM::MEDFileDataconvertInMEDFileDS ()
 Makes ParaMEDMEM::MEDFileData from self.

Public Attributes

unsigned _spaceDim
unsigned _nbNodes
NodeContainer _points
std::vector< double > _coords
std::vector< Group_groups
std::vector< DoubleField * > _nodeFields
std::vector< DoubleField * > _cellFields
std::list< nameGIBItoMED_listGIBItoMED_mail
std::list< nameGIBItoMED_listGIBItoMED_cham
std::list< nameGIBItoMED_listGIBItoMED_comp
std::map< int, std::string > _mapStrings

Private Member Functions

ParaMEDMEM::MEDFileUMeshmakeMEDFileMesh ()
 Creates ParaMEDMEM::MEDFileUMesh from its data.
ParaMEDMEM::DataArrayDoublegetCoords ()
 Creates coord array.
void setConnectivity (ParaMEDMEM::MEDFileUMesh *mesh, ParaMEDMEM::DataArrayDouble *coords)
 Sets connectivity of elements to the mesh.
void setGroups (ParaMEDMEM::MEDFileUMesh *mesh)
 Fill in the mesh with groups.
ParaMEDMEM::MEDFileFieldsmakeMEDFileFields (ParaMEDMEM::MEDFileUMesh *mesh)
 Makes fields from own data.
void setFields (SauvUtilities::DoubleField *fld, ParaMEDMEM::MEDFileFields *medFields, ParaMEDMEM::MEDFileUMesh *mesh, const TID castemID, std::set< std::string > &usedNames)
 Make med fields from a SauvUtilities::DoubleField.
void setTS (SauvUtilities::DoubleField *fld, ParaMEDMEM::DataArrayDouble *values, ParaMEDMEM::MEDFileFields *medFields, ParaMEDMEM::MEDFileUMesh *mesh, const int iSub=0)
 Store value array of a field into med fields.
void checkDataAvailability () const throw (INTERP_KERNEL::Exception)
 Throw an exception if not all needed data is present.
void setGroupLongNames ()
 Set long names to groups.
void setFieldLongNames (std::set< std::string > &usedNames)
 Set long names to fields.
void makeFieldNewName (std::set< std::string > &usedNames, SauvUtilities::DoubleField *fld)
 Make a new unique name for a field.
void decreaseHierarchicalDepthOfSubgroups ()
 Decrease hierarchical depth of subgroups.
void eraseUselessGroups ()
 Erase _groups that won't be converted.
void detectMixDimGroups ()
 Detect _groups of mixed dimension.
void orientElements2D ()
 Fix connectivity of elements in 2D space.
void orientElements3D ()
 Fix connectivity of elements in 3D space.
void orientFaces3D ()
 Orient equally (by setting _reverse flag) all connected faces in 3D space.
void orientVolumes ()
 Orient volumes according to MED conventions: normal of a bottom (first) face should be outside.
void numberElements ()
 Assign new IDs to elements.
bool isOnAll (const Group *grp, int &dimRel) const
 Return true if the group is on all elements and return its relative dimension.
const double * nodeCoords (const Node *n)

Private Attributes

std::set< Cell_cellsByType [INTERP_KERNEL::NORM_HEXA20+1]

Friends

class CellsByDimIterator

Detailed Description

Definition at line 234 of file SauvMedConvertor.hxx.


Constructor & Destructor Documentation

Definition at line 250 of file SauvMedConvertor.hxx.

: _spaceDim(0), _nbNodes(0) {}

Destructor of IntermediateMED.

Definition at line 2383 of file SauvMedConvertor.cxx.

{
  for ( size_t i = 0; i < _nodeFields.size(); ++i )
    if ( _nodeFields[i] )
      delete _nodeFields[i];
  _nodeFields.clear();

  for ( size_t i = 0; i < _cellFields.size(); ++i )
    if ( _cellFields[i] )
      delete _cellFields[i];
  _cellFields.clear();

  for ( size_t i = 0; i < _groups.size(); ++i )
    if ( _groups[i]._medGroup )
      _groups[i]._medGroup->decrRef();
}

Member Function Documentation

void IntermediateMED::checkDataAvailability ( ) const throw (INTERP_KERNEL::Exception) [private]

Throw an exception if not all needed data is present.

Definition at line 1086 of file SauvMedConvertor.cxx.

{
  if ( _spaceDim == 0 )
    THROW_IK_EXCEPTION("Wrong file format"); // it is the first record in the sauve file

  if ( _groups.empty() )
    THROW_IK_EXCEPTION("No elements have been read");

  if ( _points.empty() || _nbNodes == 0 )
    THROW_IK_EXCEPTION("Nodes of elements are not filled");

  if ( _coords.empty() )
    THROW_IK_EXCEPTION("Node coordinates are missing");

  if ( _coords.size() < _nbNodes * _spaceDim )
    THROW_IK_EXCEPTION("Nodes and coordinates mismatch");
}

Here is the call graph for this function:

Here is the caller graph for this function:

Makes ParaMEDMEM::MEDFileData from self.

Definition at line 1110 of file SauvMedConvertor.cxx.

{
  MEDCouplingAutoRefCountObjectPtr< MEDFileUMesh >  mesh   = makeMEDFileMesh();
  MEDCouplingAutoRefCountObjectPtr< MEDFileFields > fields = makeMEDFileFields(mesh);

  MEDCouplingAutoRefCountObjectPtr< MEDFileMeshes > meshes = MEDFileMeshes::New();
  MEDCouplingAutoRefCountObjectPtr< MEDFileData >  medData = MEDFileData::New();
  meshes->pushMesh( mesh );
  medData->setMeshes( meshes );
  if ( fields ) medData->setFields( fields );

  medData->incrRef();
  return medData;
}

Here is the call graph for this function:

Decrease hierarchical depth of subgroups.

Definition at line 1264 of file SauvMedConvertor.cxx.

{
  for (size_t i=0; i!=_groups.size(); ++i)
  {
    Group& grp = _groups[i];
    for (size_t j = 0; j < grp._groups.size(); ++j )
    {
      Group & sub_grp = *grp._groups[j];
      if ( !sub_grp._groups.empty() )
      {
        // replace j with its 1st subgroup
        grp._groups[j] = sub_grp._groups[0];
        // push back the rest subs
        grp._groups.insert( grp._groups.end(), ++sub_grp._groups.begin(), sub_grp._groups.end() );
      }
    }
    // remove empty sub-_groups
    vector< Group* > newSubGroups;
    newSubGroups.reserve( grp._groups.size() );
    for (size_t j = 0; j < grp._groups.size(); ++j )
      if ( !grp._groups[j]->empty() )
        newSubGroups.push_back( grp._groups[j] );
    if ( newSubGroups.size() < grp._groups.size() )
      grp._groups.swap( newSubGroups );
  }
}

Here is the caller graph for this function:

Detect _groups of mixed dimension.

Definition at line 1344 of file SauvMedConvertor.cxx.

{
  //hasMixedCells = false;
  for ( size_t i=0; i < _groups.size(); ++i )
  {
    Group& grp = _groups[i];
    if ( grp._groups.size() < 2 )
      continue;

    // check if sub-groups have different dimension
    unsigned dim1 = getDim( &grp );
    for ( size_t j = 1; j  < grp._groups.size(); ++j )
    {
      unsigned dim2 = getDim( &grp );
      if ( dim1 != dim2 )
      {
        grp._cells.clear();
        grp._groups.clear();
        if ( !grp._name.empty() )
          cout << "Erase a group with elements of different dim |" << grp._name << "|"<< endl;
        break;
      }
    }
  }
}

Here is the caller graph for this function:

Erase _groups that won't be converted.

Definition at line 1297 of file SauvMedConvertor.cxx.

{
  // propagate _isProfile=true to sub-groups of composite groups
  // for (size_t int i=0; i!=_groups.size(); ++i)
  // {
  //   Group* grp = _groups[i];
  //   if ( grp->_isProfile && !grp->_groups.empty() )
  //     for (size_t j = 0; j < grp->_groups.size(); ++j )
  //       grp->_groups[j]->_isProfile=true;
  // }
  std::set<Group*> groups2convert;
  // keep not named sub-groups of field supports
  for (size_t i=0; i!=_groups.size(); ++i)
  {
    Group& grp = _groups[i];
    if ( grp._isProfile && !grp._groups.empty() )
      groups2convert.insert( grp._groups.begin(), grp._groups.end() );
  }

  // keep named groups and their subgroups
  for (size_t i=0; i!=_groups.size(); ++i)
  {
    Group& grp = _groups[i];
    if ( !grp._name.empty() && !grp.empty() )
    {
      groups2convert.insert( &grp );
      groups2convert.insert( grp._groups.begin(), grp._groups.end() );
    }
  }
  // erase groups that are not in groups2convert and not _isProfile
  for (size_t i=0; i!=_groups.size(); ++i)
  {
    Group* grp = &_groups[i];
    if ( !grp->_isProfile && !groups2convert.count( grp ) )
    {
      grp->_cells.clear();
      grp->_groups.clear();
    }
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Creates coord array.

Definition at line 1808 of file SauvMedConvertor.cxx.

{
  DataArrayDouble* coordArray = DataArrayDouble::New();
  coordArray->alloc( _nbNodes, _spaceDim );
  double * coordPrt = coordArray->getPointer();
  for ( int i = 0, nb = _points.size(); i < nb; ++i )
    {
      Node* n = getNode( i+1 );
      if ( n->isUsed() )
        {
          const double* nCoords = nodeCoords( n );
          std::copy( nCoords, nCoords+_spaceDim, coordPrt );
          coordPrt += _spaceDim;
        }
    }
  return coordArray;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 254 of file SauvMedConvertor.hxx.

{ return _cellsByType[type].size(); }

Definition at line 253 of file SauvMedConvertor.hxx.

{ return _points.getNode( nID ); }

Here is the call graph for this function:

Here is the caller graph for this function:

const Cell* SauvUtilities::IntermediateMED::insert ( TCellType  type,
const Cell ma 
) [inline]

Definition at line 255 of file SauvMedConvertor.hxx.

{ return &( *_cellsByType[type].insert( ma ).first ); }
bool IntermediateMED::isOnAll ( const Group grp,
int &  dimRel 
) const [private]

Return true if the group is on all elements and return its relative dimension.

Definition at line 1995 of file SauvMedConvertor.cxx.

{
  int dim = getDim( grp );

  int nbElems = 0;
  CellsByDimIterator dimCells( *this, dim );
  while ( const set<Cell > * cells = dimCells.nextType() )
    nbElems += cells->size();

  const bool onAll = ( nbElems == grp->size() );

  if ( dim == 0 )
    dimRel = 0;
  else
    {
      int meshDim = 3;
      for ( ; meshDim > 0; --meshDim )
        {
          dimCells.init( meshDim );
          if ( dimCells.nextType() )
            break;
        }
      dimRel = dim - meshDim;
    }
  return onAll;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void IntermediateMED::makeFieldNewName ( std::set< std::string > &  usedNames,
SauvUtilities::DoubleField fld 
) [private]

Make a new unique name for a field.

Definition at line 2163 of file SauvMedConvertor.cxx.

{
  string base = fld->_name;
  if ( base.empty() )
    {
      base = "F_";
    }
  else
    {
      string::size_type pos = base.rfind('_');
      if ( pos != string::npos )
        base = base.substr( 0, pos+1 );
      else
        base += '_';
    }

  int i = 1;
  do
    {
      fld->_name = base + SauvUtilities::toString( i++ );
    }
  while( !usedNames.insert( fld->_name ).second );
}

Here is the call graph for this function:

Here is the caller graph for this function:

Makes fields from own data.

Definition at line 2028 of file SauvMedConvertor.cxx.

{
  if ( _nodeFields.empty() && _cellFields.empty() ) return 0;

  // set long names
  set< string > usedFieldNames;
  setFieldLongNames(usedFieldNames);

  MEDFileFields* fields = MEDFileFields::New();

  for ( size_t i = 0; i < _nodeFields.size(); ++i )
    setFields( _nodeFields[i], fields, mesh, i+1, usedFieldNames );

  for ( size_t i = 0; i < _cellFields.size(); ++i )
    setFields( _cellFields[i], fields, mesh, i+1, usedFieldNames );

  return fields;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Creates ParaMEDMEM::MEDFileUMesh from its data.

Definition at line 1131 of file SauvMedConvertor.cxx.

{
  // check if all needed piles are present
  checkDataAvailability();

  // set long names
  setGroupLongNames();

  // fix element orientation
  if ( _spaceDim == 2 )
    orientElements2D();
  else if ( _spaceDim == 3 )
    orientElements3D();

  // process groups
  decreaseHierarchicalDepthOfSubgroups();
  eraseUselessGroups();
  detectMixDimGroups();

  // assign IDs
  _points.numberNodes();
  numberElements();

  // make the med mesh

  MEDFileUMesh* mesh = MEDFileUMesh::New();

  DataArrayDouble *coords = getCoords();
  setConnectivity( mesh, coords );
  setGroups( mesh );

  coords->decrRef();

  if ( !mesh->getName() || strlen( mesh->getName() ) == 0 )
    mesh->setName( "MESH" );

  return mesh;
}

Here is the call graph for this function:

Here is the caller graph for this function:

const double* SauvUtilities::IntermediateMED::nodeCoords ( const Node n) [inline, private]

Definition at line 289 of file SauvMedConvertor.hxx.

{ return &_coords[ (n->_coordID-1) * _spaceDim ]; }

Here is the caller graph for this function:

void IntermediateMED::numberElements ( ) [private]

Assign new IDs to elements.

Definition at line 1741 of file SauvMedConvertor.cxx.

{
  set<Cell>::const_iterator elemIt, elemEnd;

  // numbering _cells of type NORM_POINT1 by node number
  {
    const set<Cell>& points = _cellsByType[ INTERP_KERNEL::NORM_POINT1 ];
    elemIt = points.begin(), elemEnd = points.end();
    for ( ; elemIt != elemEnd; ++elemIt )
      elemIt->_number = elemIt->_nodes[0]->_number;
  }

  // numbering 1D-3D _cells
  for ( int dim = 1; dim <= 3; ++dim )
    {
      // check if re-numeration is needed (to try to keep elem oreder as in sauve file )
      bool ok = true, renumEntity = false;
      CellsByDimIterator cellsIt( *this, dim );
      int prevNbElems = 0;
      while ( const set<Cell> * typeCells = cellsIt.nextType() )
        {
          TID minNumber = std::numeric_limits<TID>::max(), maxNumber = 0;
          for ( elemIt = typeCells->begin(), elemEnd = typeCells->end(); elemIt!=elemEnd; ++elemIt)
            {
              if ( elemIt->_number < minNumber ) minNumber = elemIt->_number;
              if ( elemIt->_number > maxNumber ) maxNumber = elemIt->_number;
            }
          TID typeSize = typeCells->size();
          if ( typeSize != maxNumber - minNumber + 1 )
            ok = false;
          if ( prevNbElems != 0 ) {
            if ( minNumber == 1 )
              renumEntity = true;
            else if ( prevNbElems+1 != (int)minNumber )
              ok = false;
          }
          prevNbElems += typeSize;
        }

      if ( ok && renumEntity ) // each geom type was numerated separately
        {
          cellsIt.init( dim );
          prevNbElems = cellsIt.nextType()->size(); // no need to renumber the first type
          while ( const set<Cell> * typeCells = cellsIt.nextType() )
            {
              for ( elemIt = typeCells->begin(), elemEnd = typeCells->end(); elemIt!=elemEnd; ++elemIt)
                elemIt->_number += prevNbElems;
              prevNbElems += typeCells->size();
            }
        }
      if ( !ok )
        {
          int cellID=1;
          cellsIt.init( dim );
          while ( const set<Cell> * typeCells = cellsIt.nextType() )
            for ( elemIt = typeCells->begin(), elemEnd = typeCells->end(); elemIt!=elemEnd; ++elemIt)
              elemIt->_number = cellID++;
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Fix connectivity of elements in 2D space.

Definition at line 1376 of file SauvMedConvertor.cxx.

{
  set<Cell>::const_iterator elemIt, elemEnd;
  vector< pair<int,int> > swapVec;

  // ------------------------------------
  // fix connectivity of quadratic edges
  // ------------------------------------
  set<Cell>& quadEdges = _cellsByType[ INTERP_KERNEL::NORM_SEG3 ];
  if ( !quadEdges.empty() )
    {
      elemIt = quadEdges.begin(), elemEnd = quadEdges.end();
      for ( ; elemIt != elemEnd; ++elemIt )
        ConvertQuadratic( INTERP_KERNEL::NORM_SEG3, *elemIt );
    }

  CellsByDimIterator faceIt( *this, 2 );
  while ( const set<Cell > * faces = faceIt.nextType() )
    {
      TCellType cellType = faceIt.type();
      bool isQuadratic = getGibi2MedQuadraticInterlace( cellType );

      getReverseVector( cellType, swapVec );

      // ------------------------------------
      // fix connectivity of quadratic faces
      // ------------------------------------
      if ( isQuadratic )
        for ( elemIt = faces->begin(), elemEnd = faces->end(); elemIt != elemEnd; elemIt++ )
          ConvertQuadratic( cellType, *elemIt );

      // --------------------------
      // orient faces clockwise
      // --------------------------
      int iQuad = isQuadratic ? 2 : 1;
      for ( elemIt = faces->begin(), elemEnd = faces->end(); elemIt != elemEnd; elemIt++ )
        {
          // look for index of the most left node
          int iLeft = 0, iNode, nbNodes = elemIt->_nodes.size() / iQuad;
          double x, minX = nodeCoords( elemIt->_nodes[0] )[0];
          for ( iNode = 1; iNode < nbNodes; ++iNode )
            if (( x = nodeCoords( elemIt->_nodes[ iNode ])[ 0 ]) < minX )
              minX = x, iLeft = iNode;

          // indeces of the nodes neighboring the most left one
          int iPrev = ( iLeft - 1 < 0 ) ? nbNodes - 1 : iLeft - 1;
          int iNext = ( iLeft + 1 == nbNodes ) ? 0 : iLeft + 1;
          // find components of prev-left and left-next vectors
          double xP = nodeCoords( elemIt->_nodes[ iPrev ])[ 0 ];
          double yP = nodeCoords( elemIt->_nodes[ iPrev ])[ 1 ];
          double xN = nodeCoords( elemIt->_nodes[ iNext ])[ 0 ];
          double yN = nodeCoords( elemIt->_nodes[ iNext ])[ 1 ];
          double xL = nodeCoords( elemIt->_nodes[ iLeft ])[ 0 ];
          double yL = nodeCoords( elemIt->_nodes[ iLeft ])[ 1 ];
          double xPL = xL - xP, yPL = yL - yP; // components of prev-left vector
          double xLN = xN - xL, yLN = yN - yL; // components of left-next vector
          // normalise y of the vectors
          double modPL = sqrt ( xPL * xPL + yPL * yPL );
          double modLN = sqrt ( xLN * xLN + yLN * yLN );
          if ( modLN > std::numeric_limits<double>::min() &&
               modPL > std::numeric_limits<double>::min() )
            {
              yPL /= modPL;
              yLN /= modLN;
              // summary direction of neighboring links must be positive
              bool clockwise = ( yPL + yLN > 0 );
              if ( !clockwise )
                reverse( *elemIt, swapVec );
            }
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Fix connectivity of elements in 3D space.

Definition at line 1455 of file SauvMedConvertor.cxx.

{
  // set _reverse flags of faces
  orientFaces3D();

  // -----------------
  // fix connectivity
  // -----------------

  set<Cell>::const_iterator elemIt, elemEnd;
  vector< pair<int,int> > swapVec;

  for ( int dim = 1; dim <= 3; ++dim )
  {
    CellsByDimIterator cellsIt( *this, dim );
    while ( const set<Cell > * elems = cellsIt.nextType() )
    {
      TCellType cellType = cellsIt.type();
      bool isQuadratic = getGibi2MedQuadraticInterlace( cellType );
      getReverseVector( cellType, swapVec );

      elemIt = elems->begin(), elemEnd = elems->end();
      for ( ; elemIt != elemEnd; elemIt++ )
      {
        // GIBI connectivity -> MED one
        if( isQuadratic )
          ConvertQuadratic( cellType, *elemIt );

        // reverse faces
        if ( elemIt->_reverse )
          reverse ( *elemIt, swapVec );
      }
    }
  }

  orientVolumes();
}

Here is the call graph for this function:

Here is the caller graph for this function:

void IntermediateMED::orientFaces3D ( ) [private]

Orient equally (by setting _reverse flag) all connected faces in 3D space.

Definition at line 1499 of file SauvMedConvertor.cxx.

{
  // fill map of links and their faces
  set<const Cell*> faces;
  map<const Cell*, Group*> fgm;
  map<Link, list<const Cell*> > linkFacesMap;
  map<Link, list<const Cell*> >::iterator lfIt, lfIt2;

  for (size_t i=0; i!=_groups.size(); ++i)
    {
      Group& grp = _groups[i];
      if ( !grp._cells.empty() && getDimension( grp._cellType ) == 2 )
        for ( size_t j = 0; j < grp._cells.size(); ++j )
          if ( faces.insert( grp._cells[j] ).second )
            {
              for ( size_t k = 0; k < grp._cells[j]->_nodes.size(); ++k )
                linkFacesMap[ grp._cells[j]->link( k ) ].push_back( grp._cells[j] );
              fgm.insert( make_pair( grp._cells[j], &grp ));
            }
    }
  // dump linkFacesMap
  //     for ( lfIt = linkFacesMap.begin(); lfIt!=linkFacesMap.end(); lfIt++) {
  //       cout<< "LINK: " << lfIt->first.first << "-" << lfIt->first.second << endl;
  //       list<const Cell*> & fList = lfIt->second;
  //       list<const Cell*>::iterator fIt = fList.begin();
  //       for ( ; fIt != fList.end(); fIt++ )
  //         cout << "\t" << **fIt << fgm[*fIt]->nom << endl;
  //     }

  // Each oriented link must appear in one face only, else a face is reversed.

  queue<const Cell*> faceQueue; /* the queue contains well oriented faces
                                     whose neighbors orientation is to be checked */
  bool manifold = true;
  while ( !linkFacesMap.empty() )
    {
      if ( faceQueue.empty() )
        {
          assert( !linkFacesMap.begin()->second.empty() );
          faceQueue.push( linkFacesMap.begin()->second.front() );
        }
      while ( !faceQueue.empty() )
        {
          const Cell* face = faceQueue.front();
          faceQueue.pop();

          // loop on links of <face>
          for ( int i = 0; i < (int)face->_nodes.size(); ++i )
            {
              Link link = face->link( i );
              // find the neighbor faces
              lfIt = linkFacesMap.find( link );
              int nbFaceByLink = 0;
              list< const Cell* > ml;
              if ( lfIt != linkFacesMap.end() )
                {
                  list<const Cell*> & fList = lfIt->second;
                  list<const Cell*>::iterator fIt = fList.begin();
                  assert( fIt != fList.end() );
                  for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ )
                    {
                      ml.push_back( *fIt );
                      if ( *fIt != face ) // wrongly oriented neighbor face
                        {
                          const Cell* badFace = *fIt;
                          // reverse and remove badFace from linkFacesMap
                          for ( int j = 0; j < (int)badFace->_nodes.size(); ++j )
                            {
                              Link badlink = badFace->link( j );
                              if ( badlink == link ) continue;
                              lfIt2 = linkFacesMap.find( badlink );
                              if ( lfIt2 != linkFacesMap.end() )
                                {
                                  list<const Cell*> & ff = lfIt2->second;
                                  ff.erase( find( ff.begin(), ff.end(), badFace ));
                                  if ( ff.empty() )
                                    linkFacesMap.erase( lfIt2 );
                                }
                            }
                          badFace->_reverse = true; // reverse
                          //INFOS_MED( "REVERSE " << *badFace );
                          faceQueue.push( badFace );
                        }
                    }
                  linkFacesMap.erase( lfIt );
                }
              // add good neighbors to the queue
              Link revLink( link.second, link.first );
              lfIt = linkFacesMap.find( revLink );
              if ( lfIt != linkFacesMap.end() )
                {
                  list<const Cell*> & fList = lfIt->second;
                  list<const Cell*>::iterator fIt = fList.begin();
                  for ( ; fIt != fList.end(); fIt++, nbFaceByLink++ )
                    {
                      ml.push_back( *fIt );
                      if ( *fIt != face )
                        faceQueue.push( *fIt );
                    }
                  linkFacesMap.erase( lfIt );
                }
              if ( nbFaceByLink > 2 )
                {
                  if ( manifold )
                    {
                      list<const Cell*>::iterator ii = ml.begin();
                      cout << nbFaceByLink << " faces by 1 link:";
                      for( ; ii!= ml.end(); ii++ )
                        cout << "in sub-mesh " << fgm[ *ii ]->_name << endl << **ii;
                    }
                  manifold = false;
                }
            } // loop on links of the being checked face
        } // loop on the face queue
    } // while ( !linkFacesMap.empty() )

  if ( !manifold )
    cout << " -> Non manifold mesh, faces orientation may be incorrect" << endl;
}

Here is the call graph for this function:

Here is the caller graph for this function:

void IntermediateMED::orientVolumes ( ) [private]

Orient volumes according to MED conventions: normal of a bottom (first) face should be outside.

Definition at line 1626 of file SauvMedConvertor.cxx.

{
  set<Cell>::const_iterator elemIt, elemEnd;
  vector< pair<int,int> > swapVec;

  CellsByDimIterator cellsIt( *this, 3 );
  while ( const set<Cell > * elems = cellsIt.nextType() )
    {
      TCellType cellType = cellsIt.type();
      elemIt = elems->begin(), elemEnd = elems->end();
      int nbBottomNodes = 0;
      switch ( cellType )
        {
        case NORM_TETRA4:
        case NORM_TETRA10:
        case NORM_PENTA6:
        case NORM_PENTA15:
          nbBottomNodes = 3; break;
        case NORM_PYRA5:
        case NORM_PYRA13:
        case NORM_HEXA8:
        case NORM_HEXA20:
          nbBottomNodes = 4; break;
        default: continue;
        }
      getReverseVector( cellType, swapVec );

      for ( ; elemIt != elemEnd; elemIt++ )
        {
          // find a normal to the bottom face
          const double* n[4];
          n[0] = nodeCoords( elemIt->_nodes[0]); // 3 bottom nodes
          n[1] = nodeCoords( elemIt->_nodes[1]);
          n[2] = nodeCoords( elemIt->_nodes[2]);
          n[3] = nodeCoords( elemIt->_nodes[nbBottomNodes]); // a top node
          double vec01[3]; // vector n[0]-n[1]
          vec01[0] = n[1][0] - n[0][0];
          vec01[1] = n[1][1] - n[0][1];
          vec01[2] = n[1][2] - n[0][2];
          double vec02 [3]; // vector n[0]-n[2]
          vec02[0] = n[2][0] - n[0][0];
          vec02[1] = n[2][1] - n[0][1];
          vec02[2] = n[2][2] - n[0][2];
          double normal [3]; // vec01 ^ vec02
          normal[0] = vec01[1] * vec02[2] - vec01[2] * vec02[1];
          normal[1] = vec01[2] * vec02[0] - vec01[0] * vec02[2];
          normal[2] = vec01[0] * vec02[1] - vec01[1] * vec02[0];
          // check if the 102 angle is convex
          if ( nbBottomNodes > 3 )
            {
              const double* n3 = nodeCoords( elemIt->_nodes[nbBottomNodes-1] );// last bottom node
              double vec03 [3];  // vector n[0]-n3
              vec03[0] = n3[0] - n[0][0];
              vec03[1] = n3[1] - n[0][1];
              vec03[2] = n3[2] - n[0][2];
              if ( fabs( normal[0]+normal[1]+normal[2] ) <= numeric_limits<double>::max() ) // vec01 || vec02
                {
                  normal[0] = vec01[1] * vec03[2] - vec01[2] * vec03[1]; // vec01 ^ vec03
                  normal[1] = vec01[2] * vec03[0] - vec01[0] * vec03[2];
                  normal[2] = vec01[0] * vec03[1] - vec01[1] * vec03[0];
                }
              else
                {
                  double vec [3]; // normal ^ vec01
                  vec[0] = normal[1] * vec01[2] - normal[2] * vec01[1];
                  vec[1] = normal[2] * vec01[0] - normal[0] * vec01[2];
                  vec[2] = normal[0] * vec01[1] - normal[1] * vec01[0];
                  double dot2 = vec[0]*vec03[0] + vec[1]*vec03[1] + vec[2]*vec03[2]; // vec*vec03
                  if ( dot2 < 0 ) // concave -> reverse normal
                    {
                      normal[0] *= -1;
                      normal[1] *= -1;
                      normal[2] *= -1;
                    }
                }
            }
          // direction from top to bottom
          double tbDir[3];
          tbDir[0] = n[0][0] - n[3][0];
          tbDir[1] = n[0][1] - n[3][1];
          tbDir[2] = n[0][2] - n[3][2];

          // compare 2 directions: normal and top-bottom
          double dot = normal[0]*tbDir[0] + normal[1]*tbDir[1] + normal[2]*tbDir[2];
          if ( dot < 0. ) // need reverse
            reverse( *elemIt, swapVec );

        } // loop on volumes of one geometry
    } // loop on 3D geometry types

}

Here is the call graph for this function:

Here is the caller graph for this function:

Sets connectivity of elements to the mesh.

Parameters:
mesh- mesh to fill in
coords- coordinates that must be shared by all meshes of different dim

Definition at line 1834 of file SauvMedConvertor.cxx.

{
  int meshDim = 0;

  mesh->setCoords( coords );

  set<Cell>::const_iterator elemIt, elemEnd;
  for ( int dim = 3; dim > 0; --dim )
  {
    CellsByDimIterator dimCells( *this, dim );

    int nbOfCells = 0;
    while ( const std::set<Cell > * cells = dimCells.nextType() )
      nbOfCells += cells->size();
    if ( nbOfCells == 0 )
      continue;

    if ( !meshDim ) meshDim = dim;

    MEDCouplingUMesh* dimMesh = MEDCouplingUMesh::New();
    dimMesh->setCoords( coords );
    dimMesh->setMeshDimension( dim );
    dimMesh->allocateCells( nbOfCells );

    int prevNbCells = 0;
    dimCells.init( dim );
    while ( const std::set<Cell > * cells = dimCells.nextType() )
      {
        // fill connectivity array to take into account order of elements in the sauv file
        const int nbCellNodes = cells->begin()->_nodes.size();
        vector< TID > connectivity( cells->size() * nbCellNodes );
        int * nodalConnOfCell;
        for ( elemIt = cells->begin(), elemEnd = cells->end(); elemIt != elemEnd; ++elemIt )
          {
            const Cell& cell = *elemIt;
            const int index = cell._number - 1 - prevNbCells;
            nodalConnOfCell = &connectivity[ index * nbCellNodes ];
            if ( cell._reverse )
              for ( int i = nbCellNodes-1; i >= 0; --i )
                *nodalConnOfCell++ = cell._nodes[i]->_number - 1;
            else
              for ( int i = 0; i < nbCellNodes; ++i )
                *nodalConnOfCell++ = cell._nodes[i]->_number - 1;
          }
        prevNbCells += cells->size();

        // fill dimMesh
        TCellType cellType = dimCells.type();
        nodalConnOfCell = &connectivity[0];
        for ( size_t i = 0; i < cells->size(); ++i, nodalConnOfCell += nbCellNodes )
          dimMesh->insertNextCell( cellType, nbCellNodes, nodalConnOfCell );
      }
    dimMesh->finishInsertingCells();
    mesh->setMeshAtLevel( dim - meshDim, dimMesh );
    dimMesh->decrRef();
  }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void IntermediateMED::setFieldLongNames ( std::set< std::string > &  usedNames) [private]

Set long names to fields.

Definition at line 1208 of file SauvMedConvertor.cxx.

{
  list<nameGIBItoMED>::iterator itGIBItoMED = _listGIBItoMED_cham.begin();
  for (; itGIBItoMED != _listGIBItoMED_cham.end(); itGIBItoMED++)
    {
      if (itGIBItoMED->gibi_pile == PILE_FIELD)
        {
          _cellFields[itGIBItoMED->gibi_id - 1]->_name = _mapStrings[itGIBItoMED->med_id];
        }
      else if (itGIBItoMED->gibi_pile == PILE_NODES_FIELD)
        {
          _nodeFields[itGIBItoMED->gibi_id - 1]->_name = _mapStrings[itGIBItoMED->med_id];
        }
    } // iterate on _listGIBItoMED_cham

  for (itGIBItoMED =_listGIBItoMED_comp.begin(); itGIBItoMED != _listGIBItoMED_comp.end(); itGIBItoMED++)
    {
      string medName  = _mapStrings[itGIBItoMED->med_id];
      string gibiName = _mapStrings[itGIBItoMED->gibi_id];

      bool name_found = false;
      for ( int isNodal = 0; isNodal < 2 && !name_found; ++isNodal )
        {
          vector<DoubleField* > & fields = isNodal ? _nodeFields : _cellFields;
          for ( size_t ifi = 0; ifi < fields.size() && !name_found; ifi++)
            {
              if (medName.find( fields[ifi]->_name + "." ) == 0 )
                {
                  vector<DoubleField::_Sub_data>& aSubDs = fields[ifi]->_sub;
                  int nbSub = aSubDs.size();
                  for (int isu = 0; isu < nbSub; isu++)
                    for (int ico = 0; ico < aSubDs[isu].nbComponents(); ico++)
                      {
                        if (aSubDs[isu].compName(ico) == gibiName)
                          {
                            string medNameCompo = medName.substr( fields[ifi]->_name.size() + 1 );
                            fields[ifi]->_sub[isu].compName(ico) = medNameCompo;
                          }
                      }
                }
            }
        }
    } // iterate on _listGIBItoMED_comp

  for ( size_t i = 0; i < _nodeFields.size() ; i++)
    usedNames.insert( _nodeFields[i]->_name );
  for ( size_t i = 0; i < _cellFields.size() ; i++)
    usedNames.insert( _cellFields[i]->_name );
}

Here is the caller graph for this function:

void IntermediateMED::setFields ( SauvUtilities::DoubleField fld,
ParaMEDMEM::MEDFileFields medFields,
ParaMEDMEM::MEDFileUMesh mesh,
const TID  castemID,
std::set< std::string > &  usedNames 
) [private]

Make med fields from a SauvUtilities::DoubleField.

Definition at line 2053 of file SauvMedConvertor.cxx.

{
  if ( !fld || !fld->isMedCompatible() ) return;

  // if ( !fld->hasCommonSupport() ):
  //     each sub makes MEDFileFieldMultiTS
  // else:
  //     unite several subs into a MEDCouplingFieldDouble

  const bool uniteSubs = fld->hasCommonSupport();
  if ( !uniteSubs )
    cout << "Castem field #" << castemID << " " << fld->_name
         << " is incompatible with MED format, so we split it into several fields" << endl;

  for ( size_t iSub = 0; iSub < fld->_sub.size(); )
    {
      // set field name
      if ( !uniteSubs || fld->_name.empty() )
        makeFieldNewName( usedFieldNames, fld );

      // allocate values
      DataArrayDouble * values = DataArrayDouble::New();
      values->alloc( fld->getNbTuples(iSub), fld->_sub[iSub].nbComponents() );

      // set values
      double * valPtr = values->getPointer();
      if ( uniteSubs )
        {
          int nbElems = fld->_group->size();
          for ( int elemShift = 0; elemShift < nbElems; )
            elemShift += fld->setValues( valPtr, iSub++, elemShift );
          setTS( fld, values, medFields, mesh );
        }
      else
        {
          fld->setValues( valPtr, iSub++ );
          setTS( fld, values, medFields, mesh, iSub );
        }
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

Set long names to groups.

Definition at line 1176 of file SauvMedConvertor.cxx.

{
  // IMP 0020434: mapping GIBI names to MED names
  // set med names to objects (mesh, fields, support, group or other)

  set<int> treatedGroups;

  list<nameGIBItoMED>::iterator itGIBItoMED = _listGIBItoMED_mail.begin();
  for (; itGIBItoMED != _listGIBItoMED_mail.end(); itGIBItoMED++)
    {
      if ( (int)_groups.size() < itGIBItoMED->gibi_id ) continue;

      SauvUtilities::Group & grp = _groups[itGIBItoMED->gibi_id - 1];

      // if there are several names for grp then the 1st name is the name
      // of grp and the rest ones are names of groups referring grp (issue 0021311)
      const bool isRefName = !treatedGroups.insert( itGIBItoMED->gibi_id ).second;
      if ( !isRefName )
        grp._name = _mapStrings[ itGIBItoMED->med_id ];
      else
        for ( unsigned i = 0; i < grp._refNames.size(); ++i )
          if ( grp._refNames[i].empty() )
            grp._refNames[i] = _mapStrings[ (*itGIBItoMED).med_id ];
    }
}

Here is the caller graph for this function:

Fill in the mesh with groups.

Parameters:
mesh- mesh to fill in

Definition at line 1900 of file SauvMedConvertor.cxx.

{
  bool isMeshNameSet = false;
  const int meshDim = mesh->getMeshDimension();
  for ( int dim = 0; dim <= meshDim; ++dim )
    {
      const int meshDimRelToMaxExt = ( dim == 0 ? 1 : dim - meshDim );

      vector<const DataArrayInt *> medGroups;
      vector<MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > refGroups;
      for ( size_t i = 0; i < _groups.size(); ++i )
        {
          Group& grp = _groups[i];
          if ( (int)getDim( &grp ) != dim )
            continue;
          // convert only named groups or field supports
          if ( grp.empty() || (grp._name.empty() && !grp._isProfile ))
            continue;
          //if ( grp._medGroup ) continue; // already converted

          // sort cells by ID and remember their initial order in the group
          TCellToOrderMap cell2order;
          unsigned orderInGroup = 0;
          vector< Group* > groupVec;
          if ( grp._groups.empty() ) groupVec.push_back( & grp );
          else                       groupVec = grp._groups;
          for ( size_t iG = 0; iG < groupVec.size(); ++iG )
            {
              Group* aG = groupVec[ iG ];
              for ( size_t iC = 0; iC < aG->_cells.size(); ++iC )
                cell2order.insert( cell2order.end(), make_pair( aG->_cells[iC], orderInGroup++ ));
            }
          bool isSelfIntersect = ( orderInGroup != cell2order.size() );
          if ( isSelfIntersect ) // self intersecting group
            {
              ostringstream msg;
              msg << "Self intersecting sub-mesh: id = " << i+1
                  << ", name = |" << grp._name << "|" << endl
                  << " nb unique elements = " << cell2order.size() << endl
                  << " total nb elements  = " << orderInGroup;
              if ( grp._isProfile )
                {
                  THROW_IK_EXCEPTION( msg.str() );
                }
              else
                {
                  cout << msg << endl;
                }
            }
          // create a med group
          grp._medGroup = DataArrayInt::New();
          grp._medGroup->setName( grp._name.c_str() );
          grp._medGroup->alloc( orderInGroup, /*nbOfCompo=*/1 );
          int * idsPrt = grp._medGroup->getPointer();
          TCellToOrderMap::iterator cell2orderIt, cell2orderEnd = cell2order.end();
          for ( cell2orderIt = cell2order.begin(); cell2orderIt != cell2orderEnd; ++cell2orderIt )
            *idsPrt++ = (*cell2orderIt).first->_number - 1;

          // try to set the mesh name
          if ( !isMeshNameSet &&
               dim == meshDim &&
               !grp._name.empty() &&
               grp.size() == mesh->getSizeAtLevel( meshDimRelToMaxExt ))
            {
              mesh->setName( grp._name.c_str() );
              isMeshNameSet = true;
            }
          else if ( !grp._name.empty() )
            {
              medGroups.push_back( grp._medGroup );
            }
          // set relocation table
          setRelocationTable( &grp, cell2order );

          // Issue 0021311. Use case: a gibi group has references (recorded in pile 1)
          // and several names (pile 27) refer (pile 10) to this group.
          // We create a copy of this group per each named reference
          for ( unsigned iRef = 0 ; iRef < grp._refNames.size(); ++iRef )
            if ( !grp._refNames[ iRef ].empty() )
              {
                refGroups.push_back( grp._medGroup->deepCpy() );
                refGroups.back()->setName( grp._refNames[ iRef ].c_str() );
                medGroups.push_back( refGroups.back() );
              }
        }
      mesh->setGroupsAtLevel( meshDimRelToMaxExt, medGroups );
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:

void IntermediateMED::setTS ( SauvUtilities::DoubleField fld,
ParaMEDMEM::DataArrayDouble values,
ParaMEDMEM::MEDFileFields medFields,
ParaMEDMEM::MEDFileUMesh mesh,
const int  iSub = 0 
) [private]

Store value array of a field into med fields.

Definition at line 2104 of file SauvMedConvertor.cxx.

{
  // analyze a field support
  const Group* support = fld->getSupport();
  int dimRel;
  const bool onAll = isOnAll( support, dimRel );
  if ( !onAll && support->_name.empty() )
    {
      const_cast<Group*>(support)->_name += "PFL_" + fld->_name;
      support->_medGroup->setName( support->_name.c_str() );
    }

  // make a time-stamp
  MEDCouplingFieldDouble * timeStamp = MEDCouplingFieldDouble::New( fld->getMedType(),
                                                                    fld->getMedTimeDisc() );
  timeStamp->setName( fld->_name.c_str() );
  timeStamp->setDescription( fld->_description.c_str() );
  MEDCouplingAutoRefCountObjectPtr< MEDCouplingUMesh > dimMesh = mesh->getMeshAtLevel( dimRel );
  timeStamp->setMesh( dimMesh );
  for ( size_t i = 0; i < (size_t)fld->_sub[iSub].nbComponents(); ++i )
    values->setInfoOnComponent( i, fld->_sub[iSub]._comp_names[ i ].c_str() );
  timeStamp->setArray( values );
  values->decrRef();

  // get a field to add the time-stamp
  bool isNewMedField = false;
  if ( !fld->_curMedField || fld->_name != fld->_curMedField->getName() )
    {
      fld->_curMedField = MEDFileFieldMultiTS::New();
      isNewMedField = true;
    }

  // set an order
  timeStamp->setOrder( fld->_curMedField->getNumberOfTS() );

  // add the time-stamp
  if ( onAll )
    fld->_curMedField->appendFieldNoProfileSBT( timeStamp );
  else
    fld->_curMedField->appendFieldProfile( timeStamp, mesh, dimRel, support->_medGroup );
  timeStamp->decrRef();

  if ( isNewMedField ) // timeStamp must be added before this
    {
      medFields->pushField( fld->_curMedField );
      fld->_curMedField->decrRef();
    }
}

Here is the call graph for this function:

Here is the caller graph for this function:


Friends And Related Function Documentation

friend class CellsByDimIterator [friend]

Definition at line 301 of file SauvMedConvertor.hxx.


Member Data Documentation

Definition at line 242 of file SauvMedConvertor.hxx.

Definition at line 300 of file SauvMedConvertor.hxx.

Definition at line 239 of file SauvMedConvertor.hxx.

Definition at line 240 of file SauvMedConvertor.hxx.

Definition at line 246 of file SauvMedConvertor.hxx.

Definition at line 247 of file SauvMedConvertor.hxx.

Definition at line 245 of file SauvMedConvertor.hxx.

Definition at line 248 of file SauvMedConvertor.hxx.

Definition at line 237 of file SauvMedConvertor.hxx.

Definition at line 241 of file SauvMedConvertor.hxx.

Definition at line 238 of file SauvMedConvertor.hxx.

Definition at line 236 of file SauvMedConvertor.hxx.


The documentation for this struct was generated from the following files: