/// @brief Computes total absorbed polymer mass over all grid cells. /// With compressibility /// @param[in] grid grid /// @param[in] props fluid and rock properties. /// @param[in] polyprops polymer properties /// @param[in] state fluid state variable /// @param[in] rock_comp rock compressibility (depends on pressure) /// @return total absorbed polymer mass. double computePolymerAdsorbed(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const Opm::PolymerProperties& polyprops, const PolymerBlackoilState& state, const RockCompressibility* rock_comp ) { const int num_cells = props.numCells(); const double rhor = polyprops.rockDensity(); std::vector<double> porosity; if (rock_comp && rock_comp->isActive()) { computePorosity(grid, props.porosity(), *rock_comp, state.pressure(), porosity); } else { porosity.assign(props.porosity(), props.porosity() + num_cells); } double abs_mass = 0.0; const std::vector<double>& cmax = state.getCellData( state.CMAX ); for (int cell = 0; cell < num_cells; ++cell) { double c_ads; polyprops.simpleAdsorption(cmax[cell], c_ads); abs_mass += c_ads*grid.cell_volumes[cell]*(1.0 - porosity[cell])*rhor; } return abs_mass; }
/// Construct solver. /// \param[in] grid A 2d or 3d grid. /// \param[in] props Rock and fluid properties. /// \param[in] linsolver Linear solver to use. /// \param[in] residual_tol Solution accepted if inf-norm of residual is smaller. /// \param[in] change_tol Solution accepted if inf-norm of change in pressure is smaller. /// \param[in] maxiter Maximum acceptable number of iterations. /// \param[in] gravity Gravity vector. If non-null, the array should /// have D elements. /// \param[in] wells The wells argument. Will be used in solution, /// is ignored if NULL. /// Note: this class observes the well object, and /// makes the assumption that the well topology /// and completions does not change during the /// run. However, controls (only) are allowed /// to change. CompressibleTpfa::CompressibleTpfa(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const RockCompressibility* rock_comp_props, const LinearSolverInterface& linsolver, const double residual_tol, const double change_tol, const int maxiter, const double* gravity, const struct Wells* wells) : grid_(grid), props_(props), rock_comp_props_(rock_comp_props), linsolver_(linsolver), residual_tol_(residual_tol), change_tol_(change_tol), maxiter_(maxiter), gravity_(gravity), wells_(wells), htrans_(grid.cell_facepos[ grid.number_of_cells ]), trans_ (grid.number_of_faces), allcells_(grid.number_of_cells), singular_(false) { if (wells_ && (wells_->number_of_phases != props.numPhases())) { OPM_THROW(std::runtime_error, "Inconsistent number of phases specified (wells vs. props): " << wells_->number_of_phases << " != " << props.numPhases()); } const int num_dofs = grid.number_of_cells + (wells ? wells->number_of_wells : 0); pressure_increment_.resize(num_dofs); UnstructuredGrid* gg = const_cast<UnstructuredGrid*>(&grid_); tpfa_htrans_compute(gg, props.permeability(), &htrans_[0]); tpfa_trans_compute(gg, &htrans_[0], &trans_[0]); // If we have rock compressibility, pore volumes are updated // in the compute*() methods, otherwise they are constant and // hence may be computed here. if (rock_comp_props_ == NULL || !rock_comp_props_->isActive()) { computePorevolume(grid_, props.porosity(), porevol_); } for (int c = 0; c < grid.number_of_cells; ++c) { allcells_[c] = c; } cfs_tpfa_res_wells w; w.W = const_cast<struct Wells*>(wells_); w.data = NULL; h_ = cfs_tpfa_res_construct(gg, &w, props.numPhases()); }