mirror of
https://git.salome-platform.org/gitpub/modules/smesh.git
synced 2025-04-13 13:47:26 +05:00
435 lines
15 KiB
C++
435 lines
15 KiB
C++
// Copyright (C) 2007-2020 CEA/DEN, EDF R&D, OPEN CASCADE
|
|
//
|
|
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
|
|
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2.1 of the License, or (at your option) any later version.
|
|
//
|
|
// This library 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
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
//
|
|
// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
|
|
//
|
|
|
|
// File : DriverMED_W_Field.cxx
|
|
// Created : Thu Feb 27 17:45:00 2014
|
|
// Author : eap
|
|
|
|
#include "DriverMED_W_Field.h"
|
|
|
|
#include "DriverMED.hxx"
|
|
#include "DriverMED_W_SMESHDS_Mesh.h"
|
|
#include "MED_Factory.hxx"
|
|
#include "MED_Utilities.hxx"
|
|
#include "MED_Wrapper.hxx"
|
|
#include "SMDS_IteratorOnIterators.hxx"
|
|
#include "SMDS_MeshElement.hxx"
|
|
#include "SMDS_SetIterator.hxx"
|
|
#include "SMESHDS_Mesh.hxx"
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Constructor
|
|
*/
|
|
//================================================================================
|
|
|
|
DriverMED_W_Field::DriverMED_W_Field():
|
|
//_medFileID( -1 ),
|
|
_elemType( SMDSAbs_All ),
|
|
_dt( -1 ),
|
|
_it( -1 )
|
|
{
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Sets basic data
|
|
* \param [in] mesh - supporting mesh
|
|
* \param [in] fieldName - name of a field
|
|
* \param [in] type - type of supporting elements
|
|
* \param [in] nbComps - number of components
|
|
* \param [in] isIntData - type of data: double or integer
|
|
*/
|
|
//================================================================================
|
|
|
|
bool DriverMED_W_Field::Set(SMESHDS_Mesh * mesh,
|
|
const std::string & fieldName,
|
|
SMDSAbs_ElementType type,
|
|
const int nbComps,
|
|
const bool isIntData)
|
|
{
|
|
_fieldName = fieldName;
|
|
_compNames.resize( nbComps, "" );
|
|
|
|
if ( type == SMDSAbs_All )
|
|
{
|
|
if ( mesh->NbVolumes() > 0 )
|
|
type = SMDSAbs_Volume;
|
|
else if ( mesh->NbFaces() > 0 )
|
|
type = SMDSAbs_Face;
|
|
else if ( mesh->NbEdges() > 0 )
|
|
type = SMDSAbs_Edge;
|
|
else
|
|
type = SMDSAbs_Node;
|
|
}
|
|
if ( myMesh != mesh )
|
|
{
|
|
_nbElemsByGeom.clear();
|
|
for ( int iG = 0; iG < SMDSEntity_Last; ++iG )
|
|
_elemsByGeom[iG].clear();
|
|
SetMesh( mesh );
|
|
}
|
|
|
|
// find out "MED order" of elements - sort elements by geom type
|
|
int nbElems;
|
|
if ( _nbElemsByGeom.empty() || _elemType != type )
|
|
{
|
|
_elemType = type;
|
|
_nbElemsByGeom.resize( 1, std::make_pair( SMDSEntity_Last, 0 ));
|
|
|
|
// count nb of elems of each geometry
|
|
for ( int iG = 0; iG < SMDSEntity_Last; ++iG )
|
|
{
|
|
SMDSAbs_EntityType geom = (SMDSAbs_EntityType) iG;
|
|
SMDSAbs_ElementType t = SMDS_MeshCell::ElemType( geom );
|
|
if ( t != _elemType ) continue;
|
|
|
|
nbElems = mesh->GetMeshInfo().NbElements( geom );
|
|
if ( nbElems < 1 ) continue;
|
|
|
|
_nbElemsByGeom.push_back( std::make_pair( geom, nbElems + _nbElemsByGeom.back().second ));
|
|
}
|
|
// add nodes of missing 0D elements on VERTEXes
|
|
if ( _addODOnVertices && _elemType == SMDSAbs_0DElement )
|
|
{
|
|
std::vector< const SMDS_MeshElement* >& nodes = _elemsByGeom[SMDSEntity_Node];
|
|
if ( nodes.empty() )
|
|
DriverMED_W_SMESHDS_Mesh::getNodesOfMissing0DOnVert( myMesh, nodes );
|
|
if ( !nodes.empty() )
|
|
{
|
|
if ( _nbElemsByGeom.size() == 1 )
|
|
_nbElemsByGeom.push_back( std::make_pair( SMDSEntity_0D, 0));
|
|
_nbElemsByGeom.push_back( std::make_pair( SMDSEntity_Node,
|
|
nodes.size() + _nbElemsByGeom.back().second ));
|
|
}
|
|
}
|
|
|
|
// sort elements by their geometry
|
|
int iGeoType, nbGeomTypes = _nbElemsByGeom.size() - 1;
|
|
if ( nbGeomTypes > 1 )
|
|
{
|
|
for ( size_t iG = 1; iG < _nbElemsByGeom.size(); ++iG )
|
|
{
|
|
iGeoType = _nbElemsByGeom[iG].first;
|
|
nbElems = _nbElemsByGeom[iG].second - _nbElemsByGeom[iG-1].second;
|
|
_elemsByGeom[ iGeoType ].reserve( nbElems );
|
|
}
|
|
iGeoType = _nbElemsByGeom[1].first; // for missing 0D
|
|
if ( _elemsByGeom[ iGeoType ].empty() )
|
|
{
|
|
nbElems = mesh->GetMeshInfo().NbElements( _elemType );
|
|
SMDS_ElemIteratorPtr eIt = mesh->elementsIterator( _elemType );
|
|
for ( int iE = 0; iE < nbElems && eIt->more(); ++iE )
|
|
{
|
|
const SMDS_MeshElement* e = eIt->next();
|
|
_elemsByGeom[ e->GetEntityType() ].push_back( e );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
_intValues.clear();
|
|
_dblValues.clear();
|
|
|
|
// allocate memory for values
|
|
nbElems = _nbElemsByGeom.empty() ? 0 : _nbElemsByGeom.back().second;
|
|
if ( isIntData )
|
|
_intValues.reserve( nbElems * nbComps );
|
|
else
|
|
_dblValues.reserve( nbElems * nbComps );
|
|
|
|
return nbElems && nbComps;
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Set a name of a component countered from zero
|
|
*/
|
|
//================================================================================
|
|
|
|
void DriverMED_W_Field::SetCompName(const int iComp, const char* name)
|
|
{
|
|
if ( (int)_compNames.size() <= iComp )
|
|
_compNames.resize( iComp + 1 );
|
|
_compNames[ iComp ] = name;
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Sets numdt and numit field features. Call this fun before AddValue()!
|
|
*/
|
|
//================================================================================
|
|
|
|
void DriverMED_W_Field::SetDtIt(const int dt, const int it)
|
|
{
|
|
_dt = dt;
|
|
_it = it;
|
|
_intValues.clear();
|
|
_dblValues.clear();
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Adds a float field value
|
|
*/
|
|
//================================================================================
|
|
|
|
void DriverMED_W_Field::AddValue( double val )
|
|
{
|
|
_dblValues.push_back( val );
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* \brief Adds an integer field value
|
|
*/
|
|
//================================================================================
|
|
|
|
void DriverMED_W_Field::AddValue( int val )
|
|
{
|
|
_intValues.push_back( val );
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* Returns elements in the order they are written in MED file
|
|
*/
|
|
//================================================================================
|
|
|
|
SMDS_ElemIteratorPtr DriverMED_W_Field::GetOrderedElems()
|
|
{
|
|
if ( _nbElemsByGeom.size() < 2 )
|
|
return SMDS_ElemIteratorPtr();
|
|
|
|
if ( _nbElemsByGeom.size() == 2 )
|
|
// sole geom type of elements
|
|
return myMesh->elementsIterator( _elemType );
|
|
|
|
std::vector< SMDS_ElemIteratorPtr > iterVec( _nbElemsByGeom.size()-1 );
|
|
for ( size_t iG = 1; iG < _nbElemsByGeom.size(); ++iG )
|
|
{
|
|
int iGeoType = _nbElemsByGeom[ iG ].first;
|
|
iterVec[ iG-1 ] = SMDS_ElemIteratorPtr
|
|
( new SMDS_ElementVectorIterator( _elemsByGeom[ iGeoType ].begin(),
|
|
_elemsByGeom[ iGeoType ].end() ));
|
|
}
|
|
typedef SMDS_IteratorOnIterators
|
|
< const SMDS_MeshElement *, std::vector< SMDS_ElemIteratorPtr > > TItIterator;
|
|
return SMDS_ElemIteratorPtr( new TItIterator( iterVec ));
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* Writes a field to the file
|
|
*/
|
|
//================================================================================
|
|
|
|
Driver_Mesh::Status DriverMED_W_Field::Perform()
|
|
{
|
|
if ( myFile.empty() )
|
|
return addMessage("File name not set", /*isFatal=*/true ); // 'fatal' means 'bug'
|
|
if ( myMeshId < 0 && myMeshName.empty() )
|
|
return addMessage("Mesh in file not specified", /*isFatal=*/true );
|
|
if ( _nbElemsByGeom.size() < 2 )
|
|
return addMessage("No values to write", /*isFatal=*/false );
|
|
if ( !myMesh )
|
|
return addMessage("Supporting mesh not set", /*isFatal=*/true );
|
|
|
|
int version = -1, major, minor, release;
|
|
if ( MED::GetMEDVersion( myFile, major, minor, release ))
|
|
version = major * 10 + minor;
|
|
|
|
MED::PWrapper medFile = MED::CrWrapperW( myFile, version );
|
|
MED::PMeshInfo meshInfo;
|
|
if ( myMeshId > 0 )
|
|
{
|
|
meshInfo = medFile->GetPMeshInfo( myMeshId );
|
|
}
|
|
else
|
|
{
|
|
// look for a mesh by name
|
|
int aNbMeshes = medFile->GetNbMeshes();
|
|
for ( int iMesh = aNbMeshes; iMesh > 0 && myMeshId < 1; --iMesh )
|
|
{
|
|
meshInfo = medFile->GetPMeshInfo( iMesh );
|
|
if ( !meshInfo || meshInfo->GetName() != myMeshName )
|
|
meshInfo.reset();
|
|
else
|
|
myMeshId = iMesh;
|
|
}
|
|
}
|
|
if (( !meshInfo ) ||
|
|
( !myMeshName.empty() && meshInfo->GetName() != myMeshName ))
|
|
{
|
|
myMeshId = -1;
|
|
return addMessage("DriverMED_W_Field: Specified mesh not found in the file", /*isFatal=*/true );
|
|
}
|
|
|
|
// create a field
|
|
MED::ETypeChamp dataType = _dblValues.empty() ? MED::eINT : MED::eFLOAT64;
|
|
MED::PFieldInfo fieldInfo = medFile->CrFieldInfo( meshInfo,
|
|
_compNames.size(),
|
|
dataType );
|
|
fieldInfo->SetName( _fieldName );
|
|
for ( size_t iC = 0; iC < _compNames.size(); ++iC )
|
|
{
|
|
fieldInfo->SetCompName( iC, _compNames[ iC ]);
|
|
fieldInfo->SetUnitName( iC, "");
|
|
}
|
|
if ( _compNames.size() > 1 )
|
|
{
|
|
for ( size_t i = 0; i < fieldInfo->myCompNames.size()-1; ++i )
|
|
if ( !fieldInfo->myCompNames[i] )
|
|
fieldInfo->myCompNames[i] = ' ';
|
|
}
|
|
medFile->SetFieldInfo( fieldInfo );
|
|
|
|
// specific treatment of added 0D elements
|
|
if ( _nbElemsByGeom.size() == 3 &&
|
|
_nbElemsByGeom[1].first == SMDSEntity_0D )
|
|
{
|
|
_nbElemsByGeom[1].second += _nbElemsByGeom[2].second;
|
|
_nbElemsByGeom.resize( 2 );
|
|
}
|
|
|
|
// create a time stamp
|
|
MED::TGeom2Size type2nb;
|
|
for ( size_t iG = 1; iG < _nbElemsByGeom.size(); ++iG )
|
|
{
|
|
SMDSAbs_EntityType smdsType = _nbElemsByGeom[iG].first;
|
|
MED::EGeometrieElement medType = (MED::EGeometrieElement) DriverMED::GetMedGeoType( smdsType );
|
|
int nbElems = _nbElemsByGeom[iG].second - _nbElemsByGeom[iG-1].second;
|
|
type2nb.insert( std::make_pair( medType, nbElems ));
|
|
}
|
|
|
|
MED::EEntiteMaillage entity = ( _elemType == SMDSAbs_Node ? MED::eNOEUD : MED::eMAILLE );
|
|
MED::PTimeStampInfo timeStampInfo = medFile->CrTimeStampInfo( fieldInfo, entity, type2nb );
|
|
timeStampInfo->myNumDt = _dt;
|
|
timeStampInfo->myNumOrd = _it;
|
|
|
|
MED::PTimeStampValueBase timeStampVal = medFile->CrTimeStampValue( timeStampInfo, dataType );
|
|
MED::PFloatTimeStampValue timeStampFltVal = timeStampVal;
|
|
MED::PIntTimeStampValue timeStampIntVal = timeStampVal;
|
|
|
|
// set values
|
|
int iVal = 0;
|
|
MED::TFloat* ptrDbl = 0;
|
|
MED::TInt* ptrInt = 0;
|
|
for ( size_t iG = 1; iG < _nbElemsByGeom.size(); ++iG )
|
|
{
|
|
SMDSAbs_EntityType smdsType = _nbElemsByGeom[iG].first;
|
|
MED::EGeometrieElement medType = (MED::EGeometrieElement) DriverMED::GetMedGeoType( smdsType );
|
|
int nbElems = ( _nbElemsByGeom[iG].second - _nbElemsByGeom[iG-1].second ) * _compNames.size();
|
|
if ( dataType == MED::eFLOAT64 )
|
|
{
|
|
ptrDbl = timeStampFltVal->GetMeshValue( medType ).GetPointer();
|
|
for ( int i = 0; i < nbElems; ++i, ++iVal )
|
|
ptrDbl[ i ] = _dblValues[ iVal ];
|
|
}
|
|
else
|
|
{
|
|
ptrInt = timeStampIntVal->GetMeshValue( medType ).GetPointer();
|
|
for ( int i = 0; i < nbElems; ++i, ++iVal )
|
|
ptrInt[ i ] = _intValues[ iVal ];
|
|
}
|
|
}
|
|
|
|
// write
|
|
medFile->SetTimeStampValue( timeStampVal );
|
|
|
|
_dblValues.clear();
|
|
_intValues.clear();
|
|
|
|
return DRS_OK;
|
|
}
|
|
|
|
namespace DriverMED // Implementation of functions declared in DriverMED.hxx
|
|
{
|
|
//================================================================================
|
|
/*!
|
|
* Returns a vector containing MED::EGeometrieElement for each SMDSAbs_EntityType
|
|
*/
|
|
//================================================================================
|
|
|
|
const std::vector< MED::EGeometrieElement >& getMedTypesVec()
|
|
{
|
|
static std::vector< MED::EGeometrieElement > theVec;
|
|
if ( theVec.empty() )
|
|
{
|
|
theVec.resize( SMDSEntity_Last, MED::eAllGeoType );
|
|
theVec[ SMDSEntity_Node ] = MED::eNONE ;
|
|
theVec[ SMDSEntity_0D ] = MED::ePOINT1 ;
|
|
theVec[ SMDSEntity_Edge ] = MED::eSEG2 ;
|
|
theVec[ SMDSEntity_Quad_Edge ] = MED::eSEG3 ;
|
|
theVec[ SMDSEntity_Triangle ] = MED::eTRIA3 ;
|
|
theVec[ SMDSEntity_Quad_Triangle ] = MED::eTRIA6 ;
|
|
theVec[ SMDSEntity_BiQuad_Triangle ] = MED::eTRIA7 ;
|
|
theVec[ SMDSEntity_Quadrangle ] = MED::eQUAD4 ;
|
|
theVec[ SMDSEntity_Quad_Quadrangle ] = MED::eQUAD8 ;
|
|
theVec[ SMDSEntity_BiQuad_Quadrangle ] = MED::eQUAD9 ;
|
|
theVec[ SMDSEntity_Polygon ] = MED::ePOLYGONE;
|
|
//theVec[ SMDSEntity_Quad_Polygon ] = MED::ePOLYGONE; // !!
|
|
theVec[ SMDSEntity_Tetra ] = MED::eTETRA4 ;
|
|
theVec[ SMDSEntity_Quad_Tetra ] = MED::eTETRA10 ;
|
|
theVec[ SMDSEntity_Pyramid ] = MED::ePYRA5 ;
|
|
theVec[ SMDSEntity_Quad_Pyramid ] = MED::ePYRA13 ;
|
|
theVec[ SMDSEntity_Hexa ] = MED::eHEXA8 ;
|
|
theVec[ SMDSEntity_Quad_Hexa ] = MED::eHEXA20 ;
|
|
theVec[ SMDSEntity_TriQuad_Hexa ] = MED::eHEXA27 ;
|
|
theVec[ SMDSEntity_Penta ] = MED::ePENTA6 ;
|
|
theVec[ SMDSEntity_Quad_Penta ] = MED::ePENTA15 ;
|
|
theVec[ SMDSEntity_BiQuad_Penta ] = MED::ePENTA18 ;
|
|
theVec[ SMDSEntity_Hexagonal_Prism ] = MED::eOCTA12 ;
|
|
theVec[ SMDSEntity_Polyhedra ] = MED::ePOLYEDRE;
|
|
//theVec[ SMDSEntity_Quad_Polyhedra ] = MED::ePOLYEDRE; // !!
|
|
theVec[ SMDSEntity_Ball ] = MED::eBALL ;
|
|
}
|
|
return theVec;
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* Returns MED element geom type (MED::EGeometrieElement) by SMDS type
|
|
*/
|
|
//================================================================================
|
|
|
|
int GetMedGeoType( SMDSAbs_EntityType smdsType )
|
|
{
|
|
return getMedTypesVec()[ smdsType ];
|
|
}
|
|
|
|
//================================================================================
|
|
/*!
|
|
* Returns SMDS element geom type by MED type (MED::EGeometrieElement)
|
|
*/
|
|
//================================================================================
|
|
|
|
SMDSAbs_EntityType GetSMDSType( int medType )
|
|
{
|
|
const std::vector< MED::EGeometrieElement >& theVec = getMedTypesVec();
|
|
|
|
std::vector< MED::EGeometrieElement >::const_iterator i =
|
|
std::find( theVec.begin(), theVec.end(), medType );
|
|
|
|
return SMDSAbs_EntityType( std::distance( theVec.begin(), i ));
|
|
}
|
|
}
|