void TransportSolverCompressibleTwophaseReorder::initGravity(const double* grav) { // Set up transmissibilities. std::vector<double> htrans(grid_.cell_facepos[grid_.number_of_cells]); const int nf = grid_.number_of_faces; trans_.resize(nf); gravflux_.resize(nf); tpfa_htrans_compute(const_cast<UnstructuredGrid*>(&grid_), props_.permeability(), &htrans[0]); tpfa_trans_compute(const_cast<UnstructuredGrid*>(&grid_), &htrans[0], &trans_[0]); // Remember gravity vector. gravity_ = grav; }
/// 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()); }
void init(const Grid& grid, const double* perm, const double* porosity, const typename Grid::Vector& gravity) { // Build C grid structure. grid_.init(grid); // Initialize data. int num_phases = 3; well_t* w = 0; if (wells_.number_of_wells != 0) { w = &wells_; } data_ = cfs_tpfa_construct(grid_.c_grid(), w, num_phases); if (!data_) { throw std::runtime_error("Failed to initialize cfs_tpfa solver."); } // Compute half-transmissibilities int num_cells = grid.numCells(); int ngconn = grid_.c_grid()->cell_facepos[num_cells]; ncf_.resize(num_cells); for (int cell = 0; cell < num_cells; ++cell) { int num_local_faces = grid.numCellFaces(cell); ncf_[cell] = num_local_faces; } htrans_.resize(ngconn); tpfa_htrans_compute(grid_.c_grid(), perm, &htrans_[0]); // Compute transmissibilities. trans_.resize(grid_.numFaces()); tpfa_trans_compute(grid_.c_grid(), &htrans_[0], &trans_[0]); // Compute pore volumes. porevol_.resize(num_cells); for (int i = 0; i < num_cells; ++i) { porevol_[i] = porosity[i]*grid.cellVolume(i); } // Set gravity. if (Grid::dimension != 3) { throw std::logic_error("Only 3 dimensions supported currently."); } std::copy(gravity.begin(), gravity.end(), gravity_); state_ = Initialized; }
DerivedGeology(const UnstructuredGrid& grid, const Props& props , const double* grav = 0) : pvol_ (grid.number_of_cells) , trans_(grid.number_of_faces) , gpot_ (Vector::Zero(grid.cell_facepos[ grid.number_of_cells ], 1)) { // Pore volume const typename Vector::Index nc = grid.number_of_cells; std::transform(grid.cell_volumes, grid.cell_volumes + nc, props.porosity(), pvol_.data(), std::multiplies<double>()); // Transmissibility Vector htrans(grid.cell_facepos[nc]); UnstructuredGrid* ug = const_cast<UnstructuredGrid*>(& grid); tpfa_htrans_compute(ug, props.permeability(), htrans.data()); tpfa_trans_compute (ug, htrans.data() , trans_.data()); // Gravity potential std::fill(gravity_, gravity_ + 3, 0.0); if (grav != 0) { const typename Vector::Index nd = grid.dimensions; for (typename Vector::Index c = 0; c < nc; ++c) { const double* const cc = & grid.cell_centroids[c*nd + 0]; const int* const p = grid.cell_facepos; for (int i = p[c]; i < p[c + 1]; ++i) { const int f = grid.cell_faces[i]; const double* const fc = & grid.face_centroids[f*nd + 0]; for (typename Vector::Index d = 0; d < nd; ++d) { gpot_[i] += grav[d] * (fc[d] - cc[d]); } } } std::copy(grav, grav + nd, gravity_); } }
void TransportSolverTwophaseReorder::initGravity(const double* grav) { // Set up gravflux_ = T_ij g (rho_w - rho_o) (z_i - z_j) std::vector<double> htrans(grid_.cell_facepos[grid_.number_of_cells]); const int nf = grid_.number_of_faces; const int dim = grid_.dimensions; gravflux_.resize(nf); tpfa_htrans_compute(const_cast<UnstructuredGrid*>(&grid_), props_.permeability(), &htrans[0]); tpfa_trans_compute(const_cast<UnstructuredGrid*>(&grid_), &htrans[0], &gravflux_[0]); const double delta_rho = props_.density()[0] - props_.density()[1]; for (int f = 0; f < nf; ++f) { const int* c = &grid_.face_cells[2*f]; double gdz = 0.0; if (c[0] != -1 && c[1] != -1) { for (int d = 0; d < dim; ++d) { gdz += grav[d]*(grid_.cell_centroids[dim*c[0] + d] - grid_.cell_centroids[dim*c[1] + d]); } } gravflux_[f] *= delta_rho*gdz; } }