/*! * \brief Initialize the parameters for dry gas using an ECL deck. * * This method assumes that the deck features valid DENSITY and PVDG keywords. */ void initFromDeck(DeckConstPtr deck, EclipseStateConstPtr eclState) { const auto& pvdgTables = eclState->getTableManager()->getPvdgTables(); const auto& densityKeyword = deck->getKeyword("DENSITY"); assert(pvdgTables.size() == densityKeyword.size()); size_t numRegions = pvdgTables.size(); setNumRegions(numRegions); for (unsigned regionIdx = 0; regionIdx < numRegions; ++ regionIdx) { Scalar rhoRefO = densityKeyword.getRecord(regionIdx).getItem("OIL").getSIDouble(0); Scalar rhoRefG = densityKeyword.getRecord(regionIdx).getItem("GAS").getSIDouble(0); Scalar rhoRefW = densityKeyword.getRecord(regionIdx).getItem("WATER").getSIDouble(0); setReferenceDensities(regionIdx, rhoRefO, rhoRefG, rhoRefW); // determine the molar masses of the components Scalar p = 1.01325e5; // surface pressure, [Pa] Scalar T = 273.15 + 15.56; // surface temperature, [K] Scalar MO = 175e-3; // [kg/mol] Scalar MG = Opm::Constants<Scalar>::R*T*rhoRefG / p; // [kg/mol], consequence of the ideal gas law Scalar MW = 18.0e-3; // [kg/mol] // TODO (?): the molar mass of the components can possibly specified // explicitly in the deck. setMolarMasses(regionIdx, MO, MG, MW); const auto& pvdgTable = pvdgTables.getTable<PvdgTable>(regionIdx); // say 99.97% of all time: "premature optimization is the root of all // evil". Eclipse does this "optimization" for apparently no good reason! std::vector<Scalar> invB(pvdgTable.numRows()); const auto& Bg = pvdgTable.getFormationFactorColumn(); for (unsigned i = 0; i < Bg.size(); ++ i) { invB[i] = 1.0/Bg[i]; } size_t numSamples = invB.size(); inverseGasB_[regionIdx].setXYArrays(numSamples, pvdgTable.getPressureColumn(), invB); gasMu_[regionIdx].setXYArrays(numSamples, pvdgTable.getPressureColumn(), pvdgTable.getViscosityColumn()); } initEnd(); }
void Foam::CentredFitSnGradData<Polynomial>::calcFit ( scalarList& coeffsi, const List<point>& C, const scalar wLin, const scalar deltaCoeff, const label facei ) { vector idir(1,0,0); vector jdir(0,1,0); vector kdir(0,0,1); this->findFaceDirs(idir, jdir, kdir, facei); // Setup the point weights scalarList wts(C.size(), scalar(1)); wts[0] = this->centralWeight(); wts[1] = this->centralWeight(); // Reference point point p0 = this->mesh().faceCentres()[facei]; // p0 -> p vector in the face-local coordinate system vector d; // Local coordinate scaling scalar scale = 1; // Matrix of the polynomial components scalarRectangularMatrix B(C.size(), this->minSize(), scalar(0)); forAll(C, ip) { const point& p = C[ip]; const vector p0p = p - p0; d.x() = p0p & idir; d.y() = p0p & jdir; d.z() = p0p & kdir; if (ip == 0) { scale = cmptMax(cmptMag((d))); } // Scale the radius vector d /= scale; Polynomial::addCoeffs(B[ip], d, wts[ip], this->dim()); } // Additional weighting for constant and linear terms for (label i = 0; i < B.m(); i++) { B(i, 0) *= wts[0]; B(i, 1) *= wts[0]; } // Set the fit label stencilSize = C.size(); coeffsi.setSize(stencilSize); bool goodFit = false; for (int iIt = 0; iIt < 8 && !goodFit; iIt++) { SVD svd(B, small); scalarRectangularMatrix invB(svd.VSinvUt()); for (label i=0; i<stencilSize; i++) { coeffsi[i] = wts[1]*wts[i]*invB(1, i)/scale; } goodFit = ( mag(wts[0]*wts[0]*invB(0, 0) - wLin) < this->linearLimitFactor()*wLin) && (mag(wts[0]*wts[1]*invB(0, 1) - (1 - wLin) ) < this->linearLimitFactor()*(1 - wLin)) && coeffsi[0] < 0 && coeffsi[1] > 0 && mag(coeffsi[0] + deltaCoeff) < 0.5*deltaCoeff && mag(coeffsi[1] - deltaCoeff) < 0.5*deltaCoeff; if (!goodFit) { // (not good fit so increase weight in the centre and weight // for constant and linear terms) WarningInFunction << "Cannot fit face " << facei << " iteration " << iIt << " with sum of weights " << sum(coeffsi) << nl << " Weights " << coeffsi << nl << " Linear weights " << wLin << " " << 1 - wLin << nl << " deltaCoeff " << deltaCoeff << nl << " sing vals " << svd.S() << nl << "Components of goodFit:\n" << " wts[0]*wts[0]*invB(0, 0) = " << wts[0]*wts[0]*invB(0, 0) << nl << " wts[0]*wts[1]*invB(0, 1) = " << wts[0]*wts[1]*invB(0, 1) << " dim = " << this->dim() << endl; wts[0] *= 10; wts[1] *= 10; for (label j = 0; j < B.n(); j++) { B(0, j) *= 10; B(1, j) *= 10; } for (label i = 0; i < B.m(); i++) { B(i, 0) *= 10; B(i, 1) *= 10; } } } if (goodFit) { // Remove the uncorrected coefficients coeffsi[0] += deltaCoeff; coeffsi[1] -= deltaCoeff; } else { WarningInFunction << "Could not fit face " << facei << " Coefficients = " << coeffsi << ", reverting to uncorrected." << endl; coeffsi = 0; } }