///////////////////////////////////////////////////////////////////////////////// // // 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 // for more details. // ///////////////////////////////////////////////////////////////////////////////// #ifdef _MSC_VER // Get rid of warnings from compilation of ODB API #pragma warning( push ) #pragma warning( disable : 4018 ) #pragma warning( disable : 4482 ) #pragma warning( disable : 4584 ) #pragma warning( disable : 4800 ) #endif #include #include #ifdef _MSC_VER #pragma warning( pop ) #endif #include "RifOdbReader.h" #include "RigFemPart.h" #include "RigFemPartCollection.h" #include "cafProgressInfo.h" #include #include #include #include #include //================================================================================================== // // Helper class to ensure that ODB bulk data are returned as float. Converting if necessary. // //================================================================================================== class RifOdbBulkDataGetter { public: explicit RifOdbBulkDataGetter( const odb_FieldBulkData& bulkData ) : m_bulkData( bulkData ){}; virtual ~RifOdbBulkDataGetter(){}; float* data() { 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 ) { 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]; } } return m_data.data(); } // Should never end up here CVF_ASSERT( 0 ); return NULL; } private: const odb_FieldBulkData& m_bulkData; std::vector m_data; }; size_t RifOdbReader::sm_instanceCount = 0; //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map initFemTypeMap() { std::map typeMap; typeMap["C3D8R"] = HEX8; typeMap["C3D8"] = HEX8; typeMap["C3D8P"] = HEX8P; typeMap["CAX4"] = CAX4; return typeMap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RigElementType toRigElementType( const odb_String& odbTypeName ) { static std::map odbElmTypeToRigElmTypeMap = initFemTypeMap(); std::map::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; } return it->second; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const int* localElmNodeToIntegrationPointMapping( RigElementType elmType ) { static const int HEX8_Mapping[8] = {0, 1, 3, 2, 4, 5, 7, 6}; switch ( elmType ) { case HEX8: case HEX8P: return HEX8_Mapping; break; case CAX4: return HEX8_Mapping; // First four is identical to HEX8 break; default: // assert(false); // Element type not supported break; } return NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifOdbReader::RifOdbReader() { if ( ++sm_instanceCount == 1 ) { odb_initializeAPI(); } m_odb = NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- RifOdbReader::~RifOdbReader() { close(); if ( --sm_instanceCount == 0 ) { odb_finalizeAPI(); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::close() { if ( m_odb ) { m_odb->close(); m_odb = NULL; } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RifOdbReader::openFile( const std::string& fileName, std::string* errorMessage ) { close(); CVF_ASSERT( m_odb == NULL ); odb_String path = fileName.c_str(); try { m_odb = &openOdb( path, true ); } catch ( const nex_Exception& nex ) { if ( errorMessage ) { *errorMessage = nex.UserReport().CStr(); } return false; } catch ( ... ) { if ( errorMessage ) { std::stringstream errStr; errStr << "Unable to open file '" << fileName << "'."; *errorMessage = errStr.str(); } return false; } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RifOdbReader::isOpen() const { return m_odb != NULL; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::assertMetaDataLoaded() { CVF_ASSERT( m_odb != NULL ); if ( m_resultsMetaData.empty() ) { m_resultsMetaData = readResultsMetaData( m_odb ); } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RifOdbReader::readResultsMetaData( odb_Odb* odb ) { CVF_ASSERT( odb != NULL ); std::map> resultsMap; const odb_StepRepository& stepRepository = odb->steps(); odb_StepRepositoryIT stepIt( stepRepository ); stepIt.first(); const odb_Step& step = stepRepository.constGet( stepIt.currentKey() ); const odb_SequenceFrame& stepFrames = step.frames(); if ( stepFrames.size() > 1 ) { // Optimization: Get results metadata for the second frame of the first step only 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 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: resultsMap[RifOdbResultKey( NODAL, fieldName )] = compVec; break; case odb_Enum::ELEMENT_NODAL: resultsMap[RifOdbResultKey( ELEMENT_NODAL, fieldName )] = compVec; break; case odb_Enum::INTEGRATION_POINT: resultsMap[RifOdbResultKey( INTEGRATION_POINT, fieldName )] = compVec; resultsMap[RifOdbResultKey( ELEMENT_NODAL, fieldName )] = compVec; break; default: break; } } } } stepFrames.release(); return resultsMap; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool RifOdbReader::readFemParts( RigFemPartCollection* femParts ) { CVF_ASSERT( femParts ); CVF_ASSERT( m_odb != NULL ); odb_InstanceRepository instanceRepository = m_odb->rootAssembly().instances(); odb_InstanceRepositoryIT iter( instanceRepository ); caf::ProgressInfo modelProgress( instanceRepository.size() * ( 2 + 4 ), "Reading Odb Parts" ); int instanceCount = 0; for ( iter.first(); !iter.isDone(); iter.next(), instanceCount++ ) { modelProgress.setProgressDescription( QString( iter.currentKey().cStr() ) + ": Reading Nodes" ); m_nodeIdToIdxMaps.push_back( std::map() ); odb_Instance& inst = instanceRepository[iter.currentKey()]; RigFemPart* femPart = new RigFemPart; // Extract nodes const odb_SequenceNode& odbNodes = inst.nodes(); std::map& nodeIdToIdxMap = m_nodeIdToIdxMaps.back(); 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; // Progress reporting if ( nIdx == nodeCount / 2 ) { modelProgress.incrementProgress(); } } modelProgress.incrementProgress(); modelProgress.setProgressDescription( QString( iter.currentKey().cStr() ) + ": Reading Elements" ); // Extract elements const odb_SequenceElement& elements = inst.elements(); int elmCount = elements.size(); femPart->preAllocateElementStorage( elmCount ); std::vector indexBasedConnectivities; m_elementIdToIdxMaps.push_back( std::map() ); std::map& elementIdToIdxMap = m_elementIdToIdxMaps.back(); for ( int elmIdx = 0; elmIdx < elmCount; ++elmIdx ) { const odb_Element odbElm = elements.element( elmIdx ); elementIdToIdxMap[odbElm.label()] = elmIdx; RigElementType elmType = toRigElementType( odbElm.type() ); if ( elmType == UNKNOWN_ELM_TYPE ) continue; 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() ); // Progress reporting if ( elmIdx == elmCount / 4 || elmIdx == elmCount / 2 || elmIdx == 3 * elmCount / 4 ) { modelProgress.incrementProgress(); } } femPart->setElementPartId( femParts->partCount() ); femParts->addFemPart( femPart ); modelProgress.incrementProgress(); } return true; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::allStepNames() const { CVF_ASSERT( m_odb != NULL ); std::vector stepNames; odb_StepRepository stepRepository = m_odb->steps(); odb_StepRepositoryIT sIter( stepRepository ); for ( sIter.first(); !sIter.isDone(); sIter.next() ) { std::string stepName( sIter.currentValue().name().CStr() ); stepNames.push_back( stepName ); } return stepNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::filteredStepNames() const { CVF_ASSERT( m_odb != NULL ); std::vector stepNames; odb_StepRepository stepRepository = m_odb->steps(); odb_StepRepositoryIT sIter( stepRepository ); int stepIndex = 0; for ( sIter.first(); !sIter.isDone(); sIter.next() ) { std::string stepName( sIter.currentValue().name().CStr() ); if ( this->isTimeStepIncludedByFilter( stepIndex++ ) ) { stepNames.push_back( stepName ); } } return stepNames; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::frameTimes( int stepIndex ) const { CVF_ASSERT( m_odb != NULL ); odb_StepRepository& stepRepository = m_odb->steps(); odb_StepList stepList = stepRepository.stepList(); int stepFileIndex = this->timeStepIndexOnFile( stepIndex ); odb_Step& step = stepList.Get( stepFileIndex ); odb_SequenceFrame& stepFrames = step.frames(); std::vector frameValues; int numFrames = stepFrames.size(); for ( int f = 0; f < numFrames; f++ ) { odb_Frame frame = stepFrames.constGet( f ); frameValues.push_back( frame.frameValue() ); } return frameValues; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::elementSetNames( int partIndex ) { CVF_ASSERT( m_odb != NULL ); std::map>::const_iterator mapIt = m_partElementSetNames.find( partIndex ); if ( mapIt == m_partElementSetNames.end() ) { std::vector setNames; const odb_Assembly& rootAssembly = m_odb->constRootAssembly(); const odb_InstanceRepository& instances = rootAssembly.instances(); int currentInstance = 0; odb_InstanceRepositoryIT instIt( instances ); for ( instIt.first(); !instIt.isDone(); instIt.next(), currentInstance++ ) { const odb_Instance& instance = instIt.currentValue(); if ( currentInstance == partIndex ) { const odb_SetRepository& sets = rootAssembly.elementSets(); odb_SetRepositoryIT setIt( sets ); for ( setIt.first(); !setIt.isDone(); setIt.next() ) { const odb_Set& set = setIt.currentValue(); setNames.push_back( set.name().CStr() ); } break; } } m_partElementSetNames[partIndex] = setNames; } return m_partElementSetNames.at( partIndex ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::elementSet( int partIndex, int setIndex ) { CVF_ASSERT( m_odb != NULL ); std::vector 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(); const odb_SequenceElement& setElements = set.elements( instanceNames[partIndex] ); int elementCount = setElements.size(); std::vector elementIndexes; elementIndexes.resize( elementCount ); for ( int i = 0; i < elementCount; i++ ) { elementIndexes[i] = setElements.element( i ).index(); } return elementIndexes; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RifOdbReader::scalarNodeFieldAndComponentNames() { return fieldAndComponentNames( NODAL ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RifOdbReader::scalarElementNodeFieldAndComponentNames() { return fieldAndComponentNames( ELEMENT_NODAL ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RifOdbReader::scalarIntegrationPointFieldAndComponentNames() { return fieldAndComponentNames( INTEGRATION_POINT ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- const odb_Frame& RifOdbReader::stepFrame( int stepIndex, int frameIndex ) const { CVF_ASSERT( m_odb ); const odb_StepRepository& stepRepository = m_odb->steps(); const odb_StepList& stepList = stepRepository.stepList(); int stepFileIndex = this->timeStepIndexOnFile( stepIndex ); const odb_Step& step = stepList.ConstGet( stepFileIndex ); const odb_SequenceFrame& stepFrames = step.frames(); return stepFrames.constGet( frameIndex ); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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; } //-------------------------------------------------------------------------------------------------- /// Get the number of result items (== #nodes or #elements) //-------------------------------------------------------------------------------------------------- size_t RifOdbReader::resultItemCount( const std::string& fieldName, int partIndex, int stepIndex, int frameIndex ) { odb_Instance* partInstance = instance( partIndex ); CVF_ASSERT( partInstance != NULL ); const odb_Frame& frame = stepFrame( stepIndex, frameIndex ); const odb_FieldOutput& instanceFieldOutput = frame.fieldOutputs()[fieldName.c_str()].getSubset( *partInstance ); const odb_SequenceFieldBulkData& seqFieldBulkData = instanceFieldOutput.bulkDataBlocks(); size_t resultItemCount = 0; int numBlocks = seqFieldBulkData.size(); for ( int block = 0; block < numBlocks; block++ ) { const odb_FieldBulkData& bulkData = seqFieldBulkData[block]; resultItemCount += bulkData.length(); } return resultItemCount; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- size_t RifOdbReader::componentsCount( const std::string& fieldName, ResultPosition position ) { std::vector compNames = componentNames( RifOdbResultKey( position, fieldName ) ); return compNames.size() > 0 ? compNames.size() : 1; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::vector RifOdbReader::componentNames( const RifOdbResultKey& result ) { assertMetaDataLoaded(); std::map>::const_iterator resMapIt = m_resultsMetaData.find( result ); if ( resMapIt != m_resultsMetaData.end() ) { std::vector compNames; compNames = resMapIt->second; return compNames; } CVF_ASSERT( false ); return std::vector(); } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- std::map> RifOdbReader::fieldAndComponentNames( ResultPosition position ) { assertMetaDataLoaded(); std::map> fieldsAndComponents; std::map>::const_iterator resMapIt; for ( resMapIt = m_resultsMetaData.begin(); resMapIt != m_resultsMetaData.end(); ++resMapIt ) { if ( resMapIt->first.resultPostion == position ) { fieldsAndComponents[resMapIt->first.fieldName] = resMapIt->second; } } return fieldsAndComponents; } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::readDisplacements( int partIndex, int stepIndex, int frameIndex, std::vector* displacements ) { CVF_ASSERT( displacements ); odb_Instance* partInstance = instance( partIndex ); CVF_ASSERT( partInstance != NULL ); 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]; RifOdbBulkDataGetter bulkDataGetter( bulkData ); if ( bulkData.numberOfNodes() > 0 ) { int numNodes = bulkData.length(); int numComp = bulkData.width(); float* data = bulkDataGetter.data(); for ( int i = 0; i < numNodes; i++ ) { ( *displacements )[i + dataIndex].set( data[i * numComp], data[i * numComp + 1], data[i * numComp + 2] ); } dataIndex += numNodes * numComp; } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::readNodeField( const std::string& fieldName, int partIndex, int stepIndex, int frameIndex, std::vector*>* resultValues ) { CVF_ASSERT( resultValues ); odb_Instance* partInstance = instance( partIndex ); CVF_ASSERT( partInstance != NULL ); size_t compCount = componentsCount( fieldName, NODAL ); CVF_ASSERT( compCount == resultValues->size() ); std::map& nodeIdToIdxMap = m_nodeIdToIdxMaps[partIndex]; size_t dataSize = nodeIdToIdxMap.size(); if ( dataSize > 0 ) { for ( int comp = 0; comp < compCount; comp++ ) { CVF_ASSERT( ( *resultValues )[comp] ); ( *resultValues )[comp]->resize( dataSize, std::numeric_limits::infinity() ); } } const odb_Frame& frame = stepFrame( stepIndex, frameIndex ); const odb_FieldOutput& instanceFieldOutput = frame.fieldOutputs()[fieldName.c_str()].getSubset( *partInstance ); const odb_FieldOutput& fieldOutput = instanceFieldOutput.getSubset( odb_Enum::NODAL ); const odb_SequenceFieldBulkData& seqFieldBulkData = fieldOutput.bulkDataBlocks(); int numBlocks = seqFieldBulkData.size(); for ( int block = 0; block < numBlocks; block++ ) { const odb_FieldBulkData& bulkData = seqFieldBulkData[block]; RifOdbBulkDataGetter bulkDataGetter( bulkData ); int numNodes = bulkData.length(); int numComp = bulkData.width(); int* nodeLabels = bulkData.nodeLabels(); float* data = bulkDataGetter.data(); for ( int nIdx = 0; nIdx < numNodes; nIdx++ ) { for ( int comp = 0; comp < numComp; comp++ ) { std::vector* singleComponentValues = ( *resultValues )[comp]; ( *singleComponentValues )[nodeIdToIdxMap[nodeLabels[nIdx]]] = data[nIdx * numComp + comp]; } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::readElementNodeField( const std::string& fieldName, int partIndex, int stepIndex, int frameIndex, std::vector*>* resultValues ) { CVF_ASSERT( resultValues ); odb_Instance* partInstance = instance( partIndex ); CVF_ASSERT( partInstance != NULL ); size_t compCount = componentsCount( fieldName, ELEMENT_NODAL ); CVF_ASSERT( compCount == resultValues->size() ); size_t dataSize = resultItemCount( fieldName, partIndex, stepIndex, frameIndex ); if ( dataSize > 0 ) { for ( int comp = 0; comp < compCount; comp++ ) { CVF_ASSERT( ( *resultValues )[comp] ); ( *resultValues )[comp]->resize( dataSize, std::numeric_limits::infinity() ); } } const odb_Frame& frame = stepFrame( stepIndex, frameIndex ); const odb_FieldOutput& instanceFieldOutput = frame.fieldOutputs()[fieldName.c_str()].getSubset( *partInstance ); const odb_FieldOutput& fieldOutput = instanceFieldOutput.getSubset( odb_Enum::ELEMENT_NODAL ); const odb_SequenceFieldBulkData& seqFieldBulkData = fieldOutput.bulkDataBlocks(); std::map& elementIdToIdxMap = m_elementIdToIdxMaps[partIndex]; CVF_ASSERT( elementIdToIdxMap.size() > 0 ); int numBlocks = seqFieldBulkData.size(); for ( int block = 0; block < numBlocks; block++ ) { const odb_FieldBulkData& bulkData = seqFieldBulkData[block]; RifOdbBulkDataGetter bulkDataGetter( bulkData ); int numValues = bulkData.length(); int numComp = bulkData.width(); int elemCount = bulkData.numberOfElements(); int elemNodeCount = numValues / elemCount; int* elementLabels = bulkData.elementLabels(); float* data = bulkDataGetter.data(); for ( int elem = 0; elem < elemCount; elem++ ) { int elementIdx = elementIdToIdxMap[elementLabels[elem * elemNodeCount]]; int elementResultStartDestIdx = elementIdx * elemNodeCount; // Ikke generellt riktig ! int elementResultStartSourceIdx = elem * elemNodeCount * numComp; for ( int elemNode = 0; elemNode < elemNodeCount; elemNode++ ) { int destIdx = elementResultStartDestIdx + elemNode; int srcIdx = elementResultStartSourceIdx + elemNode * numComp; for ( int comp = 0; comp < numComp; comp++ ) { ( *( *resultValues )[comp] )[destIdx] = data[srcIdx + comp]; } } } } } //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void RifOdbReader::readIntegrationPointField( const std::string& fieldName, int partIndex, int stepIndex, int frameIndex, std::vector*>* 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() ); size_t dataSize = resultItemCount( fieldName, partIndex, stepIndex, frameIndex ); if ( dataSize > 0 ) { for ( int comp = 0; comp < compCount; comp++ ) { CVF_ASSERT( ( *resultValues )[comp] ); ( *resultValues )[comp]->resize( dataSize, std::numeric_limits::infinity() ); } } const odb_Frame& frame = stepFrame( stepIndex, frameIndex ); const odb_FieldOutput& instanceFieldOutput = frame.fieldOutputs()[fieldName.c_str()].getSubset( *partInstance ); const odb_FieldOutput& fieldOutput = instanceFieldOutput.getSubset( odb_Enum::INTEGRATION_POINT ); const odb_SequenceFieldBulkData& seqFieldBulkData = fieldOutput.bulkDataBlocks(); std::map& elementIdToIdxMap = m_elementIdToIdxMaps[partIndex]; CVF_ASSERT( elementIdToIdxMap.size() > 0 ); int numBlocks = seqFieldBulkData.size(); for ( int block = 0; block < numBlocks; block++ ) { const odb_FieldBulkData& bulkData = seqFieldBulkData[block]; RifOdbBulkDataGetter bulkDataGetter( bulkData ); int numValues = bulkData.length(); int numComp = bulkData.width(); int elemCount = bulkData.numberOfElements(); int ipCount = numValues / elemCount; int* elementLabels = bulkData.elementLabels(); float* data = bulkDataGetter.data(); RigElementType eType = toRigElementType( bulkData.baseElementType() ); const int* elmNodeToIpResultMapping = localElmNodeToIntegrationPointMapping( eType ); // Todo: Use the one in RigFemTypes.h, but we need to guard // against unknown element types first. 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]; } } } } }