|
|
|
|
@ -651,6 +651,7 @@ nmCalculationDllPebiSolverTask::nmCalculationDllPebiSolverTask(
|
|
|
|
|
} catch(const std::bad_alloc&) {
|
|
|
|
|
// 构造阶段内存不足时保留旧成果,任务保持无效并由既有完成流程报错。
|
|
|
|
|
qWarning() << "Cannot allocate PEBI solver input snapshot.";
|
|
|
|
|
fail(tr("Insufficient memory to prepare solver input."));
|
|
|
|
|
delete m_pManualCaptureState;
|
|
|
|
|
m_pManualCaptureState = nullptr;
|
|
|
|
|
delete m_pInputSnapshot;
|
|
|
|
|
@ -683,6 +684,7 @@ void nmCalculationDllPebiSolverTask::run()
|
|
|
|
|
} catch(const std::bad_alloc&) {
|
|
|
|
|
// VTK 部分分配接口没有返回值,统一在任务边界拒绝候选并保留旧快照。
|
|
|
|
|
qWarning() << "Cannot allocate PEBI solver result snapshot.";
|
|
|
|
|
fail(tr("Insufficient memory to process solver results."));
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
bSucceeded = false;
|
|
|
|
|
}
|
|
|
|
|
@ -732,7 +734,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
if(m_pManualCaptureState == nullptr || m_pInputSnapshot == nullptr ||
|
|
|
|
|
m_pDataManager == nullptr || isRunning() ||
|
|
|
|
|
QThread::currentThread() != m_pDataManager->thread()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Solver input is unavailable."));
|
|
|
|
|
}
|
|
|
|
|
if(isCancelRequested()) {
|
|
|
|
|
m_nWasCancelled.fetchAndStoreOrdered(1);
|
|
|
|
|
@ -745,7 +747,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
nmDataNumericalAnalysisCase* pAnalysisCase =
|
|
|
|
|
m_pDataManager->getNumericalAnalysisCase();
|
|
|
|
|
if(pGridService == nullptr || pAnalysisCase == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Solver input is unavailable."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(pState->m_ePhase !=
|
|
|
|
|
@ -764,7 +766,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
|
|
|
|
|
if(!pGridService->beginManualInputSnapshot(
|
|
|
|
|
m_pDataManager, m_pInputSnapshot->m_oGridInput)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture solver input."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QVector<nmCalculationWellRef> vecEffectiveWells =
|
|
|
|
|
@ -774,7 +776,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
if(oWellRef.m_sWellCode.isEmpty() ||
|
|
|
|
|
pState->m_setEffectiveWellCodes.contains(
|
|
|
|
|
oWellRef.m_sWellCode)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The well configuration is invalid."));
|
|
|
|
|
}
|
|
|
|
|
pState->m_setEffectiveWellCodes.insert(oWellRef.m_sWellCode);
|
|
|
|
|
pState->m_mapWellModes.insert(
|
|
|
|
|
@ -782,7 +784,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
static_cast<int>(oWellRef.m_eMode));
|
|
|
|
|
}
|
|
|
|
|
if(pState->m_setEffectiveWellCodes.isEmpty()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("No valid wells are available for solving."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QSet<QString> setOrderedWellCodes;
|
|
|
|
|
@ -829,7 +831,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
if(setOrderedWellCodes != pState->m_setEffectiveWellCodes ||
|
|
|
|
|
pState->m_vecOrderedWells.size() !=
|
|
|
|
|
pState->m_setEffectiveWellCodes.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The well configuration is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pState->m_ePhase = nmPebiManualCaptureState::CapturePhase_Wells;
|
|
|
|
|
@ -856,7 +858,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
pWellData,
|
|
|
|
|
pState->m_mapWellModes.value(pWellData->getWellCode()),
|
|
|
|
|
m_pInputSnapshot->m_oGridInput)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture well data."));
|
|
|
|
|
}
|
|
|
|
|
if(m_pInputSnapshot->m_oGridInput.m_vecWellInputs.isEmpty() ||
|
|
|
|
|
!captureResultWellMetadata(
|
|
|
|
|
@ -864,7 +866,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
isDisplayResultWell(pAnalysisCase,
|
|
|
|
|
pWellData->getWellCode()),
|
|
|
|
|
m_pInputSnapshot->m_oGridInput.m_vecWellInputs.last())) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture well data."));
|
|
|
|
|
}
|
|
|
|
|
++pState->m_nNextWellIndex;
|
|
|
|
|
}
|
|
|
|
|
@ -887,7 +889,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
m_pDataManager,
|
|
|
|
|
pState->m_setEffectiveWellCodes,
|
|
|
|
|
m_pInputSnapshot->m_oGridInput)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to finalize solver input."));
|
|
|
|
|
}
|
|
|
|
|
pState->m_ePhase =
|
|
|
|
|
nmPebiManualCaptureState::CapturePhase_SolverSettings;
|
|
|
|
|
@ -907,7 +909,7 @@ bool nmCalculationDllPebiSolverTask::captureManualInputStep(
|
|
|
|
|
m_pDataManager->getPebiIluReuseSteps();
|
|
|
|
|
if(!captureResultParameters(m_pDataManager,
|
|
|
|
|
*m_pInputSnapshot)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture solver settings."));
|
|
|
|
|
}
|
|
|
|
|
pState->m_ePhase =
|
|
|
|
|
nmPebiManualCaptureState::CapturePhase_GridCache;
|
|
|
|
|
@ -953,6 +955,14 @@ void nmCalculationDllPebiSolverTask::reportStage(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool nmCalculationDllPebiSolverTask::fail(const QString& sFailureReason)
|
|
|
|
|
{
|
|
|
|
|
if(!isCancelRequested() && m_sFailureReason.isEmpty()) {
|
|
|
|
|
m_sFailureReason = sFailureReason;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void nmCalculationDllPebiSolverTask::releaseDataManagerUse()
|
|
|
|
|
{
|
|
|
|
|
if(m_bManagerUseActive && m_pDataManager != nullptr) {
|
|
|
|
|
@ -967,13 +977,13 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
if(m_pDataManager == nullptr || m_pInputSnapshot == nullptr ||
|
|
|
|
|
QThread::currentThread() != m_pDataManager->thread()) {
|
|
|
|
|
qWarning() << "PEBI solver input must be captured on the DataManager thread.";
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Solver input is unavailable."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmDataNumericalAnalysisCase* pAnalysisCase =
|
|
|
|
|
m_pDataManager->getNumericalAnalysisCase();
|
|
|
|
|
if(pAnalysisCase == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Solver input is unavailable."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第一步:冻结几何和求解输入版本。提交阶段会再次核对,期间发生任何编辑
|
|
|
|
|
@ -992,7 +1002,7 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
if(pTargetWell == nullptr || pTargetWell->getWellCode().isEmpty()) {
|
|
|
|
|
qWarning() << "Auto-fit target well is unavailable:"
|
|
|
|
|
<< sAutoFitTargetWellName;
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The target well is unavailable."));
|
|
|
|
|
}
|
|
|
|
|
m_sAutoFitTargetWellCode = pTargetWell->getWellCode();
|
|
|
|
|
} else {
|
|
|
|
|
@ -1010,14 +1020,14 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
!m_pInputSnapshot->m_bAutoFitTargetOnly) ||
|
|
|
|
|
m_pInputSnapshot->m_oGridInput.m_nGridInputRevision !=
|
|
|
|
|
m_nGridInputRevision) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture solver input."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QVector<nmSolverWellRef>& vecWellOrder =
|
|
|
|
|
m_pInputSnapshot->m_oGridInput.m_vecSolverWellOrder;
|
|
|
|
|
if(m_pInputSnapshot->m_oGridInput.m_vecWellInputs.size() !=
|
|
|
|
|
vecWellOrder.size()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture well data."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 自动拟合候选保持原来的轻量输入;只有最终完整场求解冻结正式结果元数据。
|
|
|
|
|
@ -1044,7 +1054,7 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
isDisplayResultWell(pAnalysisCase,
|
|
|
|
|
oWellRef.m_sWellCode),
|
|
|
|
|
m_pInputSnapshot->m_oGridInput.m_vecWellInputs[nIndex])) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture well data."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1061,7 +1071,7 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
m_pDataManager->getPebiIluReuseSteps();
|
|
|
|
|
if(!m_pInputSnapshot->m_bAutoFitTargetOnly &&
|
|
|
|
|
!captureResultParameters(m_pDataManager, *m_pInputSnapshot)) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to capture solver settings."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第四步:主线程仅检查缓存并捕获基础网格的智能指针。生成后的基础网格
|
|
|
|
|
@ -1106,8 +1116,10 @@ bool nmCalculationDllPebiSolverTask::captureInputSnapshot(
|
|
|
|
|
|
|
|
|
|
bool nmCalculationDllPebiSolverTask::prepareManualInput()
|
|
|
|
|
{
|
|
|
|
|
if(m_pInputSnapshot == nullptr ||
|
|
|
|
|
m_pInputSnapshot->m_bAutoFitTargetOnly) {
|
|
|
|
|
if(m_pInputSnapshot == nullptr) {
|
|
|
|
|
return fail(tr("Solver input snapshot is invalid."));
|
|
|
|
|
}
|
|
|
|
|
if(m_pInputSnapshot->m_bAutoFitTargetOnly) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1119,7 +1131,9 @@ bool nmCalculationDllPebiSolverTask::prepareManualInput()
|
|
|
|
|
m_pInputSnapshot->m_oGridInput,
|
|
|
|
|
&m_nCancelRequested) ||
|
|
|
|
|
isCancelRequested()) {
|
|
|
|
|
return false;
|
|
|
|
|
return isCancelRequested()
|
|
|
|
|
? false
|
|
|
|
|
: fail(tr("Failed to prepare solver input."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
reportStage(tr("Checking grid cache..."), 0, 0);
|
|
|
|
|
@ -1149,7 +1163,7 @@ bool nmCalculationDllPebiSolverTask::prepareManualInput()
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(m_pInputSnapshot->m_pBaseGrid->GetNumberOfCells() <= 0) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The prepared result grid is invalid."));
|
|
|
|
|
}
|
|
|
|
|
} else if(isCancelRequested()) {
|
|
|
|
|
return false;
|
|
|
|
|
@ -1177,6 +1191,11 @@ int nmCalculationDllPebiSolverTask::getPebiCount() const
|
|
|
|
|
return m_nPebiCount;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QString nmCalculationDllPebiSolverTask::getFailureReason() const
|
|
|
|
|
{
|
|
|
|
|
return m_sFailureReason;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QVector<QVector<double> > nmCalculationDllPebiSolverTask::getAutoFitResultPressure() const
|
|
|
|
|
{
|
|
|
|
|
return m_autoFitResultPressure;
|
|
|
|
|
@ -1205,7 +1224,9 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
{
|
|
|
|
|
if(!m_bInputSnapshotValid || m_pInputSnapshot == nullptr ||
|
|
|
|
|
isCancelRequested()) {
|
|
|
|
|
return false;
|
|
|
|
|
return isCancelRequested()
|
|
|
|
|
? false
|
|
|
|
|
: fail(tr("Solver input snapshot is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const QAtomicInt* pCancelRequested =
|
|
|
|
|
@ -1229,12 +1250,17 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
const bool bCreateUnstructuredGrid =
|
|
|
|
|
!m_pInputSnapshot->m_bAutoFitTargetOnly;
|
|
|
|
|
reportStage(tr("Generating grid..."), 0, 0);
|
|
|
|
|
if(!nmCalculationPebiGrid::getInstance()->calculateSnapshot(
|
|
|
|
|
nmCalculationPebiGrid* pGridService =
|
|
|
|
|
nmCalculationPebiGrid::getInstance();
|
|
|
|
|
if(pGridService == nullptr ||
|
|
|
|
|
!pGridService->calculateSnapshot(
|
|
|
|
|
m_pInputSnapshot->m_oGridInput,
|
|
|
|
|
oGridResult,
|
|
|
|
|
bCreateUnstructuredGrid,
|
|
|
|
|
pCancelRequested)) {
|
|
|
|
|
return false;
|
|
|
|
|
return isCancelRequested()
|
|
|
|
|
? false
|
|
|
|
|
: fail(tr("Grid generation failed."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(isCancelRequested()) {
|
|
|
|
|
@ -1244,7 +1270,7 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
if(bCreateUnstructuredGrid) {
|
|
|
|
|
if(oGridResult.m_pUnstructuredGrid == nullptr ||
|
|
|
|
|
oGridResult.m_pUnstructuredGrid->GetNumberOfCells() <= 0) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The generated grid is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_pInputSnapshot->m_pBaseGrid =
|
|
|
|
|
@ -1262,7 +1288,9 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
if(!oGridResult.m_bSucceeded ||
|
|
|
|
|
oGridResult.m_oGridOutput1.PEBI_cell.p.empty() ||
|
|
|
|
|
isCancelRequested()) {
|
|
|
|
|
return false;
|
|
|
|
|
return isCancelRequested()
|
|
|
|
|
? false
|
|
|
|
|
: fail(tr("The generated grid is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第三步:由场景值快照重建完整模型输入。属性插值可以耗时,但它只读取任务
|
|
|
|
|
@ -1283,7 +1311,7 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
.arg(sInterpolationError);
|
|
|
|
|
qWarning() << sLogMessage;
|
|
|
|
|
zxLogInstance::getInstance()->writeLogF(sLogMessage);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Property interpolation failed."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(isCancelRequested()) {
|
|
|
|
|
@ -1301,7 +1329,7 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
if(hModelModule == nullptr) {
|
|
|
|
|
qWarning() << "Failed to load HX_NWTM.dll. Error code:"
|
|
|
|
|
<< GetLastError();
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to load HX_NWTM.dll."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
typedef void (*HX_NWTM_MODEL_Fun)(
|
|
|
|
|
@ -1332,7 +1360,7 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
pfnGetSolveTime == nullptr) {
|
|
|
|
|
qWarning() << "Failed to resolve PEBI solver configuration interface.";
|
|
|
|
|
FreeLibrary(hModelModule);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver interface is incomplete."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HX_NWTM_MODEL_OUTPUT oModelOutput;
|
|
|
|
|
@ -1356,12 +1384,12 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
.arg(e.what());
|
|
|
|
|
logHX_NWTM_MODEL_INPUT_Simplified(oModelInput);
|
|
|
|
|
FreeLibrary(hModelModule);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("An exception occurred while calling the solver."));
|
|
|
|
|
} catch(...) {
|
|
|
|
|
qWarning() << "SEH Exception Occurred during HX_NWTM_MODEL call";
|
|
|
|
|
logHX_NWTM_MODEL_INPUT_Simplified(oModelInput);
|
|
|
|
|
FreeLibrary(hModelModule);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("An exception occurred while calling the solver."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 后处理只读取本次局部输出,无需继续占用进程级 DLL 锁。
|
|
|
|
|
@ -1378,6 +1406,9 @@ bool nmCalculationDllPebiSolverTask::execPebiMode()
|
|
|
|
|
oModelOutput,
|
|
|
|
|
oModelInput.T,
|
|
|
|
|
oGridResult.m_oGridOutput1);
|
|
|
|
|
if(!bSucceeded && !isCancelRequested() && m_sFailureReason.isEmpty()) {
|
|
|
|
|
fail(tr("The solver result data is invalid."));
|
|
|
|
|
}
|
|
|
|
|
return bSucceeded;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1408,7 +1439,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
const HX_NWTM_GRID_OUTPUT1& oGridOutput)
|
|
|
|
|
{
|
|
|
|
|
if(m_pInputSnapshot == nullptr) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver result data is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool autoFitTargetOnly =
|
|
|
|
|
@ -1430,7 +1461,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
|
|
|
|
|
if(usePseudoPressure && calPseudoPressure == nullptr) {
|
|
|
|
|
qWarning() << "Failed to load the gas pseudo-pressure converter.";
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to load the gas pseudo-pressure converter."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 井顺序与后处理输入都来自任务启动时的同一份快照。
|
|
|
|
|
@ -1444,7 +1475,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
if(vecWellsOrder.isEmpty() ||
|
|
|
|
|
vecWellInputs.size() != vecWellsOrder.size() ||
|
|
|
|
|
p1.t.empty()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned incomplete result data."));
|
|
|
|
|
}
|
|
|
|
|
for(size_t nTimeIndex = 0; nTimeIndex < p1.t.size(); ++nTimeIndex) {
|
|
|
|
|
if((nTimeIndex % 256) == 0 && isCancelRequested()) {
|
|
|
|
|
@ -1453,7 +1484,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
if(!isFiniteSolverNumber(p1.t[nTimeIndex])) {
|
|
|
|
|
qWarning() << "PEBI returned a non-finite time at index:"
|
|
|
|
|
<< static_cast<int>(nTimeIndex);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned invalid time data."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(int nIndex = 0; nIndex < vecWellsOrder.size(); ++nIndex) {
|
|
|
|
|
@ -1471,7 +1502,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
vecWellInputs[nIndex].m_sWellCode != oWellRef.m_sWellCode) {
|
|
|
|
|
qWarning() << "Incomplete well pressure returned for WellCode:"
|
|
|
|
|
<< oWellRef.m_sWellCode;
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned incomplete well pressure data."));
|
|
|
|
|
}
|
|
|
|
|
for(size_t nTimeIndex = 0;
|
|
|
|
|
nTimeIndex < p1.pw[nIndex].size();
|
|
|
|
|
@ -1483,7 +1514,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
qWarning() << "PEBI returned a non-finite pressure for WellCode:"
|
|
|
|
|
<< oWellRef.m_sWellCode
|
|
|
|
|
<< "time index:" << static_cast<int>(nTimeIndex);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned invalid well pressure data."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1573,7 +1604,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
qWarning() << "Failed to convert gas pressure to pseudo-pressure:"
|
|
|
|
|
<< p1.pw[wellIdx][i]
|
|
|
|
|
<< "well code:" << oWellRef.m_sWellCode;
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to convert gas pressure to pseudo-pressure."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pt.y = pressureForLog;
|
|
|
|
|
@ -1619,7 +1650,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
if(nullptr == preLogFun) {
|
|
|
|
|
FreeLibrary(hMod_solver);
|
|
|
|
|
std::cout << "preLogFun failed!\n";
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The pressure curve interface is incomplete."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 气井传入拟压力序列, 油井和水井仍传入原始压力序列.
|
|
|
|
|
@ -1631,7 +1662,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
nTimeNumQ,
|
|
|
|
|
logPreResultFromDll)) {
|
|
|
|
|
FreeLibrary(hMod_solver);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to calculate pressure curves."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(isCancelRequested()) {
|
|
|
|
|
@ -1694,7 +1725,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
FreeLibrary(hMod_solver);
|
|
|
|
|
} else {
|
|
|
|
|
qWarning() << "Failed to load singlePhaseSolverDll.dll.";
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to load singlePhaseSolverDll.dll."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -1730,13 +1761,15 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
&& !m_autoFitResultLogLog[0].isEmpty()
|
|
|
|
|
&& m_autoFitResultLogLog[0].size() == m_autoFitResultLogLog[1].size()
|
|
|
|
|
&& m_autoFitResultLogLog[0].size() == m_autoFitResultLogLog[2].size();
|
|
|
|
|
return pressureValid && logLogValid;
|
|
|
|
|
return pressureValid && logLogValid
|
|
|
|
|
? true
|
|
|
|
|
: fail(tr("The calculated pressure curves are invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第四步:完整求解还必须具有与时间轴、网格绘图单元严格对应的场压力。
|
|
|
|
|
if(p1.p.size() != p1.t.size() ||
|
|
|
|
|
oGridOutput.PEBI_cell.isplot.empty()) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned incomplete field pressure data."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 计算有效单元数量
|
|
|
|
|
@ -1752,7 +1785,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(actualPlotCellsCount == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The generated grid is invalid."));
|
|
|
|
|
}
|
|
|
|
|
for(size_t nTimeIndex = 0; nTimeIndex < p1.p.size(); ++nTimeIndex) {
|
|
|
|
|
if(isCancelRequested()) {
|
|
|
|
|
@ -1761,7 +1794,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
if(p1.p[nTimeIndex].size() < oGridOutput.PEBI_cell.isplot.size()) {
|
|
|
|
|
qWarning() << "Incomplete field pressure returned for time index:"
|
|
|
|
|
<< static_cast<int>(nTimeIndex);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned incomplete field pressure data."));
|
|
|
|
|
}
|
|
|
|
|
for(size_t nCellIndex = 0;
|
|
|
|
|
nCellIndex < oGridOutput.PEBI_cell.isplot.size();
|
|
|
|
|
@ -1774,7 +1807,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
qWarning() << "PEBI returned a non-finite field pressure at time/cell:"
|
|
|
|
|
<< static_cast<int>(nTimeIndex)
|
|
|
|
|
<< static_cast<int>(nCellIndex);
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned invalid field pressure data."));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@ -1841,14 +1874,14 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
|
|
|
|
|
// QMap 使用时间作为唯一键;重复时间会覆盖旧帧,因此必须检查数量一致。
|
|
|
|
|
if(m_mapPendingTimeSteps.size() != static_cast<int>(p1.t.size())) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned invalid time data."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第六步:基础网格在任务创建或局部建网阶段已经完成深拷贝。后台结果构造
|
|
|
|
|
// 不再读取 DataManager 中可能被网格窗口替换的 VTK 指针。
|
|
|
|
|
if(m_pInputSnapshot->m_pBaseGrid == nullptr ||
|
|
|
|
|
m_pInputSnapshot->m_pBaseGrid->GetNumberOfCells() <= 0) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The prepared result grid is invalid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int nExpectedWellResultCount = 0;
|
|
|
|
|
@ -1858,7 +1891,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(m_vecPendingWellResults.size() != nExpectedWellResultCount) {
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The solver returned incomplete well pressure data."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_dPendingScalarMin = dMinP;
|
|
|
|
|
@ -1866,6 +1899,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiModeResult(
|
|
|
|
|
m_bPendingFullResultReady = buildPebiResultSnapshotCandidate();
|
|
|
|
|
if(!m_bPendingFullResultReady) {
|
|
|
|
|
// 候选结构或内存校验失败时立即释放大结果,旧快照保持原状。
|
|
|
|
|
fail(tr("Failed to build the result snapshot."));
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
}
|
|
|
|
|
return m_bPendingFullResultReady;
|
|
|
|
|
@ -2037,6 +2071,7 @@ bool nmCalculationDllPebiSolverTask::buildPebiResultSnapshotCandidate()
|
|
|
|
|
return true;
|
|
|
|
|
} catch(const std::bad_alloc&) {
|
|
|
|
|
qWarning() << "Cannot allocate PEBI result snapshot candidate.";
|
|
|
|
|
fail(tr("Insufficient memory to build the result snapshot."));
|
|
|
|
|
m_pPendingResultSnapshot.clear();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
@ -2056,13 +2091,16 @@ bool nmCalculationDllPebiSolverTask::commitResult(
|
|
|
|
|
pDataManager != m_pDataManager ||
|
|
|
|
|
QThread::currentThread() != pDataManager->thread()) {
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to commit the solver results."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nmDataNumericalAnalysisCase* pAnalysisCase =
|
|
|
|
|
pDataManager->getNumericalAnalysisCase();
|
|
|
|
|
if(pAnalysisCase == nullptr ||
|
|
|
|
|
pAnalysisCase->getGridInputRevision() != m_nGridInputRevision ||
|
|
|
|
|
if(pAnalysisCase == nullptr) {
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
return fail(tr("Failed to commit the solver results."));
|
|
|
|
|
}
|
|
|
|
|
if(pAnalysisCase->getGridInputRevision() != m_nGridInputRevision ||
|
|
|
|
|
pAnalysisCase->getResultInputRevision() != m_nResultInputRevision) {
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
return false;
|
|
|
|
|
@ -2071,16 +2109,19 @@ bool nmCalculationDllPebiSolverTask::commitResult(
|
|
|
|
|
// 第二步:任务后台生成了新网格时,先在当前主线程按同一输入版本提交。
|
|
|
|
|
// 已有网格路径则再次确认其仍然有效。两条路径都不允许旧任务覆盖新编辑。
|
|
|
|
|
if(m_pInputSnapshot->m_bGridResultNeedsCommit) {
|
|
|
|
|
if(!nmCalculationPebiGrid::getInstance()->commitSnapshotResult(
|
|
|
|
|
nmCalculationPebiGrid* pGridService =
|
|
|
|
|
nmCalculationPebiGrid::getInstance();
|
|
|
|
|
if(pGridService == nullptr ||
|
|
|
|
|
!pGridService->commitSnapshotResult(
|
|
|
|
|
pDataManager,
|
|
|
|
|
m_pInputSnapshot->m_oGridInput,
|
|
|
|
|
m_pInputSnapshot->m_oGridResult)) {
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("Failed to commit the generated grid."));
|
|
|
|
|
}
|
|
|
|
|
} else if(!pAnalysisCase->isGridValid()) {
|
|
|
|
|
discardPendingFullResult();
|
|
|
|
|
return false;
|
|
|
|
|
return fail(tr("The generated grid is no longer valid."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 第三步:Manager 在唯一发布点校验 UUID、槽位和版本后替换规范快照。
|
|
|
|
|
@ -2090,6 +2131,7 @@ bool nmCalculationDllPebiSolverTask::commitResult(
|
|
|
|
|
&sError);
|
|
|
|
|
if(!bCommitted) {
|
|
|
|
|
qWarning() << "Cannot commit PEBI result snapshot:" << sError;
|
|
|
|
|
fail(tr("Failed to commit the solver results."));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 成功和失败都不允许任务继续持有候选可写别名;旧快照只由 Manager 决定。
|
|
|
|
|
|