2015-04-23 13:24:15 +02:00
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) Statoil ASA
// Copyright (C) Ceetron Solutions AS
//
// ResInsight 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 3 of the License, or
// (at your option) any later version.
//
// ResInsight 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 at <http://www.gnu.org/licenses/gpl.html>
// for more details.
//
/////////////////////////////////////////////////////////////////////////////////
2015-05-06 09:59:24 +02:00
#ifdef _MSC_VER
2015-06-04 13:02:49 +02:00
// Get rid of warnings from compilation of ODB API
#pragma warning(push)
#pragma warning(disable: 4018)
2015-05-06 09:59:24 +02:00
#pragma warning(disable: 4482)
#pragma warning(disable: 4584)
2015-06-04 13:02:49 +02:00
#pragma warning(disable: 4800)
#endif
#include <odb_API.h>
#include <odb_Enum.h>
#ifdef _MSC_VER
#pragma warning(pop)
2015-05-06 09:59:24 +02:00
#endif
2015-04-23 13:24:15 +02:00
#include "RifOdbReader.h"
2015-04-27 10:25:04 +02:00
#include "RigFemPartCollection.h"
2015-04-23 13:24:15 +02:00
#include "RigFemPart.h"
2015-04-23 15:43:11 +02:00
#include <map>
2015-04-28 09:21:27 +02:00
#include <iostream>
2015-05-06 09:47:19 +02:00
#include <limits>
2015-05-06 13:22:09 +02:00
#include <sstream>
2015-05-20 15:22:10 +02:00
#include "cafProgressInfo.h"
#include <QString>
2015-04-23 15:43:11 +02:00
2015-05-06 09:59:24 +02:00
2015-06-04 14:20:16 +02:00
//==================================================================================================
//
// Helper class to ensure that ODB bulk data are returned as float. Converting if necessary.
//
//==================================================================================================
class RifOdbBulkDataGetter
{
public :
2017-03-06 11:18:12 +01:00
explicit RifOdbBulkDataGetter ( const odb_FieldBulkData & bulkData ) : m_bulkData ( bulkData ) {};
2015-06-12 09:38:10 +02:00
virtual ~ RifOdbBulkDataGetter () {};
2015-06-04 14:20:16 +02:00
2015-06-04 07:46:33 -07:00
float * data ()
2015-06-04 14:20:16 +02:00
{
odb_Enum :: odb_PrecisionEnum precision = m_bulkData . precision ();
if ( precision == odb_Enum :: SINGLE_PRECISION )
{
return m_bulkData . data ();
}
else if ( precision == odb_Enum :: DOUBLE_PRECISION )
{
2015-06-12 09:38:10 +02:00
if ( m_data . size () < 1 )
{
int dataSize = m_bulkData . length () * m_bulkData . width ();
m_data . resize ( dataSize );
double * doublePtr = m_bulkData . dataDouble ();
CVF_ASSERT ( doublePtr );
float * dataPtr = m_data . data ();
for ( int i = 0 ; i < dataSize ; i ++ )
{
dataPtr [ i ] = ( float ) doublePtr [ i ];
}
2015-06-04 14:20:16 +02:00
}
2015-06-12 09:38:10 +02:00
return m_data . data ();
2015-06-04 14:20:16 +02:00
}
// Should never end up here
CVF_ASSERT ( 0 );
return NULL ;
}
private :
const odb_FieldBulkData & m_bulkData ;
2015-06-12 09:38:10 +02:00
std :: vector < float > m_data ;
2015-06-04 14:20:16 +02:00
};
2015-06-04 11:14:12 +02:00
2015-05-12 14:35:11 +02:00
size_t RifOdbReader :: sm_instanceCount = 0 ;
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-04-23 15:43:11 +02:00
std :: map < std :: string , RigElementType > initFemTypeMap ()
{
std :: map < std :: string , RigElementType > typeMap ;
typeMap [ "C3D8R" ] = HEX8 ;
2015-04-28 09:21:27 +02:00
typeMap [ "C3D8" ] = HEX8 ;
2015-09-25 19:31:50 +02:00
typeMap [ "C3D8P" ] = HEX8P ;
2015-04-23 15:43:11 +02:00
typeMap [ "CAX4" ] = CAX4 ;
return typeMap ;
}
2015-05-12 14:35:11 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RigElementType toRigElementType ( const odb_String & odbTypeName )
{
static std :: map < std :: string , RigElementType > odbElmTypeToRigElmTypeMap = initFemTypeMap ();
std :: map < std :: string , RigElementType >:: iterator it = odbElmTypeToRigElmTypeMap . find ( odbTypeName . cStr ());
if ( it == odbElmTypeToRigElmTypeMap . end ())
{
#if 0
std::cout << "Unsupported element type :" << odbElm.type().cStr() << std::endl;
#endif
return UNKNOWN_ELM_TYPE ;
}
2015-04-23 13:24:15 +02:00
2015-05-12 14:35:11 +02:00
return it -> second ;
}
2015-05-12 14:22:26 +02:00
2015-05-12 14:35:11 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-04-30 09:31:33 +02:00
2015-05-12 14:22:26 +02:00
const int * localElmNodeToIntegrationPointMapping ( RigElementType elmType )
{
static const int HEX8_Mapping [ 8 ] = { 0 , 1 , 3 , 2 , 4 , 5 , 7 , 6 };
switch ( elmType )
{
case HEX8 :
2015-09-25 19:31:50 +02:00
case HEX8P :
2015-05-12 14:22:26 +02:00
return HEX8_Mapping ;
break ;
case CAX4 :
2015-05-12 14:35:11 +02:00
return HEX8_Mapping ; // First four is identical to HEX8
2015-05-12 14:22:26 +02:00
break ;
default :
//assert(false); // Element type not supported
break ;
}
return NULL ;
}
2015-04-23 13:24:15 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifOdbReader :: RifOdbReader ()
{
2015-05-07 15:41:19 +02:00
if ( ++ sm_instanceCount == 1 )
{
odb_initializeAPI ();
}
2015-10-23 15:46:25 +02:00
m_odb = NULL ;
2015-04-23 13:24:15 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
RifOdbReader ::~ RifOdbReader ()
{
2015-10-23 15:46:25 +02:00
close ();
2015-04-30 09:31:33 +02:00
2015-05-07 15:41:19 +02:00
if ( -- sm_instanceCount == 0 )
{
odb_finalizeAPI ();
}
2015-04-30 09:31:33 +02:00
}
2015-04-23 13:24:15 +02:00
2015-04-30 09:31:33 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOdbReader :: close ()
{
2015-10-23 15:46:25 +02:00
if ( m_odb )
{
m_odb -> close ();
m_odb = NULL ;
}
2015-04-23 13:24:15 +02:00
}
2015-05-04 11:03:20 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-05-06 13:22:09 +02:00
bool RifOdbReader :: openFile ( const std :: string & fileName , std :: string * errorMessage )
2015-04-23 13:24:15 +02:00
{
2015-10-23 15:46:25 +02:00
close ();
CVF_ASSERT ( m_odb == NULL );
2015-04-23 13:24:15 +02:00
2015-10-23 15:46:25 +02:00
odb_String path = fileName . c_str ();
2015-04-23 15:43:11 +02:00
2015-10-23 15:46:25 +02:00
try
{
m_odb = & openOdb ( path , true );
}
2015-04-24 15:53:50 +02:00
2015-10-23 15:46:25 +02:00
catch ( const nex_Exception & nex )
2015-04-23 15:43:11 +02:00
{
2015-05-06 13:22:09 +02:00
if ( errorMessage )
{
* errorMessage = nex . UserReport (). CStr ();
}
return false ;
2015-05-04 11:03:20 +02:00
}
2015-04-23 13:24:15 +02:00
2015-05-04 11:03:20 +02:00
catch (...)
{
2015-05-06 13:22:09 +02:00
if ( errorMessage )
{
std :: stringstream errStr ;
errStr << "Unable to open file '" << fileName << "'." ;
* errorMessage = errStr . str ();
}
return false ;
2015-04-23 15:43:11 +02:00
}
2015-04-23 13:24:15 +02:00
2015-10-23 15:46:25 +02:00
return true ;
2015-05-04 11:03:20 +02:00
}
2015-04-23 13:24:15 +02:00
2015-05-06 10:22:45 +02:00
2015-05-04 14:31:12 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-09 11:17:54 +02:00
void RifOdbReader :: assertMetaDataLoaded ()
2015-05-04 14:31:12 +02:00
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( m_odb != NULL );
2015-05-04 14:31:12 +02:00
2015-06-09 11:17:54 +02:00
if ( m_resultsMetaData . empty ())
2015-10-23 15:46:25 +02:00
{
2015-06-09 11:17:54 +02:00
m_resultsMetaData = readResultsMetaData ( m_odb );
}
2015-10-23 15:46:25 +02:00
2015-05-04 14:31:12 +02:00
}
2015-04-30 13:59:34 +02:00
2015-05-04 14:31:12 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-09 11:17:54 +02:00
std :: map < RifOdbReader :: RifOdbResultKey , std :: vector < std :: string > > RifOdbReader :: readResultsMetaData ( odb_Odb * odb )
2015-05-04 14:31:12 +02:00
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( odb != NULL );
2015-05-04 14:31:12 +02:00
2015-06-04 11:14:12 +02:00
std :: map < RifOdbResultKey , std :: vector < std :: string > > resultsMap ;
2015-05-04 14:31:12 +02:00
2015-10-23 15:46:25 +02:00
const odb_StepRepository & stepRepository = odb -> steps ();
2015-06-03 11:37:13 +02:00
odb_StepRepositoryIT stepIt ( stepRepository );
stepIt . first ();
const odb_Step & step = stepRepository . constGet ( stepIt . currentKey ());
const odb_SequenceFrame & stepFrames = step . frames ();
2015-06-03 10:51:00 +02:00
2015-06-03 12:02:34 +02:00
if ( stepFrames . size () > 1 )
2015-06-03 11:37:13 +02:00
{
2015-06-03 12:02:34 +02:00
// Optimization: Get results metadata for the second frame of the first step only
2015-10-23 15:46:25 +02:00
const odb_Frame & frame = stepFrames . constGet ( 1 );
const odb_FieldOutputRepository & fieldCon = frame . fieldOutputs ();
odb_FieldOutputRepositoryIT fieldConIT ( fieldCon );
for ( fieldConIT . first (); ! fieldConIT . isDone (); fieldConIT . next ())
{
const odb_FieldOutput & field = fieldCon [ fieldConIT . currentKey ()];
const odb_SequenceFieldLocation & fieldLocations = field . locations ();
for ( int loc = 0 ; loc < fieldLocations . size (); loc ++ )
{
const odb_FieldLocation & fieldLocation = fieldLocations . constGet ( loc );
std :: string fieldName = field . name (). CStr ();
odb_SequenceString components = field . componentLabels ();
std :: vector < std :: string > compVec ;
int numComp = components . size ();
for ( int comp = 0 ; comp < numComp ; comp ++ )
{
compVec . push_back ( components [ comp ]. CStr ());
}
switch ( fieldLocation . position ())
{
case odb_Enum :: NODAL :
2015-06-12 14:33:55 +02:00
resultsMap [ RifOdbResultKey ( NODAL , fieldName )] = compVec ;
2015-10-23 15:46:25 +02:00
break ;
2015-05-04 14:31:12 +02:00
2015-06-03 11:37:13 +02:00
case odb_Enum :: ELEMENT_NODAL :
2015-06-12 14:33:55 +02:00
resultsMap [ RifOdbResultKey ( ELEMENT_NODAL , fieldName )] = compVec ;
2015-10-23 15:46:25 +02:00
break ;
2015-05-04 14:31:12 +02:00
2015-10-23 15:46:25 +02:00
case odb_Enum :: INTEGRATION_POINT :
2015-06-12 14:33:55 +02:00
resultsMap [ RifOdbResultKey ( INTEGRATION_POINT , fieldName )] = compVec ;
resultsMap [ RifOdbResultKey ( ELEMENT_NODAL , fieldName )] = compVec ;
2015-10-23 15:46:25 +02:00
break ;
2015-05-04 14:31:12 +02:00
2015-10-23 15:46:25 +02:00
default :
break ;
}
}
2015-06-03 11:37:13 +02:00
}
}
stepFrames . release ();
2015-05-04 14:31:12 +02:00
2015-10-23 15:46:25 +02:00
return resultsMap ;
2015-05-04 14:31:12 +02:00
}
2015-04-30 13:59:34 +02:00
2015-04-23 13:24:15 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-05-04 11:03:20 +02:00
bool RifOdbReader :: readFemParts ( RigFemPartCollection * femParts )
2015-04-23 13:24:15 +02:00
{
2015-05-04 11:03:20 +02:00
CVF_ASSERT ( femParts );
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( m_odb != NULL );
2015-04-30 14:05:46 +02:00
2015-05-04 11:03:20 +02:00
odb_InstanceRepository instanceRepository = m_odb -> rootAssembly (). instances ();
odb_InstanceRepositoryIT iter ( instanceRepository );
2015-04-23 13:24:15 +02:00
2015-05-20 15:22:10 +02:00
caf :: ProgressInfo modelProgress ( instanceRepository . size () * ( 2 + 4 ), "Reading Odb Parts" );
2015-05-06 09:47:19 +02:00
int instanceCount = 0 ;
for ( iter . first (); ! iter . isDone (); iter . next (), instanceCount ++ )
2015-04-23 13:24:15 +02:00
{
2015-05-20 15:22:10 +02:00
modelProgress . setProgressDescription ( QString ( iter . currentKey (). cStr ()) + ": Reading Nodes" );
m_nodeIdToIdxMaps . push_back ( std :: map < int , int > ());
2015-05-04 11:03:20 +02:00
odb_Instance & inst = instanceRepository [ iter . currentKey ()];
2015-04-23 13:24:15 +02:00
2015-05-04 11:03:20 +02:00
RigFemPart * femPart = new RigFemPart ;
// Extract nodes
const odb_SequenceNode & odbNodes = inst . nodes ();
2015-05-20 15:22:10 +02:00
std :: map < int , int >& nodeIdToIdxMap = m_nodeIdToIdxMaps . back ();
2015-05-04 11:03:20 +02:00
int nodeCount = odbNodes . size ();
femPart -> nodes (). nodeIds . resize ( nodeCount );
femPart -> nodes (). coordinates . resize ( nodeCount );
for ( int nIdx = 0 ; nIdx < nodeCount ; ++ nIdx )
{
const odb_Node odbNode = odbNodes . node ( nIdx );
femPart -> nodes (). nodeIds [ nIdx ] = odbNode . label ();
const float * pos = odbNode . coordinates ();
femPart -> nodes (). coordinates [ nIdx ]. set ( pos [ 0 ], pos [ 1 ], pos [ 2 ]);
nodeIdToIdxMap [ odbNode . label ()] = nIdx ;
2015-05-20 15:22:10 +02:00
// Progress reporting
if ( nIdx == nodeCount / 2 )
{
modelProgress . incrementProgress ();
}
2015-05-04 11:03:20 +02:00
}
2015-05-20 15:22:10 +02:00
modelProgress . incrementProgress ();
modelProgress . setProgressDescription ( QString ( iter . currentKey (). cStr ()) + ": Reading Elements" );
2015-05-06 09:47:19 +02:00
2015-05-04 11:03:20 +02:00
// Extract elements
const odb_SequenceElement & elements = inst . elements ();
int elmCount = elements . size ();
femPart -> preAllocateElementStorage ( elmCount );
2017-03-06 11:18:12 +01:00
2015-05-04 11:03:20 +02:00
std :: vector < int > indexBasedConnectivities ;
2015-05-20 15:22:10 +02:00
m_elementIdToIdxMaps . push_back ( std :: map < int , int > ());
std :: map < int , int >& elementIdToIdxMap = m_elementIdToIdxMaps . back ();
2015-05-04 11:03:20 +02:00
for ( int elmIdx = 0 ; elmIdx < elmCount ; ++ elmIdx )
{
const odb_Element odbElm = elements . element ( elmIdx );
2015-05-06 09:47:19 +02:00
elementIdToIdxMap [ odbElm . label ()] = elmIdx ;
2015-05-12 14:35:11 +02:00
RigElementType elmType = toRigElementType ( odbElm . type ());
if ( elmType == UNKNOWN_ELM_TYPE ) continue ;
2015-05-04 11:03:20 +02:00
int nodeCount = 0 ;
const int * idBasedConnectivities = odbElm . connectivity ( nodeCount );
CVF_TIGHT_ASSERT ( nodeCount == RigFemTypes :: elmentNodeCount ( elmType ));
indexBasedConnectivities . resize ( nodeCount );
for ( int lnIdx = 0 ; lnIdx < nodeCount ; ++ lnIdx )
{
indexBasedConnectivities [ lnIdx ] = nodeIdToIdxMap [ idBasedConnectivities [ lnIdx ]];
}
femPart -> appendElement ( elmType , odbElm . label (), indexBasedConnectivities . data ());
2015-05-20 15:22:10 +02:00
// Progress reporting
if ( elmIdx == elmCount / 4 || elmIdx == elmCount / 2 || elmIdx == 3 * elmCount / 4 )
{
modelProgress . incrementProgress ();
}
}
2015-05-06 09:47:19 +02:00
2015-05-04 11:03:20 +02:00
femPart -> setElementPartId ( femParts -> partCount ());
femParts -> addFemPart ( femPart );
2015-04-23 13:24:15 +02:00
2015-05-20 15:22:10 +02:00
modelProgress . incrementProgress ();
}
2015-10-23 15:46:25 +02:00
return true ;
2015-04-23 13:24:15 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-04-30 13:59:34 +02:00
std :: vector < std :: string > RifOdbReader :: stepNames ()
2015-04-30 09:31:33 +02:00
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( m_odb != NULL );
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
std :: vector < std :: string > stepNames ;
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
odb_StepRepository stepRepository = m_odb -> steps ();
odb_StepRepositoryIT sIter ( stepRepository );
for ( sIter . first (); ! sIter . isDone (); sIter . next ())
{
stepNames . push_back ( stepRepository [ sIter . currentKey ()]. name (). CStr ());
}
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
return stepNames ;
2015-04-30 09:31:33 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-04-30 13:59:34 +02:00
std :: vector < double > RifOdbReader :: frameTimes ( int stepIndex )
2015-04-30 09:31:33 +02:00
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( m_odb != NULL );
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
odb_StepRepository & stepRepository = m_odb -> steps ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
odb_StepList stepList = stepRepository . stepList ();
odb_Step & step = stepList . Get ( stepIndex );
odb_SequenceFrame & stepFrames = step . frames ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
std :: vector < double > frameValues ;
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
int numFrames = stepFrames . size ();
for ( int f = 0 ; f < numFrames ; f ++ )
{
odb_Frame frame = stepFrames . constGet ( f );
frameValues . push_back ( frame . frameValue ());
}
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
return frameValues ;
2015-04-30 09:31:33 +02:00
}
2015-06-04 16:16:35 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std :: vector < std :: string > RifOdbReader :: elementSetNames ( int partIndex )
{
CVF_ASSERT ( m_odb != NULL );
std :: map < int , std :: vector < std :: string > >:: const_iterator mapIt = m_partElementSetNames . find ( partIndex );
if ( mapIt == m_partElementSetNames . end ())
{
std :: vector < std :: string > setNames ;
const odb_Assembly & rootAssembly = m_odb -> constRootAssembly ();
const odb_InstanceRepository & instances = rootAssembly . instances ();
int currentInstance = 0 ;
odb_InstanceRepositoryIT instIt ( instances );
2015-10-23 15:46:25 +02:00
for ( instIt . first (); ! instIt . isDone (); instIt . next (), currentInstance ++ )
{
2015-06-04 16:16:35 +02:00
const odb_Instance & instance = instIt . currentValue ();
if ( currentInstance == partIndex )
{
const odb_SetRepository & sets = rootAssembly . elementSets ();
2015-10-23 15:46:25 +02:00
odb_SetRepositoryIT setIt ( sets );
for ( setIt . first (); ! setIt . isDone (); setIt . next ())
{
2015-06-04 16:16:35 +02:00
const odb_Set & set = setIt . currentValue ();
setNames . push_back ( set . name (). CStr ());
2015-10-23 15:46:25 +02:00
}
2015-06-04 16:16:35 +02:00
break ;
}
2015-10-23 15:46:25 +02:00
}
2015-06-04 16:16:35 +02:00
m_partElementSetNames [ partIndex ] = setNames ;
}
return m_partElementSetNames . at ( partIndex );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std :: vector < size_t > RifOdbReader :: elementSet ( int partIndex , int setIndex )
{
CVF_ASSERT ( m_odb != NULL );
std :: vector < std :: string > setNames = elementSetNames ( partIndex );
const odb_Assembly & rootAssembly = m_odb -> constRootAssembly ();
const odb_Set & set = rootAssembly . elementSets ()[ odb_String ( setNames [ setIndex ]. c_str ())];
odb_SequenceString instanceNames = set . instanceNames ();
2015-10-23 15:46:25 +02:00
const odb_SequenceElement & setElements = set . elements ( instanceNames [ partIndex ]);
int elementCount = setElements . size ();
2015-06-04 16:16:35 +02:00
std :: vector < size_t > elementIndexes ;
elementIndexes . resize ( elementCount );
2015-10-23 15:46:25 +02:00
for ( int i = 0 ; i < elementCount ; i ++ )
{
2015-06-04 16:16:35 +02:00
elementIndexes [ i ] = setElements . element ( i ). index ();
2015-10-23 15:46:25 +02:00
}
2015-06-04 16:16:35 +02:00
return elementIndexes ;
}
2015-04-30 09:31:33 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-05-04 14:31:12 +02:00
std :: map < std :: string , std :: vector < std :: string > > RifOdbReader :: scalarNodeFieldAndComponentNames ()
2015-04-23 13:24:15 +02:00
{
2015-06-12 14:33:55 +02:00
return fieldAndComponentNames ( NODAL );
2015-04-30 13:59:34 +02:00
}
2015-04-30 09:31:33 +02:00
2015-04-30 13:59:34 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-05-04 14:31:12 +02:00
std :: map < std :: string , std :: vector < std :: string > > RifOdbReader :: scalarElementNodeFieldAndComponentNames ()
2015-04-30 13:59:34 +02:00
{
2015-06-12 14:33:55 +02:00
return fieldAndComponentNames ( ELEMENT_NODAL );
2015-04-30 13:59:34 +02:00
}
2015-04-30 09:31:33 +02:00
2015-04-30 13:59:34 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-05-04 14:31:12 +02:00
std :: map < std :: string , std :: vector < std :: string > > RifOdbReader :: scalarIntegrationPointFieldAndComponentNames ()
2015-04-30 13:59:34 +02:00
{
2015-06-12 14:33:55 +02:00
return fieldAndComponentNames ( INTEGRATION_POINT );
2015-04-30 09:31:33 +02:00
}
2015-04-30 13:59:34 +02:00
2015-04-30 09:31:33 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-03 11:15:05 +02:00
const odb_Frame & RifOdbReader :: stepFrame ( int stepIndex , int frameIndex ) const
2015-04-30 09:31:33 +02:00
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( m_odb );
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
const odb_StepRepository & stepRepository = m_odb -> steps ();
const odb_StepList & stepList = stepRepository . stepList ();
2015-06-03 11:15:05 +02:00
const odb_Step & step = stepList . ConstGet ( stepIndex );
2015-10-23 15:46:25 +02:00
const odb_SequenceFrame & stepFrames = step . frames ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
return stepFrames . constGet ( frameIndex );
2015-04-30 09:31:33 +02:00
}
2015-05-06 09:47:19 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
odb_Instance * RifOdbReader :: instance ( int instanceIndex )
{
CVF_ASSERT ( m_odb != NULL );
odb_InstanceRepository & instanceRepository = m_odb -> rootAssembly (). instances ();
odb_InstanceRepositoryIT iter ( instanceRepository );
int instanceCount = 0 ;
for ( iter . first (); ! iter . isDone (); iter . next (), instanceCount ++ )
{
odb_Instance & inst = instanceRepository [ iter . currentKey ()];
if ( instanceCount == instanceIndex )
{
return & inst ;
}
}
return NULL ;
}
2015-04-30 09:31:33 +02:00
//--------------------------------------------------------------------------------------------------
/// Get the number of result items (== #nodes or #elements)
//--------------------------------------------------------------------------------------------------
2015-05-06 13:32:14 +02:00
size_t RifOdbReader :: resultItemCount ( const std :: string & fieldName , int partIndex , int stepIndex , int frameIndex )
2015-04-30 09:31:33 +02:00
{
2015-05-06 13:32:14 +02:00
odb_Instance * partInstance = instance ( partIndex );
CVF_ASSERT ( partInstance != NULL );
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
const odb_Frame & frame = stepFrame ( stepIndex , frameIndex );
const odb_FieldOutput & instanceFieldOutput = frame . fieldOutputs ()[ fieldName . c_str ()]. getSubset ( * partInstance );
const odb_SequenceFieldBulkData & seqFieldBulkData = instanceFieldOutput . bulkDataBlocks ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
size_t resultItemCount = 0 ;
int numBlocks = seqFieldBulkData . size ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
for ( int block = 0 ; block < numBlocks ; block ++ )
{
const odb_FieldBulkData & bulkData = seqFieldBulkData [ block ];
resultItemCount += bulkData . length ();
}
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
return resultItemCount ;
2015-04-30 09:31:33 +02:00
}
2015-06-12 14:33:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
size_t RifOdbReader :: componentsCount ( const std :: string & fieldName , ResultPosition position )
{
std :: vector < std :: string > compNames = componentNames ( RifOdbResultKey ( position , fieldName ));
return compNames . size () > 0 ? compNames . size () : 1 ;
}
2015-04-30 09:31:33 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-09 11:17:54 +02:00
int RifOdbReader :: componentIndex ( const RifOdbResultKey & result , const std :: string & componentName )
2015-04-30 09:31:33 +02:00
{
2015-10-23 15:46:25 +02:00
std :: vector < std :: string > compNames = componentNames ( result );
2015-05-04 14:31:12 +02:00
2015-06-09 11:17:54 +02:00
// If there are no component names, we expect the field to be a pure scalar.
// Then an empty string is the valid component name
if ( ! compNames . size () && componentName == "" ) return 0 ;
2015-10-23 15:46:25 +02:00
for ( size_t i = 0 ; i < compNames . size (); i ++ )
{
if ( compNames [ i ] == componentName )
{
return static_cast < int > ( i );
}
}
2015-05-04 14:31:12 +02:00
2015-10-23 15:46:25 +02:00
return - 1 ;
2015-05-04 14:31:12 +02:00
}
2015-04-30 13:59:34 +02:00
2015-04-30 09:31:33 +02:00
2015-05-04 14:31:12 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-09 11:17:54 +02:00
std :: vector < std :: string > RifOdbReader :: componentNames ( const RifOdbResultKey & result )
2015-05-04 14:31:12 +02:00
{
2015-06-09 11:17:54 +02:00
assertMetaDataLoaded ();
2015-05-04 14:31:12 +02:00
2015-06-04 11:14:12 +02:00
std :: map < RifOdbResultKey , std :: vector < std :: string > >:: const_iterator resMapIt = m_resultsMetaData . find ( result );
2015-10-23 15:46:25 +02:00
if ( resMapIt != m_resultsMetaData . end ())
{
2015-06-09 11:17:54 +02:00
std :: vector < std :: string > compNames ;
2015-06-04 11:14:12 +02:00
compNames = resMapIt -> second ;
2015-06-09 11:17:54 +02:00
return compNames ;
2015-10-23 15:46:25 +02:00
}
2015-06-09 11:17:54 +02:00
CVF_ASSERT ( false );
2015-10-23 15:46:25 +02:00
return std :: vector < std :: string > ();
2015-05-04 14:31:12 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-12 14:33:55 +02:00
std :: map < std :: string , std :: vector < std :: string > > RifOdbReader :: fieldAndComponentNames ( ResultPosition position )
2015-05-04 14:31:12 +02:00
{
2015-06-09 11:17:54 +02:00
assertMetaDataLoaded ();
2015-05-04 14:31:12 +02:00
2015-06-04 11:14:12 +02:00
std :: map < std :: string , std :: vector < std :: string > > fieldsAndComponents ;
std :: map < RifOdbResultKey , std :: vector < std :: string > >:: const_iterator resMapIt ;
2017-03-03 16:23:20 +01:00
for ( resMapIt = m_resultsMetaData . begin (); resMapIt != m_resultsMetaData . end (); ++ resMapIt )
2015-10-23 15:46:25 +02:00
{
2015-06-04 11:14:12 +02:00
if ( resMapIt -> first . resultPostion == position )
{
fieldsAndComponents [ resMapIt -> first . fieldName ] = resMapIt -> second ;
}
2015-10-23 15:46:25 +02:00
}
2015-06-04 11:14:12 +02:00
return fieldsAndComponents ;
2015-04-30 09:31:33 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOdbReader :: readDisplacements ( int partIndex , int stepIndex , int frameIndex , std :: vector < cvf :: Vec3f >* displacements )
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( displacements );
2015-04-30 09:31:33 +02:00
2015-05-06 09:47:19 +02:00
odb_Instance * partInstance = instance ( partIndex );
CVF_ASSERT ( partInstance != NULL );
2015-10-23 15:46:25 +02:00
size_t dataSize = resultItemCount ( "U" , partIndex , stepIndex , frameIndex );
if ( dataSize > 0 )
{
displacements -> resize ( dataSize );
}
const odb_Frame & frame = stepFrame ( stepIndex , frameIndex );
const odb_FieldOutput & instanceFieldOutput = frame . fieldOutputs ()[ "U" ]. getSubset ( * partInstance );
const odb_SequenceFieldBulkData & seqFieldBulkData = instanceFieldOutput . bulkDataBlocks ();
size_t dataIndex = 0 ;
int numBlocks = seqFieldBulkData . size ();
for ( int block = 0 ; block < numBlocks ; block ++ )
{
const odb_FieldBulkData & bulkData = seqFieldBulkData [ block ];
2015-06-04 14:20:16 +02:00
RifOdbBulkDataGetter bulkDataGetter ( bulkData );
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
if ( bulkData . numberOfNodes () > 0 )
{
int numNodes = bulkData . length ();
int numComp = bulkData . width ();
2015-06-04 14:20:16 +02:00
float * data = bulkDataGetter . data ();
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
for ( int i = 0 ; i < numNodes ; i ++ )
{
( * displacements )[ i + dataIndex ]. set ( data [ i * numComp ], data [ i * numComp + 1 ], data [ i * numComp + 2 ]);
}
2015-04-30 09:31:33 +02:00
2015-10-23 15:46:25 +02:00
dataIndex += numNodes * numComp ;
}
}
2015-04-30 09:31:33 +02:00
}
2015-06-12 14:33:55 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOdbReader :: readNodeField ( const std :: string & fieldName , int partIndex , int stepIndex , int frameIndex , std :: vector < std :: vector < float >*>* resultValues )
{
2015-10-23 15:46:25 +02:00
CVF_ASSERT ( resultValues );
2015-06-12 14:33:55 +02:00
odb_Instance * partInstance = instance ( partIndex );
CVF_ASSERT ( partInstance != NULL );
size_t compCount = componentsCount ( fieldName , NODAL );
CVF_ASSERT ( compCount == resultValues -> size ());
std :: map < int , int >& nodeIdToIdxMap = m_nodeIdToIdxMaps [ partIndex ];
2015-06-12 20:02:35 +02:00
size_t dataSize = nodeIdToIdxMap . size ();
2015-06-12 18:41:47 +02:00
2015-10-23 15:46:25 +02:00
if ( dataSize > 0 )
{
2015-06-12 14:33:55 +02:00
for ( int comp = 0 ; comp < compCount ; comp ++ )
2015-10-23 15:46:25 +02:00
{
2015-06-12 14:33:55 +02:00
CVF_ASSERT (( * resultValues )[ comp ]);
2015-10-23 15:46:25 +02:00
( * resultValues )[ comp ] -> resize ( dataSize , std :: numeric_limits < float >:: infinity ());
2015-06-12 14:33:55 +02:00
}
2015-10-23 15:46:25 +02:00
}
2015-06-12 14:33:55 +02:00
2015-10-23 15:46:25 +02:00
const odb_Frame & frame = stepFrame ( stepIndex , frameIndex );
const odb_FieldOutput & instanceFieldOutput = frame . fieldOutputs ()[ fieldName . c_str ()]. getSubset ( * partInstance );
2015-06-12 18:41:47 +02:00
const odb_FieldOutput & fieldOutput = instanceFieldOutput . getSubset ( odb_Enum :: NODAL );
2015-10-23 15:46:25 +02:00
const odb_SequenceFieldBulkData & seqFieldBulkData = fieldOutput . bulkDataBlocks ();
2015-06-12 14:33:55 +02:00
2015-10-23 15:46:25 +02:00
int numBlocks = seqFieldBulkData . size ();
for ( int block = 0 ; block < numBlocks ; block ++ )
{
const odb_FieldBulkData & bulkData = seqFieldBulkData [ block ];
2015-06-12 14:33:55 +02:00
RifOdbBulkDataGetter bulkDataGetter ( bulkData );
2015-10-23 15:46:25 +02:00
int numNodes = bulkData . length ();
int numComp = bulkData . width ();
2015-06-12 14:33:55 +02:00
int * nodeLabels = bulkData . nodeLabels ();
float * data = bulkDataGetter . data ();
2015-10-23 15:46:25 +02:00
for ( int nIdx = 0 ; nIdx < numNodes ; nIdx ++ )
{
2015-06-12 14:33:55 +02:00
for ( int comp = 0 ; comp < numComp ; comp ++ )
{
2015-06-12 18:41:47 +02:00
std :: vector < float >* singleComponentValues = ( * resultValues )[ comp ];
( * singleComponentValues )[ nodeIdToIdxMap [ nodeLabels [ nIdx ]]] = data [ nIdx * numComp + comp ];
2015-06-12 14:33:55 +02:00
}
2015-10-23 15:46:25 +02:00
}
}
2015-06-12 14:33:55 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2015-06-12 18:41:47 +02:00
void RifOdbReader :: readElementNodeField ( const std :: string & fieldName ,
int partIndex , int stepIndex , int frameIndex ,
std :: vector < std :: vector < float >*>* resultValues )
2015-06-12 14:33:55 +02:00
{
CVF_ASSERT ( resultValues );
odb_Instance * partInstance = instance ( partIndex );
CVF_ASSERT ( partInstance != NULL );
size_t compCount = componentsCount ( fieldName , ELEMENT_NODAL );
CVF_ASSERT ( compCount == resultValues -> size ());
2015-06-12 20:02:35 +02:00
size_t dataSize = resultItemCount ( fieldName , partIndex , stepIndex , frameIndex );
2015-10-23 15:46:25 +02:00
if ( dataSize > 0 )
{
2015-06-12 14:33:55 +02:00
for ( int comp = 0 ; comp < compCount ; comp ++ )
2015-10-23 15:46:25 +02:00
{
2015-06-12 14:33:55 +02:00
CVF_ASSERT (( * resultValues )[ comp ]);
2015-10-23 15:46:25 +02:00
( * resultValues )[ comp ] -> resize ( dataSize , std :: numeric_limits < float >:: infinity ());
2015-06-12 14:33:55 +02:00
}
2015-10-23 15:46:25 +02:00
}
2015-06-12 14:33:55 +02:00
2015-10-23 15:46:25 +02:00
const odb_Frame & frame = stepFrame ( stepIndex , frameIndex );
const odb_FieldOutput & instanceFieldOutput = frame . fieldOutputs ()[ fieldName . c_str ()]. getSubset ( * partInstance );
2015-06-12 18:41:47 +02:00
const odb_FieldOutput & fieldOutput = instanceFieldOutput . getSubset ( odb_Enum :: ELEMENT_NODAL );
2015-10-23 15:46:25 +02:00
const odb_SequenceFieldBulkData & seqFieldBulkData = fieldOutput . bulkDataBlocks ();
2015-06-12 14:33:55 +02:00
std :: map < int , int >& elementIdToIdxMap = m_elementIdToIdxMaps [ partIndex ];
CVF_ASSERT ( elementIdToIdxMap . size () > 0 );
2015-10-23 15:46:25 +02:00
int numBlocks = seqFieldBulkData . size ();
for ( int block = 0 ; block < numBlocks ; block ++ )
{
const odb_FieldBulkData & bulkData = seqFieldBulkData [ block ];
2015-06-12 14:33:55 +02:00
RifOdbBulkDataGetter bulkDataGetter ( bulkData );
2015-10-23 15:46:25 +02:00
int numValues = bulkData . length ();
int numComp = bulkData . width ();
2015-06-12 14:33:55 +02:00
int elemCount = bulkData . numberOfElements ();
2015-10-23 15:46:25 +02:00
int elemNodeCount = numValues / elemCount ;
int * elementLabels = bulkData . elementLabels ();
2015-06-12 14:33:55 +02:00
float * data = bulkDataGetter . data ();
for ( int elem = 0 ; elem < elemCount ; elem ++ )
{
2015-06-12 18:41:47 +02:00
int elementIdx = elementIdToIdxMap [ elementLabels [ elem * elemNodeCount ]];
int elementResultStartDestIdx = elementIdx * elemNodeCount ; // Ikke generellt riktig !
int elementResultStartSourceIdx = elem * elemNodeCount * numComp ;
2015-06-12 14:33:55 +02:00
2015-06-12 18:41:47 +02:00
for ( int elemNode = 0 ; elemNode < elemNodeCount ; elemNode ++ )
2015-06-12 14:33:55 +02:00
{
2015-06-12 18:41:47 +02:00
int destIdx = elementResultStartDestIdx + elemNode ;
int srcIdx = elementResultStartSourceIdx + elemNode * numComp ;
2015-06-12 14:33:55 +02:00
for ( int comp = 0 ; comp < numComp ; comp ++ )
{
( * ( * resultValues )[ comp ])[ destIdx ] = data [ srcIdx + comp ];
}
}
}
2015-10-23 15:46:25 +02:00
}
2015-06-12 14:33:55 +02:00
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void RifOdbReader :: readIntegrationPointField ( const std :: string & fieldName , int partIndex , int stepIndex , int frameIndex , std :: vector < std :: vector < float >*>* resultValues )
{
CVF_ASSERT ( resultValues );
odb_Instance * partInstance = instance ( partIndex );
CVF_ASSERT ( partInstance != NULL );
size_t compCount = componentsCount ( fieldName , INTEGRATION_POINT );
CVF_ASSERT ( compCount == resultValues -> size ());
2015-06-12 20:02:35 +02:00
size_t dataSize = resultItemCount ( fieldName , partIndex , stepIndex , frameIndex );
2015-10-23 15:46:25 +02:00
if ( dataSize > 0 )
{
2015-06-12 14:33:55 +02:00
for ( int comp = 0 ; comp < compCount ; comp ++ )
2015-10-23 15:46:25 +02:00
{
2015-06-12 14:33:55 +02:00
CVF_ASSERT (( * resultValues )[ comp ]);
2015-10-23 15:46:25 +02:00
( * resultValues )[ comp ] -> resize ( dataSize , std :: numeric_limits < float >:: infinity ());
2015-06-12 14:33:55 +02:00
}
2015-10-23 15:46:25 +02:00
}
2015-06-12 14:33:55 +02:00
2015-10-23 15:46:25 +02:00
const odb_Frame & frame = stepFrame ( stepIndex , frameIndex );
const odb_FieldOutput & instanceFieldOutput = frame . fieldOutputs ()[ fieldName . c_str ()]. getSubset ( * partInstance );
2015-06-12 18:41:47 +02:00
const odb_FieldOutput & fieldOutput = instanceFieldOutput . getSubset ( odb_Enum :: INTEGRATION_POINT );
2015-10-23 15:46:25 +02:00
const odb_SequenceFieldBulkData & seqFieldBulkData = fieldOutput . bulkDataBlocks ();
2015-06-12 14:33:55 +02:00
std :: map < int , int >& elementIdToIdxMap = m_elementIdToIdxMaps [ partIndex ];
CVF_ASSERT ( elementIdToIdxMap . size () > 0 );
2015-10-23 15:46:25 +02:00
int numBlocks = seqFieldBulkData . size ();
for ( int block = 0 ; block < numBlocks ; block ++ )
{
const odb_FieldBulkData & bulkData = seqFieldBulkData [ block ];
2015-06-12 14:33:55 +02:00
RifOdbBulkDataGetter bulkDataGetter ( bulkData );
2015-10-23 15:46:25 +02:00
int numValues = bulkData . length ();
int numComp = bulkData . width ();
2015-06-12 14:33:55 +02:00
int elemCount = bulkData . numberOfElements ();
2015-10-23 15:46:25 +02:00
int ipCount = numValues / elemCount ;
int * elementLabels = bulkData . elementLabels ();
2015-06-12 14:33:55 +02:00
float * data = bulkDataGetter . data ();
RigElementType eType = toRigElementType ( bulkData . baseElementType ());
2015-11-02 07:57:33 +01:00
const int * elmNodeToIpResultMapping = localElmNodeToIntegrationPointMapping ( eType ); // Todo: Use the one in RigFemTypes.h, but we need to guard against unknown element types first.
2015-06-12 14:33:55 +02:00
if ( ! elmNodeToIpResultMapping ) continue ;
for ( int elem = 0 ; elem < elemCount ; elem ++ )
{
int elementIdx = elementIdToIdxMap [ elementLabels [ elem * ipCount ]];
int elementResultStartDestIdx = elementIdx * ipCount ; // Ikke generellt riktig !
int elementResultStartSourceIdx = elem * ipCount * numComp ;
for ( int ipIdx = 0 ; ipIdx < ipCount ; ipIdx ++ )
{
int resultIpIdx = elmNodeToIpResultMapping [ ipIdx ];
int destIdx = elementResultStartDestIdx + ipIdx ;
int srcIdx = elementResultStartSourceIdx + resultIpIdx * numComp ;
for ( int comp = 0 ; comp < numComp ; comp ++ )
{
( * ( * resultValues )[ comp ])[ destIdx ] = data [ srcIdx + comp ];
}
}
}
2015-10-23 15:46:25 +02:00
}
2015-06-12 14:33:55 +02:00
}