|
|
|
|
@ -3541,19 +3541,11 @@ bool nmDataAnalyzeManager::isWellAvailableForResult(
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 已有结果使用求解完成时冻结的井顺序。当前参数、选井或网格变化
|
|
|
|
|
// 不能把最后一套结果中的井从结果界面移除。
|
|
|
|
|
// 已有结果使用求解完成时冻结的可显示井列表。当前参数、选井或网格变化
|
|
|
|
|
// 不能改变最后一套结果的下拉框内容,自动加入的无流量观察井也不会进入界面。
|
|
|
|
|
if(m_oNumericalAnalysisCase.hasResults()) {
|
|
|
|
|
const QVector<nmSolverWellRef> vecResultOrder =
|
|
|
|
|
m_oNumericalAnalysisCase.getResultSolverWellOrder();
|
|
|
|
|
for(int nIndex = 0; nIndex < vecResultOrder.size(); ++nIndex) {
|
|
|
|
|
const nmSolverWellRef& oWellRef = vecResultOrder[nIndex];
|
|
|
|
|
if(oWellRef.m_eEntryKind == NM_SolverEntry_Well &&
|
|
|
|
|
oWellRef.m_sWellCode == sWellCode) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
return m_oNumericalAnalysisCase
|
|
|
|
|
.getResultSelectableWellCodes().contains(sWellCode);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第一步:主分析井是结果界面的固定入口,即使当前处于关井段也必须保留。
|
|
|
|
|
@ -3562,7 +3554,7 @@ bool nmDataAnalyzeManager::isWellAvailableForResult(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第二步:其他井只有同时具备有效产量并以主动井角色参与当前求解时,
|
|
|
|
|
// 才能出现在“结果井”列表。所有无流量观察井一律只在内部保存计算结果。
|
|
|
|
|
// 才能出现在“结果井”列表。主井以外的无流量观察井只在内部保存计算结果。
|
|
|
|
|
if(pWellData->getFlowPoints().size() < 2) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@ -4109,6 +4101,7 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
|
|
QVector<nmCalculationWellRef> vecSavedIncludedWells;
|
|
|
|
|
QVector<nmSolverWellRef> vecSavedSolverOrder;
|
|
|
|
|
QVector<nmSolverWellRef> vecSavedResultSolverOrder;
|
|
|
|
|
QStringList listSavedResultSelectableWellCodes;
|
|
|
|
|
|
|
|
|
|
// 第一步:版本 2 必须完整保存分析方案,缺字段时不再按旧项目规则猜测。
|
|
|
|
|
if(!doc.HasMember("NumericalAnalysisCase") ||
|
|
|
|
|
@ -4310,14 +4303,17 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
|
|
const bool bHasAnyResultStateField =
|
|
|
|
|
oCaseJson.HasMember("ResultsAvailable") ||
|
|
|
|
|
oCaseJson.HasMember("ResultsCurrent") ||
|
|
|
|
|
oCaseJson.HasMember("ResultSolverWellOrder");
|
|
|
|
|
oCaseJson.HasMember("ResultSolverWellOrder") ||
|
|
|
|
|
oCaseJson.HasMember("ResultSelectableWellCodes");
|
|
|
|
|
const bool bHasCompleteResultState =
|
|
|
|
|
oCaseJson.HasMember("ResultsAvailable") &&
|
|
|
|
|
oCaseJson["ResultsAvailable"].IsBool() &&
|
|
|
|
|
oCaseJson.HasMember("ResultsCurrent") &&
|
|
|
|
|
oCaseJson["ResultsCurrent"].IsBool() &&
|
|
|
|
|
oCaseJson.HasMember("ResultSolverWellOrder") &&
|
|
|
|
|
oCaseJson["ResultSolverWellOrder"].IsArray();
|
|
|
|
|
oCaseJson["ResultSolverWellOrder"].IsArray() &&
|
|
|
|
|
(!oCaseJson.HasMember("ResultSelectableWellCodes") ||
|
|
|
|
|
oCaseJson["ResultSelectableWellCodes"].IsArray());
|
|
|
|
|
if(bHasAnyResultStateField && !bHasCompleteResultState) {
|
|
|
|
|
qWarning() << "Numerical result state contains invalid fields:"
|
|
|
|
|
<< filePath;
|
|
|
|
|
@ -4393,6 +4389,34 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
|
|
sWellCode, eEntryKind));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool bHasSelectableWellCodes =
|
|
|
|
|
oCaseJson.HasMember("ResultSelectableWellCodes");
|
|
|
|
|
if(bHasSelectableWellCodes) {
|
|
|
|
|
QSet<QString> setSelectableWellCodes;
|
|
|
|
|
const rapidjson::Value& vecSelectableWellCodesJson =
|
|
|
|
|
oCaseJson["ResultSelectableWellCodes"];
|
|
|
|
|
for(rapidjson::SizeType nIndex = 0;
|
|
|
|
|
nIndex < vecSelectableWellCodesJson.Size();
|
|
|
|
|
++nIndex) {
|
|
|
|
|
if(!vecSelectableWellCodesJson[nIndex].IsString()) {
|
|
|
|
|
qWarning() << "ResultSelectableWellCodes contains an invalid entry:"
|
|
|
|
|
<< filePath;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QString sWellCode = QString::fromUtf8(
|
|
|
|
|
vecSelectableWellCodesJson[nIndex].GetString());
|
|
|
|
|
if(!setResultWellCodes.contains(sWellCode) ||
|
|
|
|
|
setSelectableWellCodes.contains(sWellCode)) {
|
|
|
|
|
qWarning() << "ResultSelectableWellCodes contains an invalid WellCode:"
|
|
|
|
|
<< sWellCode;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
setSelectableWellCodes.insert(sWellCode);
|
|
|
|
|
listSavedResultSelectableWellCodes.append(sWellCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(bSavedResultsAvailable &&
|
|
|
|
|
(vecSavedResultSolverOrder.isEmpty() ||
|
|
|
|
|
!setResultWellCodes.contains(sSavedCurrentResultWellCode))) {
|
|
|
|
|
@ -4400,6 +4424,17 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
|
|
<< filePath;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(bHasSelectableWellCodes &&
|
|
|
|
|
((bSavedResultsAvailable &&
|
|
|
|
|
(listSavedResultSelectableWellCodes.isEmpty() ||
|
|
|
|
|
!listSavedResultSelectableWellCodes.contains(
|
|
|
|
|
sSavedCurrentResultWellCode))) ||
|
|
|
|
|
(!bSavedResultsAvailable &&
|
|
|
|
|
!listSavedResultSelectableWellCodes.isEmpty()))) {
|
|
|
|
|
qWarning() << "ResultSelectableWellCodes is inconsistent with result state:"
|
|
|
|
|
<< filePath;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
vecSavedResultSolverOrder = vecSavedSolverOrder;
|
|
|
|
|
}
|
|
|
|
|
@ -4798,13 +4833,14 @@ bool nmDataAnalyzeManager::ReadProjectData(const QString & filePath)
|
|
|
|
|
m_oNumericalAnalysisCase.setIncludedWells(vecSavedIncludedWells);
|
|
|
|
|
m_oNumericalAnalysisCase.setIncludeOtherWells(bSavedIncludeOtherWells);
|
|
|
|
|
m_oNumericalAnalysisCase.setSolverWellOrder(vecSavedSolverOrder);
|
|
|
|
|
m_oNumericalAnalysisCase.setCurrentResultWellCode(
|
|
|
|
|
sSavedCurrentResultWellCode.isEmpty()
|
|
|
|
|
? sSavedPrimaryWellCode : sSavedCurrentResultWellCode);
|
|
|
|
|
m_oNumericalAnalysisCase.restoreResultState(
|
|
|
|
|
vecSavedResultSolverOrder,
|
|
|
|
|
listSavedResultSelectableWellCodes,
|
|
|
|
|
bSavedResultsAvailable,
|
|
|
|
|
bSavedResultsCurrent);
|
|
|
|
|
m_oNumericalAnalysisCase.setCurrentResultWellCode(
|
|
|
|
|
sSavedCurrentResultWellCode.isEmpty()
|
|
|
|
|
? sSavedPrimaryWellCode : sSavedCurrentResultWellCode);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 解析 时间步 对象
|
|
|
|
|
@ -4944,9 +4980,30 @@ bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QStringList listValidatedResultSelectableWellCodes;
|
|
|
|
|
if(bHasResults) {
|
|
|
|
|
listValidatedResultSelectableWellCodes =
|
|
|
|
|
m_oNumericalAnalysisCase.getResultSelectableWellCodes();
|
|
|
|
|
}
|
|
|
|
|
QSet<QString> setResultSelectableWellCodes;
|
|
|
|
|
for(int nIndex = 0;
|
|
|
|
|
nIndex < listValidatedResultSelectableWellCodes.size();
|
|
|
|
|
++nIndex) {
|
|
|
|
|
const QString sWellCode =
|
|
|
|
|
listValidatedResultSelectableWellCodes[nIndex];
|
|
|
|
|
if(!setResultWellCodes.contains(sWellCode) ||
|
|
|
|
|
setResultSelectableWellCodes.contains(sWellCode)) {
|
|
|
|
|
qWarning() << "Cannot save numerical project: invalid selectable result WellCode:"
|
|
|
|
|
<< sWellCode;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
setResultSelectableWellCodes.insert(sWellCode);
|
|
|
|
|
}
|
|
|
|
|
if(bHasResults &&
|
|
|
|
|
(vecValidatedResultOrder.isEmpty() ||
|
|
|
|
|
!setResultWellCodes.contains(sCurrentResultWellCode))) {
|
|
|
|
|
listValidatedResultSelectableWellCodes.isEmpty() ||
|
|
|
|
|
!setResultSelectableWellCodes.contains(sCurrentResultWellCode))) {
|
|
|
|
|
qWarning() << "Cannot save numerical project: result order is incomplete.";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@ -5237,6 +5294,20 @@ bool nmDataAnalyzeManager::WriteProjectData(const QString & filePath)
|
|
|
|
|
}
|
|
|
|
|
oCaseJson.AddMember("ResultSolverWellOrder",
|
|
|
|
|
vecResultOrderJson, allocator);
|
|
|
|
|
|
|
|
|
|
rapidjson::Value vecResultSelectableWellCodesJson(
|
|
|
|
|
rapidjson::kArrayType);
|
|
|
|
|
for(int nIndex = 0;
|
|
|
|
|
nIndex < listValidatedResultSelectableWellCodes.size();
|
|
|
|
|
++nIndex) {
|
|
|
|
|
QByteArray baWellCode =
|
|
|
|
|
listValidatedResultSelectableWellCodes[nIndex].toUtf8();
|
|
|
|
|
vecResultSelectableWellCodesJson.PushBack(
|
|
|
|
|
rapidjson::Value(baWellCode.constData(), allocator).Move(),
|
|
|
|
|
allocator);
|
|
|
|
|
}
|
|
|
|
|
oCaseJson.AddMember("ResultSelectableWellCodes",
|
|
|
|
|
vecResultSelectableWellCodesJson, allocator);
|
|
|
|
|
doc.AddMember("NumericalAnalysisCase", oCaseJson, allocator);
|
|
|
|
|
|
|
|
|
|
// 序列化 时间步数据
|
|
|
|
|
@ -5423,6 +5494,8 @@ bool nmDataAnalyzeManager::loadNmResult(QString sLoadAnalDir)
|
|
|
|
|
m_oNumericalAnalysisCase.hasResults();
|
|
|
|
|
const QVector<nmSolverWellRef> vecResultSolverOrder =
|
|
|
|
|
getResultSolverWellOrder();
|
|
|
|
|
const QStringList listResultSelectableWellCodes =
|
|
|
|
|
m_oNumericalAnalysisCase.getResultSelectableWellCodes();
|
|
|
|
|
|
|
|
|
|
// 第一步:先检查分析方案、网格文件和结果文件是否构成完整的一组。
|
|
|
|
|
QString sCurrentGridPath = sLoadAnalDir + "/Grid/CurrentGrid.vtu";
|
|
|
|
|
@ -5597,6 +5670,8 @@ bool nmDataAnalyzeManager::loadNmResult(QString sLoadAnalDir)
|
|
|
|
|
m_oNumericalAnalysisCase.restoreResultState(
|
|
|
|
|
bHasCompleteResultFiles
|
|
|
|
|
? vecResultSolverOrder : QVector<nmSolverWellRef>(),
|
|
|
|
|
bHasCompleteResultFiles
|
|
|
|
|
? listResultSelectableWellCodes : QStringList(),
|
|
|
|
|
bHasCompleteResultFiles,
|
|
|
|
|
bHasCompleteResultFiles && bHasCurrentGridFile &&
|
|
|
|
|
bSavedResultsCurrent);
|
|
|
|
|
|