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/nmSubWxs/nmReservoirPropertiesSessio...

322 lines
12 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "nmReservoirPropertiesSession.h"
#include "nmAttrRegistry.h"
#include "nmDataAttribute.h"
#include "rapidjson/document.h"
namespace
{
/** @brief 比较两个QVariant数值保留字符串和整数的精确语义。 */
bool sameValue(const QVariant& oLeft, const QVariant& oRight)
{
return oLeft == oRight;
}
template<typename T>
bool sameDataObject(const T& oLeft, const T& oRight)
{
rapidjson::Document oLeftDocument;
rapidjson::Document oRightDocument;
rapidjson::Value oLeftValue = oLeft.ToJsonValue(
oLeftDocument.GetAllocator());
rapidjson::Value oRightValue = oRight.ToJsonValue(
oRightDocument.GetAllocator());
return oLeftValue == oRightValue;
}
template<typename T>
bool sameDataVector(const QVector<T>& vecLeft, const QVector<T>& vecRight)
{
if(vecLeft.size() != vecRight.size()) {
return false;
}
for(int nIndex = 0; nIndex < vecLeft.size(); ++nIndex) {
if(!sameDataObject(vecLeft[nIndex], vecRight[nIndex])) {
return false;
}
}
return true;
}
/** @brief 比较两口井的平面位置。 */
bool sameWellPosition(nmDataWellBase& oLeft, nmDataWellBase& oRight)
{
return sameValue(oLeft.getX().getValue(), oRight.getX().getValue()) &&
sameValue(oLeft.getY().getValue(), oRight.getY().getValue());
}
}
nmReservoirPropertiesSession::nmReservoirPropertiesSession(
nmIReservoirPropertiesDataSource* pDataSource)
: m_pDataSource(pDataSource),
m_pAttrRegistry(new nmAttrRegistry),
m_bInitialized(false)
{
}
nmReservoirPropertiesSession::~nmReservoirPropertiesSession()
{
delete m_pAttrRegistry;
m_pAttrRegistry = nullptr;
m_pDataSource = nullptr;
}
bool nmReservoirPropertiesSession::initialize(QString& sError)
{
// 第一步:读取一次真实数据,作为取消和变更检测的基线。
if (m_pDataSource == nullptr ||
!m_pDataSource->loadSnapshot(m_oOriginalSnapshot, sError))
{
m_bInitialized = false;
return false;
}
// 第二步:复制出独立工作副本,后续界面修改只写入此对象。
m_oWorkingSnapshot = m_oOriginalSnapshot;
nmReservoirParameterCatalog::registerSnapshot(m_pAttrRegistry,
m_oWorkingSnapshot);
m_bInitialized = true;
sError.clear();
return true;
}
QList<nmReservoirPropertyObjectInfo> nmReservoirPropertiesSession::objectInfos(
nmReservoirPropertiesCategory eCategory)
{
if (!m_bInitialized)
{
return QList<nmReservoirPropertyObjectInfo>();
}
return nmReservoirParameterCatalog::createObjectInfos(eCategory,
m_oWorkingSnapshot);
}
QVariant nmReservoirPropertiesSession::value(const QString& sParameterId) const
{
if (!m_bInitialized || m_pAttrRegistry == nullptr)
{
return QVariant();
}
QStringList listIds;
listIds << sParameterId;
return m_pAttrRegistry->collect(listIds).value(sParameterId, QVariant());
}
bool nmReservoirPropertiesSession::setValue(const QString& sParameterId,
const QVariant& oValue)
{
if (!m_bInitialized || m_pAttrRegistry == nullptr ||
!m_pAttrRegistry->registeredNames().contains(sParameterId))
{
return false;
}
if (sameValue(value(sParameterId), oValue))
{
return true;
}
m_pAttrRegistry->setValue(sParameterId, oValue);
return true;
}
void nmReservoirPropertiesSession::setValues(
const QMap<QString, QVariant>& mapValues)
{
QMap<QString, QVariant>::const_iterator oIterator = mapValues.constBegin();
for (; oIterator != mapValues.constEnd(); ++oIterator)
{
setValue(oIterator.key(), oIterator.value());
}
}
QString nmReservoirPropertiesSession::enumCode(const QString& sParameterId) const
{
if (!m_bInitialized)
{
return QString();
}
return nmReservoirParameterCatalog::enumCode(m_oWorkingSnapshot,
sParameterId);
}
bool nmReservoirPropertiesSession::setEnumCode(const QString& sParameterId,
const QString& sCode)
{
if (!m_bInitialized)
{
return false;
}
if (enumCode(sParameterId) == sCode)
{
return true;
}
if (!nmReservoirParameterCatalog::setEnumCode(m_oWorkingSnapshot,
sParameterId,
sCode))
{
return false;
}
return true;
}
bool nmReservoirPropertiesSession::commit(QString& sError)
{
if (!m_bInitialized || m_pDataSource == nullptr)
{
sError = QObject::tr("The reservoir properties editing session is unavailable.");
return false;
}
// 第一步:几何变化优先级最高;其他正式输入只推进结果版本。
NM_PEBI_INPUT_CHANGE eInputChange = NM_PEBI_INPUT_UNCHANGED;
if (isGeometryChanged())
{
eInputChange = NM_PEBI_GRID_INPUT_CHANGED;
}
else if (isInputChanged())
{
eInputChange = NM_PEBI_RESULT_INPUT_CHANGED;
}
// 第二步:将完整工作副本一次性交给数据源;失败时继续保留当前编辑内容。
if (!m_pDataSource->commitSnapshot(m_oWorkingSnapshot,
eInputChange,
sError))
{
return false;
}
// 第三步:提交成功后更新基线,防止同一会话重复识别旧变更。
m_oOriginalSnapshot = m_oWorkingSnapshot;
sError.clear();
return true;
}
const nmReservoirPropertiesSnapshot&
nmReservoirPropertiesSession::workingSnapshot() const
{
return m_oWorkingSnapshot;
}
bool nmReservoirPropertiesSession::isInputChanged() const
{
// 完整结构化比较覆盖数值、枚举和批量导入,不依赖具体界面入口。
return m_oOriginalSnapshot.m_nSolverModelType !=
m_oWorkingSnapshot.m_nSolverModelType ||
!sameDataObject(m_oOriginalSnapshot.m_oReservoir,
m_oWorkingSnapshot.m_oReservoir) ||
!sameDataVector(m_oOriginalSnapshot.m_vecVerticalWells,
m_oWorkingSnapshot.m_vecVerticalWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecVerticalFracturedWells,
m_oWorkingSnapshot.m_vecVerticalFracturedWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecHorizontalFracturedWells,
m_oWorkingSnapshot.m_vecHorizontalFracturedWells) ||
!sameDataVector(m_oOriginalSnapshot.m_vecRegionMarks,
m_oWorkingSnapshot.m_vecRegionMarks) ||
!sameDataVector(m_oOriginalSnapshot.m_vecFaults,
m_oWorkingSnapshot.m_vecFaults) ||
!sameDataVector(m_oOriginalSnapshot.m_vecFractures,
m_oWorkingSnapshot.m_vecFractures) ||
!sameDataVector(m_oOriginalSnapshot.m_vecRegions,
m_oWorkingSnapshot.m_vecRegions);
}
bool nmReservoirPropertiesSession::isGeometryChanged() const
{
// 第一步:对象数量变化视为几何变化,虽然当前对话框本身不提供增删操作。
if (m_oOriginalSnapshot.m_vecVerticalWells.size() !=
m_oWorkingSnapshot.m_vecVerticalWells.size() ||
m_oOriginalSnapshot.m_vecVerticalFracturedWells.size() !=
m_oWorkingSnapshot.m_vecVerticalFracturedWells.size() ||
m_oOriginalSnapshot.m_vecHorizontalFracturedWells.size() !=
m_oWorkingSnapshot.m_vecHorizontalFracturedWells.size())
{
return true;
}
// 第二步:比较三类井的位置和井径。
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecVerticalWells.size(); ++nIndex)
{
nmDataVerticalWell& oOriginal =
const_cast<nmDataVerticalWell&>(m_oOriginalSnapshot.m_vecVerticalWells[nIndex]);
nmDataVerticalWell& oWorking =
const_cast<nmDataVerticalWell&>(m_oWorkingSnapshot.m_vecVerticalWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getRadius().getValue(),
oWorking.getRadius().getValue()))
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecVerticalFracturedWells.size(); ++nIndex)
{
nmDataVerticalFracturedWell& oOriginal = const_cast<nmDataVerticalFracturedWell&>(
m_oOriginalSnapshot.m_vecVerticalFracturedWells[nIndex]);
nmDataVerticalFracturedWell& oWorking = const_cast<nmDataVerticalFracturedWell&>(
m_oWorkingSnapshot.m_vecVerticalFracturedWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getFractureHalfLength().getValue(),
oWorking.getFractureHalfLength().getValue()) ||
!sameValue(oOriginal.getFractureAngle().getValue(),
oWorking.getFractureAngle().getValue()) ||
!sameValue(oOriginal.getWidth().getValue(),
oWorking.getWidth().getValue()) ||
!sameValue(oOriginal.getDfc().getValue(),
oWorking.getDfc().getValue()))
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecHorizontalFracturedWells.size(); ++nIndex)
{
nmDataHorizontalFracturedWell& oOriginal =
const_cast<nmDataHorizontalFracturedWell&>(
m_oOriginalSnapshot.m_vecHorizontalFracturedWells[nIndex]);
nmDataHorizontalFracturedWell& oWorking =
const_cast<nmDataHorizontalFracturedWell&>(
m_oWorkingSnapshot.m_vecHorizontalFracturedWells[nIndex]);
if (!sameWellPosition(oOriginal, oWorking) ||
!sameValue(oOriginal.getWellLength().getValue(), oWorking.getWellLength().getValue()) ||
!sameValue(oOriginal.getDrainAngle().getValue(), oWorking.getDrainAngle().getValue()) ||
!sameValue(oOriginal.getNumberOfFractures().getValue(),
oWorking.getNumberOfFractures().getValue()) ||
!sameValue(oOriginal.getFractureHalfLength().getValue(),
oWorking.getFractureHalfLength().getValue()) ||
!sameValue(oOriginal.getFractureAngle().getValue(),
oWorking.getFractureAngle().getValue()) ||
!sameValue(oOriginal.getWidth().getValue(),
oWorking.getWidth().getValue()) ||
!sameValue(oOriginal.getDfc().getValue(),
oWorking.getDfc().getValue()))
{
return true;
}
}
// 第三步:断层和裂缝端点也直接参与网格,因此比较完整点坐标。
if (m_oOriginalSnapshot.m_vecFaults.size() != m_oWorkingSnapshot.m_vecFaults.size() ||
m_oOriginalSnapshot.m_vecFractures.size() != m_oWorkingSnapshot.m_vecFractures.size())
{
return true;
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecFaults.size(); ++nIndex)
{
if (m_oOriginalSnapshot.m_vecFaults[nIndex].getFaultPoints() !=
m_oWorkingSnapshot.m_vecFaults[nIndex].getFaultPoints())
{
return true;
}
}
for (int nIndex = 0; nIndex < m_oWorkingSnapshot.m_vecFractures.size(); ++nIndex)
{
if (m_oOriginalSnapshot.m_vecFractures[nIndex].getFracturePoints() !=
m_oWorkingSnapshot.m_vecFractures[nIndex].getFracturePoints())
{
return true;
}
}
return false;
}