/*! * \brief Initialize the phase viscosity for oil saturated gas * * The gas viscosity is a function of \f$(p_g, X_g^O)\f$, but this method only * requires the viscosity of oil-saturated gas (which only depends on pressure) while * there is assumed to be no dependence on the gas mass fraction... */ void setSaturatedGasViscosity(int regionIdx, const SamplingPoints &samplePoints ) { auto& oilVaporizationFactor = oilVaporizationFactorTable_[regionIdx]; Scalar RvMin = 0.0; Scalar RvMax = oilVaporizationFactor.eval(oilVaporizationFactorTable_[regionIdx].xMax(), /*extrapolate=*/true); Scalar poMin = samplePoints.front().first; Scalar poMax = samplePoints.back().first; size_t nRv = 20; size_t nP = samplePoints.size()*2; Spline mugSpline; mugSpline.setContainerOfTuples(samplePoints, /*type=*/Spline::Monotonic); // calculate a table of estimated densities depending on pressure and gas mass // fraction for (size_t RvIdx = 0; RvIdx < nRv; ++RvIdx) { Scalar Rv = RvMin + (RvMax - RvMin)*RvIdx/nRv; gasMu_[regionIdx].appendXPos(Rv); for (size_t pIdx = 0; pIdx < nP; ++pIdx) { Scalar pg = poMin + (poMax - poMin)*pIdx/nP; Scalar mug = mugSpline.eval(pg, /*extrapolate=*/true); gasMu_[regionIdx].appendSamplePoint(RvIdx, pg, mug); } } }
void testMonotonic(const Spline &sp, const double *x, const double *y) { // test the common properties of splines testCommon(sp, x, y); size_t n = sp.numSamples(); for (size_t i = 0; i < n - 1; ++ i) { // make sure that the spline is monotonic for each interval // between sampling points if (!sp.monotonic(x[i], x[i + 1])) OPM_THROW(std::runtime_error, "Spline says it is not monotonic in interval " << i << " where it should be"); // test the intersection methods double d = (y[i] + y[i+1])/2; double interX = sp.template intersectInterval<double>(x[i], x[i+1], /*a=*/0, /*b=*/0, /*c=*/0, d); double interY = sp.eval(interX); if (std::abs(interY - d) > 1e-5) OPM_THROW(std::runtime_error, "Spline::intersectInterval() seems to be broken: " << sp.eval(interX) << " - " << d << " = " << sp.eval(interX) - d << "!"); } // make sure the spline says to be monotonic on the (extrapolated) // left and right sides if (!sp.monotonic(x[0] - 1.0, (x[0] + x[1])/2, /*extrapolate=*/true)) OPM_THROW(std::runtime_error, "Spline says it is not monotonic on left side where it should be"); if (!sp.monotonic((x[n - 2]+ x[n - 1])/2, x[n-1] + 1.0, /*extrapolate=*/true)) OPM_THROW(std::runtime_error, "Spline says it is not monotonic on right side where it should be"); for (size_t i = 0; i < n - 2; ++ i) { // make sure that the spline says that it is non-monotonic for // if extrema are within the queried interval if (sp.monotonic((x[i] + x[i + 1])/2, (x[i + 1] + x[i + 2])/2)) OPM_THROW(std::runtime_error, "Spline says it is monotonic in interval " << i << " where it should not be"); } }
/*! * \brief Initialize the function for the gas formation volume factor * * The gas formation volume factor \f$B_g\f$ is a function of \f$(p_g, X_g^O)\f$ and * represents the partial density of the oil component in the gas phase at a given * pressure. This method only requires the volume factor of oil-saturated gas (which * only depends on pressure) while the dependence on the oil mass fraction is * guesstimated... */ void setSaturatedGasFormationVolumeFactor(int regionIdx, const SamplingPoints &samplePoints) { auto& invGasB = inverseGasB_[regionIdx]; auto &Rv = oilVaporizationFactorTable_[regionIdx]; Scalar T = BlackOilFluidSystem::surfaceTemperature; Scalar RvMin = 0.0; Scalar RvMax = Rv.eval(oilVaporizationFactorTable_[regionIdx].xMax(), /*extrapolate=*/true); Scalar poMin = samplePoints.front().first; Scalar poMax = samplePoints.back().first; size_t nRv = 20; size_t nP = samplePoints.size()*2; Scalar rhogRef = BlackOilFluidSystem::referenceDensity(gasPhaseIdx, regionIdx); Scalar rhooRef = BlackOilFluidSystem::referenceDensity(oilPhaseIdx, regionIdx); Spline gasFormationVolumeFactorSpline; gasFormationVolumeFactorSpline.setContainerOfTuples(samplePoints, /*type=*/Spline::Monotonic); updateSaturationPressureSpline_(regionIdx); // calculate a table of estimated densities depending on pressure and gas mass // fraction for (size_t RvIdx = 0; RvIdx < nRv; ++RvIdx) { Scalar Rv = RvMin + (RvMax - RvMin)*RvIdx/nRv; Scalar XgO = Rv/(rhooRef/rhogRef + Rv); invGasB.appendXPos(Rv); for (size_t pIdx = 0; pIdx < nP; ++pIdx) { Scalar pg = poMin + (poMax - poMin)*pIdx/nP; Scalar poSat = gasSaturationPressure(regionIdx, T, XgO); Scalar BgSat = gasFormationVolumeFactorSpline.eval(poSat, /*extrapolate=*/true); Scalar drhoo_dp = (1.1200 - 1.1189)/((5000 - 4000)*6894.76); Scalar rhoo = BlackOilFluidSystem::referenceDensity(oilPhaseIdx, regionIdx)/BgSat*(1 + drhoo_dp*(pg - poSat)); Scalar Bg = BlackOilFluidSystem::referenceDensity(oilPhaseIdx, regionIdx)/rhoo; invGasB.appendSamplePoint(RvIdx, pg, 1.0/Bg); } } }
static Scalar regularizedSqrt_(Scalar x) { static const Scalar xMin = 1e-2; static const Scalar sqrtXMin = std::sqrt(xMin); static const Scalar fPrimeXMin = 1.0/(2*std::sqrt(xMin)); static const Scalar fPrime0 = 2*fPrimeXMin; typedef Opm::Spline<Scalar> Spline; static const Spline sqrtRegSpline(0, xMin, // x0, x1 0, sqrtXMin, // y0, y1 fPrime0, fPrimeXMin); // m0, m1 if (x > xMin) return std::sqrt(x); else if (x <= 0) return fPrime0 * x; else return sqrtRegSpline.eval(x); }
void testCommon(const Spline &sp, const double *x, const double *y) { static double eps = 1e-10; static double epsFD = 1e-7; size_t n = sp.numSamples(); for (size_t i = 0; i < n; ++i) { // sure that we hit all sampling points double y0 = (i>0)?sp.eval(x[i]-eps):y[0]; double y1 = sp.eval(x[i]); double y2 = (i<n-1)?sp.eval(x[i]+eps):y[n-1]; if (std::abs(y0 - y[i]) > 100*eps || std::abs(y2 - y[i]) > 100*eps) OPM_THROW(std::runtime_error, "Spline seems to be discontinuous at sampling point " << i << "!"); if (std::abs(y1 - y[i]) > eps) OPM_THROW(std::runtime_error, "Spline does not capture sampling point " << i << "!"); // make sure the derivative is continuous (assuming that the // second derivative is smaller than 1000) double d1 = sp.evalDerivative(x[i]); double d0 = (i>0)?sp.evalDerivative(x[i]-eps):d1; double d2 = (i<n-1)?sp.evalDerivative(x[i]+eps):d1; if (std::abs(d1 - d0) > 1000*eps || std::abs(d2 - d0) > 1000*eps) OPM_THROW(std::runtime_error, "Spline seems to exhibit a discontinuous derivative at sampling point " << i << "!"); } // make sure the derivatives are consistent with the curve size_t np = 3*n; for (size_t i = 0; i < np; ++i) { double xMin = sp.xAt(0); double xMax = sp.xAt(sp.numSamples() - 1); double xval = xMin + (xMax - xMin)*i/np; // first derivative double y1 = sp.eval(xval+epsFD); double y0 = sp.eval(xval); double mFD = (y1 - y0)/epsFD; double m = sp.evalDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); // second derivative y1 = sp.evalDerivative(xval+epsFD); y0 = sp.evalDerivative(xval); mFD = (y1 - y0)/epsFD; m = sp.evalSecondDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Second derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); // Third derivative y1 = sp.evalSecondDerivative(xval+epsFD); y0 = sp.evalSecondDerivative(xval); mFD = (y1 - y0)/epsFD; m = sp.evalThirdDerivative(xval); if (std::abs( mFD - m ) > 1000*epsFD) OPM_THROW(std::runtime_error, "Third derivative of spline seems to be inconsistent with cuve" " (" << mFD << " - " << m << " = " << mFD - m << ")!"); } }
int main(int argc, char **argv) { using Calibration::HistogramF; using Calibration::VarProcessor; ROOT::Cintex::Cintex::Enable(); if (argc != 3) { std::cerr << "Syntax: " << argv[0] << " <MVA File> " << "<output ROOT file>" << std::endl; return 1; } Calibration::MVAComputer *calib = MVAComputer::readCalibration(argv[1]); if (!calib) return 1; std::map<std::string, HistogramF*> histos; std::vector<VarProcessor*> procs = calib->getProcessors(); for(unsigned int z = 0; z < procs.size(); ++z) { VarProcessor *proc = procs[z]; if (!proc) continue; std::ostringstream ss3; ss3 << (z + 1); Calibration::ProcLikelihood *lkh = dynamic_cast<Calibration::ProcLikelihood*>(proc); Calibration::ProcNormalize *norm = dynamic_cast<Calibration::ProcNormalize*>(proc); if (lkh) { for(unsigned int i = 0; i < lkh->pdfs.size(); i++) { std::ostringstream ss2; ss2 << (i + 1); histos["proc" + ss3.str() + "_sig" + ss2.str()] = &lkh->pdfs[i].signal; histos["proc" + ss3.str() + "_bkg" + ss2.str()] = &lkh->pdfs[i].background; } } else if (norm) { for(unsigned int i = 0; i < norm->distr.size(); i++) { std::ostringstream ss2; ss2 << (i + 1); histos["proc" + ss3.str() + "_norm" + ss2.str()] = &norm->distr[i]; } } } TFile *f = TFile::Open(argv[2], "RECREATE"); if (!f) return 2; for(std::map<std::string, HistogramF*>::const_iterator iter = histos.begin(); iter != histos.end(); ++iter) { std::string name = iter->first; HistogramF *histo = iter->second; unsigned int size = histo->values().size() - 2; std::vector<double> values( histo->values().begin() + 1, histo->values().end() - 1); Spline spline; spline.set(values.size(), &values.front()); double min = histo->range().min; double max = histo->range().max; TH1F *h = new TH1F((name + "_histo").c_str(), (name + "_histo").c_str(), size, min - 0.5 * (max - min) / size, max + 0.5 * (max - min) / size); TH1F *s = new TH1F((name + "_spline").c_str(), (name + "_spline").c_str(), size * precision, min, max); for(unsigned int i = 0; i < size; i++) { h->SetBinContent(i + 1, histo->values()[i + 1]); for(int j = 0; j < precision; j++) { unsigned int k = i * precision + j; double x = (k + 0.5) / (size * precision); double v = spline.eval(x); s->SetBinContent(k, v); } } } f->Write(); delete f; return 0; }