double SimulatedAnnealingOptimizer::SimAnnealEvalFunction(const SC_DoubleArray& normParEstimates) { if (!NormParOK(normParEstimates)) return currFitVal; // should simulate this if (!CalcFitValue(normParEstimates, currFitVal)) { if (runCount == 1) throw SimError("failure on first sa calculation"); currFitVal = worstFitVal * 1.1; } else optProgressOutput.CalcAndUpdate(); updateCB(*this); if ((currFitVal < bestFitVal) || (runCount == 1)) { bestFitVal = currFitVal; bestNormParEst = normParEstimates; GetOptParEst(bestParEst); } if (currFitVal > worstFitVal) worstFitVal = currFitVal; return currFitVal; }
void SingleWell1DNonLinearGas::MatSolve(bool& setupRequired) { NonlinearMatSolve(); if (nodePressure[0] < 0.0) throw SimError("-ve pressure in gas well - reduce pumping rate", SimError::seSemiFatal); currSeqTZ.tzPressure = nodePressure[0] - atmosPressure; currSeqTZ.formFlow = NLCalcDTerm(0, nodePressure[0], nodePressure[1]) + NLCalcFormSTerm(nodePressure[0]) - NLCalcFormSTerm(lastSeqTZ.tzPressure + atmosPressure); }
void SingleWell1DNonLinearLiquid::MatSolve(bool& setupRequired) { NonlinearMatSolve(); if ((nodePressure[0] < 0.0) && (!allowNegativePressure)) throw SimError("well sucked dry - reduce pumping rate", SimError::seSemiFatal); currSeqTZ.tzPressure = nodePressure[0]; currSeqTZ.formFlow = NLCalcDTerm(0, nodePressure[0], nodePressure[1]) + NLCalcFormSTerm(nodePressure[0]) - NLCalcFormSTerm(lastSeqTZ.tzPressure); }
void SingleWell1DLinear::MatSolve(bool& setupRequired) // main driver { if (!allAreConstant) { parameterTime = currSeqTime.testTime; BuildMatrices(); setupRequired = true; } if (setupRequired) { LinearMatSetup(); setupRequired = false; } LinearMatSolve(); currSeqTZ.tzPressure = nodePressure[0]; currSeqTZ.formFlow = wellDTerm * (currSeqTZ.tzPressure - nodePressure[1]) + fracSVector[0] * (currSeqTZ.tzPressure - lastSeqTZ.tzPressure) / deltaT; if ((currSeqTZ.tzPressure < 0.0) && (!allowNegativePressure)) throw SimError("1D linear well sucked dry - reduce pumping rate", SimError::seSemiFatal); }
void SingleWell1DLinear::LinearMatSolve() { int indxOff = SolveNodeOffset(); for (int i = 0; i < nequations; i++) fracRhs[i] = fracSSolve[i] * nodePressure[i + indxOff]; if (control.IsDual()) AddSCRhsTerm(matrix); if (control.IsLeaky()) { if (leakageType == ltUpperLower) { AddSCRhsTerm(upperLeak); AddSCRhsTerm(lowerLeak); } else AddSCRhsTerm(singleLeak); } fracRhs[nequations - 1] -= externalBoundaryTerm; if (currentSeqIsFixed) fracRhs[0] += currSeqTZ.tzPressure * wellDTerm; else fracRhs[0] += GetWellBCRhs(); #ifdef LAPACK //for LAPACK, just use the simple tri-diagonal solver. int N = nequations; int nrhs = 1; double *DL = new double[N-1]; double *D = new double[N]; double *DU = new double[N-1]; double *B = new double[N]; for(int i = 0; i < N-1; i++) { DL[i]=fracSolveUpper[i]; DU[i]=fracSolveUpper[i]; D[i]=fracSolveDiag[i]; B[i]=fracRhs[i]; } D[N-1]=fracSolveDiag[N-1]; B[N-1]=fracRhs[N-1]; int ldb = N; int info; dgtsv_(&N, &nrhs, DL, D, DU, B, &ldb, &info); if(info == 0) { for(int i = 0; i < N; i++) { nodePressure[i]=B[i]; } } else //info != 0 { throw SimError("SingleWell1DLinear::LinearMatSolve - failed tri-diagonal solve", SimError::seSemiFatal); } delete [] DL; delete [] DU; delete [] D; delete [] B; #else // LAPACK ThomasSolve(fracSolveDiag, fracSolveUpper, fracWork, fracRhs, nodePressure, nequations); #endif // LAPACK if (currentSeqIsFixed) { for (int i = nequations; i > 0; i--) nodePressure[i] = nodePressure[i - 1]; nodePressure[0] = currSeqTZ.tzPressure; } if (control.IsDual()) SCGaussSolve(matrix); if (control.IsLeaky()) { if (leakageType == ltUpperLower) { SCGaussSolve(upperLeak); SCGaussSolve(lowerLeak); } else SCGaussSolve(singleLeak); } }
void WorkingSequence::StartSequence( SeqTimeVals& initTime, const SeqBoundVals& lastSeqEndBC, // at end of prev seq - used for TS/TZ rel init pressure SeqBoundVals& initBC) { // set up time initTime.seqTime = 0.0; initTime.testTime = startTime; switch (timeStepType) { case TimeStep::tstStatic : { initTime.deltaT = linDeltaT; break; } case TimeStep::tstLog : { initTime.deltaT = logTStart; break; } case TimeStep::tstDynamicP : case TimeStep::tstDynamicQ :{ initTime.deltaT = minTS; if (initTime.deltaT < 0.01) initTime.deltaT = 0.01; lastQOK = false; break; } } // set up BC tsSavePressure = lastSeqEndBC.tsPressure; // maintained for duration of pulse // or for flow/hist with isolated initBC.tsPressure = lastSeqEndBC.tsPressure; switch (seqType) { case Sequence::stFlow : { initBC.tzPressure = lastSeqEndBC.tzPressure; // maintained for duration of pulse initBC.wellFlow = tzFlowBC.GetCurveY(initTime) + fixedOffset; break; } case Sequence::stHistory : { initBC.tzPressure = tzPressBC.GetCurveY(initTime) + fixedOffset; break; } case Sequence::stPulse : case Sequence::stSlug : { switch (initialPressureType) { case PulseSlugBase::ipAbsolute : { initBC.tzPressure = initialPressure; break; } case PulseSlugBase::ipTSRelative : { initBC.tzPressure = lastSeqEndBC.tsPressure + initialPressure; break; } case PulseSlugBase::ipSeqRelative : { initBC.tzPressure = lastSeqEndBC.tzPressure + initialPressure; break; } } if (initBC.tzPressure < 0.0) throw SimError("initial well pressure/head < zero", SimError::seSemiFatal); break; } } if (wellboreStorage == FlowHistBase::wsOpen) initBC.tsPressure = initBC.tzPressure; lastP = initBC.tzPressure; // get remainder initBC.tzTemp = tzTempBC.GetCurveY(initTime); initBC.tzVol = tzVolBC.GetCurveY(initTime) + volOffset; if (tzCompFP->IsFP()) initBC.tzComp = tzCompFP->GetData(initBC.tzPressure); else initBC.tzComp = tzCompFTBC.GetCurveY(initTime); if (!control.IsGas()) initBC.tzDens = tzDensFP->GetData(initBC.tzPressure); }