You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/Src/nmNum/nmData/nmPebiResultSnapshot.cpp

477 lines
12 KiB
C++

#include "nmPebiResultSnapshot.h"
#include "nmPebiCellMapping.h"
#include "nmPebiResultPropertyCatalog.h"
#include <vtkAbstractArray.h>
#include <vtkCellData.h>
#include <vtkDataArray.h>
#include <vtkDoubleArray.h>
#include <vtkFieldData.h>
#include <vtkUnstructuredGrid.h>
#include <QUuid>
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<vtkAbstractArray> 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<nmPebiResultPropertyDescriptor> 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();
}