#include "nmPebiResultSnapshot.h" #include "nmPebiCellMapping.h" #include "nmPebiResultPropertyCatalog.h" #include #include #include #include #include #include #include namespace { bool deepCopyNamedArray(vtkFieldData* pSource, vtkFieldData* pTarget, const char* pArrayName) { if(pSource == NULL || pTarget == NULL || pArrayName == NULL || pTarget->GetAbstractArray(pArrayName) != NULL) { return false; } vtkAbstractArray* pSourceArray = pSource->GetAbstractArray(pArrayName); if(pSourceArray == NULL) { return false; } vtkSmartPointer pTargetArray; pTargetArray.TakeReference(pSourceArray->NewInstance()); if(pTargetArray == NULL) { return false; } pTargetArray->DeepCopy(pSourceArray); return pTarget->AddArray(pTargetArray) >= 0 && pTarget->GetAbstractArray(pArrayName) == pTargetArray.GetPointer(); } } // VTK 结构和压力操作仅供渲染适配器调用,普通结果读取接口不暴露可写对象。 nmPebiResultSolverSlot::nmPebiResultSolverSlot() : m_nSolverIndex(-1), m_eEntryKind(NM_SolverEntry_Well), m_eWellType(Unknow_Well), m_eWellCategory(NM_WellCategory_Unknown) { } nmPebiResultWellSnapshot::nmPebiResultWellSnapshot() : m_eWellType(Unknow_Well), m_eWellCategory(NM_WellCategory_Unknown), m_eWellMode(NM_CaseWell_Observation), m_eFlowSchedulePhase(PHASE_UNKNOWN), m_nFlowSectionIndex(0), m_bUseOilRate(false), m_bUseGasRate(false), m_bUseWaterRate(false), m_bHasPerforation(false), m_bHasSkin(false), m_bHasDfc(false), m_dRadius(0.0), m_dWellboreStorage(0.0), m_dSkin(0.0), m_dDfc(0.0) { } nmPebiResultReservoirParameters::nmPebiResultReservoirParameters() : m_dInitialPressure(0.0), m_dPermeability(0.0), m_dThickness(0.0), m_dPorosity(0.0), m_dTotalCompressibility(0.0), m_dRockCompressibility(0.0), m_dOilSaturation(0.0), m_dGasSaturation(0.0), m_dWaterSaturation(0.0) { } nmPebiResultPvtParameters::nmPebiResultPvtParameters() : m_bHasBubblePoint(false), m_dBubblePoint(0.0), m_dConstantBo(0.0), m_dConstantMiuo(0.0), m_dConstantBg(0.0), m_dConstantMiug(0.0), m_dConstantBw(0.0), m_dConstantMiuw(0.0) { } nmPebiResultSolverSettings::nmPebiResultSolverSettings() : m_nSolverModelType(0), m_nPebiSolverType(0), m_nOmpThreads(0), m_nIluReuseSteps(0), m_dGridControl(0.0), m_bHasTimeStepSettings(false), m_dTimeGrowthExponent(0.0), m_dMinDeltaT(0.0), m_dMaxDeltaT(0.0) { } nmPebiResultSnapshot::PressureFrame::PressureFrame() : m_dTime(0.0) { } nmPebiResultSnapshot::nmPebiResultSnapshot() : m_sSnapshotId(QUuid::createUuid().toString() .remove('{').remove('}')), m_nGridInputRevision(0), m_nResultInputRevision(0), m_bComplete(false), m_dScalarMin(0.0), m_dScalarMax(0.0) { for(int nPropertyIndex = 0; nPropertyIndex < 3; ++nPropertyIndex) { m_aStaticRanges[nPropertyIndex][0] = 0.0; m_aStaticRanges[nPropertyIndex][1] = 0.0; } } nmPebiResultSnapshot::~nmPebiResultSnapshot() { } QString nmPebiResultSnapshot::getSnapshotId() const { return m_sSnapshotId; } quint64 nmPebiResultSnapshot::getGridInputRevision() const { return m_nGridInputRevision; } quint64 nmPebiResultSnapshot::getResultInputRevision() const { return m_nResultInputRevision; } bool nmPebiResultSnapshot::isComplete() const { return m_bComplete; } int nmPebiResultSnapshot::getSolverSlotCount() const { return m_vecSolverSlots.size(); } const nmPebiResultSolverSlot* nmPebiResultSnapshot::getSolverSlotAt( int nIndex) const { if(nIndex < 0 || nIndex >= m_vecSolverSlots.size()) { return NULL; } return &m_vecSolverSlots[nIndex]; } int nmPebiResultSnapshot::getWellCount() const { return m_vecWells.size(); } const nmPebiResultWellSnapshot* nmPebiResultSnapshot::getWellAt( int nIndex) const { if(nIndex < 0 || nIndex >= m_vecWells.size()) { return NULL; } return &m_vecWells[nIndex]; } const nmPebiResultWellSnapshot* nmPebiResultSnapshot::findWell( const QString& sWellInstanceId) const { for(int nIndex = 0; nIndex < m_vecWells.size(); ++nIndex) { if(m_vecWells[nIndex].m_sWellInstanceId == sWellInstanceId) { return &m_vecWells[nIndex]; } } return NULL; } const QStringList& nmPebiResultSnapshot::getDisplayWellInstanceIds() const { return m_listDisplayWellInstanceIds; } bool nmPebiResultSnapshot::isDisplayWell( const QString& sWellInstanceId) const { return m_listDisplayWellInstanceIds.contains(sWellInstanceId); } vtkIdType nmPebiResultSnapshot::getResultCellCount() const { return m_pResultGrid != NULL ? m_pResultGrid->GetNumberOfCells() : 0; } QStringList nmPebiResultSnapshot::getAvailablePropertyIds() const { QStringList listPropertyIds; if(!m_bComplete) { return listPropertyIds; } const QList listDescriptors = nmPebiResultPropertyCatalog::descriptors(); for(int nIndex = 0; nIndex < listDescriptors.size(); ++nIndex) { if(hasProperty(listDescriptors[nIndex].m_sPropertyId)) { listPropertyIds.append(listDescriptors[nIndex].m_sPropertyId); } } return listPropertyIds; } bool nmPebiResultSnapshot::hasProperty(const QString& sPropertyId) const { if(!m_bComplete) { return false; } if(sPropertyId == QString::fromLatin1("permeability")) { return m_pPermeability != NULL; } if(sPropertyId == QString::fromLatin1("porosity")) { return m_pPorosity != NULL; } if(sPropertyId == QString::fromLatin1("thickness")) { return m_pThickness != NULL; } if(sPropertyId == QString::fromLatin1("pressure")) { return !m_vecPressureFrames.isEmpty(); } return false; } int nmPebiResultSnapshot::getPropertyFrameCount( const QString& sPropertyId) const { if(!hasProperty(sPropertyId)) { return 0; } return sPropertyId == QString::fromLatin1("pressure") ? m_vecPressureFrames.size() : 1; } bool nmPebiResultSnapshot::getPropertyTimeAt( const QString& sPropertyId, int nFrameIndex, double& dTime) const { if(sPropertyId != QString::fromLatin1("pressure") || !hasProperty(sPropertyId) || nFrameIndex < 0 || nFrameIndex >= m_vecPressureFrames.size()) { return false; } dTime = m_vecPressureFrames[nFrameIndex].m_dTime; return true; } bool nmPebiResultSnapshot::getPropertyRange( const QString& sPropertyId, double aRange[2]) const { if(aRange == NULL || !hasProperty(sPropertyId)) { return false; } if(sPropertyId == QString::fromLatin1("permeability")) { aRange[0] = m_aStaticRanges[0][0]; aRange[1] = m_aStaticRanges[0][1]; return true; } if(sPropertyId == QString::fromLatin1("porosity")) { aRange[0] = m_aStaticRanges[1][0]; aRange[1] = m_aStaticRanges[1][1]; return true; } if(sPropertyId == QString::fromLatin1("thickness")) { aRange[0] = m_aStaticRanges[2][0]; aRange[1] = m_aStaticRanges[2][1]; return true; } aRange[0] = m_dScalarMin; aRange[1] = m_dScalarMax; return true; } int nmPebiResultSnapshot::getPressureFrameCount() const { return m_vecPressureFrames.size(); } double nmPebiResultSnapshot::getPressureTimeAt(int nIndex) const { if(nIndex < 0 || nIndex >= m_vecPressureFrames.size()) { return 0.0; } return m_vecPressureFrames[nIndex].m_dTime; } bool nmPebiResultSnapshot::getScalarRange(double aRange[2]) const { return getPropertyRange(QString::fromLatin1("pressure"), aRange); } const nmPebiResultReservoirParameters& nmPebiResultSnapshot::getReservoirParameters() const { return m_oReservoirParameters; } const nmPebiResultPvtParameters& nmPebiResultSnapshot::getPvtParameters() const { return m_oPvtParameters; } const nmPebiResultSolverSettings& nmPebiResultSnapshot::getSolverSettings() const { return m_oSolverSettings; } bool nmPebiResultSnapshot::copyResultGridStructure( vtkUnstructuredGrid* pTargetGrid) const { if(!m_bComplete || m_pResultGrid == NULL || pTargetGrid == NULL) { return false; } // CopyStructure 在当前 VTK 7.1 中共享点和单元拓扑,不复制大网格。 // 结果属性仍由受控接口按帧挂载;内部映射单独深拷贝,避免渲染端 // 修改数组时污染不可变快照。 pTargetGrid->Initialize(); pTargetGrid->CopyStructure(m_pResultGrid); pTargetGrid->GetCellData()->Initialize(); pTargetGrid->GetFieldData()->Initialize(); if(pTargetGrid->GetNumberOfCells() != m_pResultGrid->GetNumberOfCells() || !deepCopyNamedArray(m_pResultGrid->GetCellData(), pTargetGrid->GetCellData(), nmPebiCellMapping::originalCellIdArrayName()) || !deepCopyNamedArray(m_pResultGrid->GetFieldData(), pTargetGrid->GetFieldData(), nmPebiCellMapping::originalCellCountArrayName()) || pTargetGrid->GetCellData()->GetScalars() != NULL) { pTargetGrid->Initialize(); return false; } return true; } bool nmPebiResultSnapshot::bindPropertyFrame( const QString& sPropertyId, int nFrameIndex, vtkUnstructuredGrid* pTargetGrid) const { if(!m_bComplete || pTargetGrid == NULL || nFrameIndex < 0 || nFrameIndex >= getPropertyFrameCount(sPropertyId) || pTargetGrid->GetNumberOfCells() != getResultCellCount()) { return false; } vtkDoubleArray* pScalars = NULL; if(sPropertyId == QString::fromLatin1("permeability")) { pScalars = m_pPermeability.GetPointer(); } else if(sPropertyId == QString::fromLatin1("porosity")) { pScalars = m_pPorosity.GetPointer(); } else if(sPropertyId == QString::fromLatin1("thickness")) { pScalars = m_pThickness.GetPointer(); } else if(sPropertyId == QString::fromLatin1("pressure")) { pScalars = m_vecPressureFrames[nFrameIndex].m_pPressure.GetPointer(); } const QString sExpectedArrayName = sPropertyId == QString::fromLatin1("pressure") ? QString::fromLatin1("p") : sPropertyId; if(pScalars == NULL || pScalars->GetName() == NULL || QString::fromLatin1(pScalars->GetName()) != sExpectedArrayName || pScalars->GetNumberOfComponents() != 1 || pScalars->GetNumberOfTuples() != getResultCellCount()) { return false; } // 共享模式只在完整校验后替换活动数组;事后校验失败时恢复旧引用。 vtkDataArray* pPreviousScalars = pTargetGrid->GetCellData()->GetScalars(); pTargetGrid->GetCellData()->SetScalars(pScalars); if(pTargetGrid->GetCellData()->GetScalars() != pScalars) { pTargetGrid->GetCellData()->SetScalars(pPreviousScalars); return false; } pTargetGrid->Modified(); return true; } bool nmPebiResultSnapshot::copyPropertyFrame( const QString& sPropertyId, int nFrameIndex, vtkDoubleArray* pTargetScalars) const { if(!m_bComplete || pTargetScalars == NULL || nFrameIndex < 0 || nFrameIndex >= getPropertyFrameCount(sPropertyId)) { return false; } vtkDoubleArray* pSourceScalars = NULL; if(sPropertyId == QString::fromLatin1("permeability")) { pSourceScalars = m_pPermeability.GetPointer(); } else if(sPropertyId == QString::fromLatin1("porosity")) { pSourceScalars = m_pPorosity.GetPointer(); } else if(sPropertyId == QString::fromLatin1("thickness")) { pSourceScalars = m_pThickness.GetPointer(); } else if(sPropertyId == QString::fromLatin1("pressure")) { pSourceScalars = m_vecPressureFrames[nFrameIndex].m_pPressure.GetPointer(); } if(pSourceScalars == NULL) { return false; } pTargetScalars->DeepCopy(pSourceScalars); return pTargetScalars->GetNumberOfComponents() == 1 && pTargetScalars->GetNumberOfTuples() == getResultCellCount(); }