From 527f2aef52761e1131a5ae9de2a4747681c2ce1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Mon, 2 Jul 2012 17:44:16 +0200 Subject: [PATCH 01/58] Initialise all members in default constructor. --- opm/core/fluid/SaturationPropsBasic.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/opm/core/fluid/SaturationPropsBasic.cpp b/opm/core/fluid/SaturationPropsBasic.cpp index 4f20bd1b5..8249a31f1 100644 --- a/opm/core/fluid/SaturationPropsBasic.cpp +++ b/opm/core/fluid/SaturationPropsBasic.cpp @@ -99,6 +99,7 @@ namespace Opm /// Default constructor. SaturationPropsBasic::SaturationPropsBasic() + : num_phases_(0), relperm_func_(Constant) { } From 81f4ab5dd9f239bf733b830776f687f6f906687d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 3 Jul 2012 01:30:18 +0200 Subject: [PATCH 02/58] Add partial Doxygen markup to public interfaces. More work needed. --- opm/core/pressure/tpfa/ifs_tpfa.h | 65 ++++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 13 deletions(-) diff --git a/opm/core/pressure/tpfa/ifs_tpfa.h b/opm/core/pressure/tpfa/ifs_tpfa.h index f7ab4230e..d7853bef2 100644 --- a/opm/core/pressure/tpfa/ifs_tpfa.h +++ b/opm/core/pressure/tpfa/ifs_tpfa.h @@ -20,6 +20,16 @@ #ifndef OPM_IFS_TPFA_HEADER_INCLUDED #define OPM_IFS_TPFA_HEADER_INCLUDED +/** + * \file + * Interfaces and data structures to assemble a system of simultaneous linear + * equations discretising a flow problem that is either incompressible or + * features rock compressibility using the two-point flux approximation method. + * + * Includes support for reconstructing the Darcy flux field as well as well + * connection fluxes. + */ + #include #ifdef __cplusplus @@ -31,37 +41,66 @@ struct CSRMatrix; struct FlowBoundaryConditions; struct Wells; +/** + * Main data structure presenting a view of an assembled system of simultaneous + * linear equations which may be solved using external software. + */ struct ifs_tpfa_data { - struct CSRMatrix *A; - double *b; - double *x; + struct CSRMatrix *A; /**< Coefficient matrix */ + double *b; /**< Right-hand side */ + double *x; /**< Solution */ - struct ifs_tpfa_impl *pimpl; + struct ifs_tpfa_impl *pimpl; /**< Internal management structure */ }; +/** + * Solution variables. + */ struct ifs_tpfa_solution { - double *cell_press; - double *face_flux ; + double *cell_press; /**< Cell pressures */ + double *face_flux ; /**< Interface fluxes */ - double *well_press; /* BHP */ - double *well_flux ; /* Perforation (total) fluxes */ + double *well_press; /**< Bottom-hole pressures for each well */ + double *well_flux ; /**< Well connection total fluxes */ }; +/** + * Driving forces pertaining to a particular model setup. + */ struct ifs_tpfa_forces { - const double *src; - const struct FlowBoundaryConditions *bc ; + const double *src; /**< Explicit source terms */ + const struct FlowBoundaryConditions *bc ; /**< Boundary conditions */ - const struct Wells *W ; - const double *totmob; - const double *wdp ; + const struct Wells *W ; /**< Well topology */ + const double *totmob; /**< Total mobility in each cell */ + const double *wdp ; /**< Gravity adjustment at each perforation */ }; +/** + * Allocate TPFA management structure capable of assembling a system of + * simultaneous linear equations corresponding to a particular grid and well + * configuration. + * + * @param[in] G Grid. + * @param[in] W Well topology. + * @return Fully formed TPFA management structure if successful, @c NULL in case + * of allocation failure. + */ struct ifs_tpfa_data * ifs_tpfa_construct(struct UnstructuredGrid *G, struct Wells *W); +/** + * + * @param[in] G + * @param[in] F + * @param[in] trans + * @param[in] gpress + * @param[in,out] h + * @return + */ int ifs_tpfa_assemble(struct UnstructuredGrid *G , const struct ifs_tpfa_forces *F , From 52a5aabf57a32abd7a25b31d651382ade5d48916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Thu, 12 Jul 2012 14:36:36 +0200 Subject: [PATCH 03/58] Use have_boost_redef.hpp rather than direct override. --- opm/core/linalg/LinearSolverIstl.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/opm/core/linalg/LinearSolverIstl.cpp b/opm/core/linalg/LinearSolverIstl.cpp index 791fcb179..3c4435e8e 100644 --- a/opm/core/linalg/LinearSolverIstl.cpp +++ b/opm/core/linalg/LinearSolverIstl.cpp @@ -24,10 +24,7 @@ #include -// Work around the fact that istl headers expect -// HAVE_BOOST to be 1, and not just defined. -#undef HAVE_BOOST -#define HAVE_BOOST 1 +#include // TODO: clean up includes. #include From eb7d46accf3f784e491787a45d24bc73ea268fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 19 Jul 2012 14:02:26 +0200 Subject: [PATCH 04/58] Transport solver partially complete (segregation solver remains). --- .../TransportModelCompressibleTwophase.cpp | 38 ++++++++++--------- .../TransportModelCompressibleTwophase.hpp | 4 ++ 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index c04aac0a3..8d221f924 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -76,6 +76,7 @@ namespace Opm void TransportModelCompressibleTwophase::solve(const double* darcyflux, const double* pressure, const double* surfacevol0, + const double* porevolume0, const double* porevolume, const double* source, const double dt, @@ -83,6 +84,7 @@ namespace Opm { darcyflux_ = darcyflux; surfacevol0_ = surfacevol0; + porevolume0_ = porevolume0; porevolume_ = porevolume; source_ = source; dt_ = dt; @@ -111,37 +113,38 @@ namespace Opm // // [[ incompressible was: r(s) = s - s0 + dt/pv*( influx + outflux*f(s) ) ]] // - // r(s) = s - B*z0 + dt/pv*( influx + outflux*f(s)) + // r(s) = s - B*z0 + dt/pv*( influx + outflux*f(s) ) // // @@@ What about the source term // // where influx is water influx, outflux is total outflux. - // We need the formula influx = B_i sum_{j->i} b_j v_{ij} + q_w. - // outflux = B_i sum_{i->j} b_i v_{ij} - q = sum_{i->j} v_{ij} - q (as before) + // We need the formula influx = B_i sum_{j->i} b_j v_{ij} - B_i q_w. + // outflux = B_i sum_{i->j} b_i v_{ij} - B_i q = sum_{i->j} v_{ij} - B_i q // Influxes are negative, outfluxes positive. struct TransportModelCompressibleTwophase::Residual { int cell; - double s0; - double influx; // sum_j min(v_ij, 0)*f(s_j) + q_w // TODO: fix comment. - double outflux; // sum_j max(v_ij, 0) - q + double B_cell; + double z0; + double influx; // B_i sum_j b_j min(v_ij, 0)*f(s_j) - B_i q_w + double outflux; // sum_j max(v_ij, 0) - B_i q // @@@ TODO: figure out change to rock-comp. terms with fluid compr. - // double comp_term; // q - sum_j v_ij + double comp_term; // Now: used to be: q - sum_j v_ij double dtpv; // dt/pv(i) const TransportModelCompressibleTwophase& tm; explicit Residual(const TransportModelCompressibleTwophase& tmodel, int cell_index) : tm(tmodel) { cell = cell_index; - s0 = tm.saturation_[cell]; const int np = tm.props_.numPhases(); - const double B_cell = 1.0/tm.A_[np*np*cell + 0]; + z0 = tm.surfacevol0_[np*cell + 0]; // I.e. water surface volume + B_cell = 1.0/tm.A_[np*np*cell + 0]; double src_flux = -tm.source_[cell]; bool src_is_inflow = src_flux < 0.0; - influx = src_is_inflow ? src_flux : 0.0; - outflux = !src_is_inflow ? src_flux : 0.0; - // comp_term = tm.source_[cell]; // Note: this assumes that all source flux is water. - dtpv = tm.dt_/tm.porevolume_[cell]; + influx = src_is_inflow ? B_cell*src_flux : 0.0; + outflux = !src_is_inflow ? B_cell*src_flux : 0.0; + comp_term = (tm.porevolume_[cell] - tm.porevolume0_[cell])/tm.porevolume0_[cell]; + dtpv = tm.dt_/tm.porevolume0_[cell]; for (int i = tm.grid_.cell_facepos[cell]; i < tm.grid_.cell_facepos[cell+1]; ++i) { const int f = tm.grid_.cell_faces[i]; double flux; @@ -160,16 +163,15 @@ namespace Opm const double b_face = tm.A_[np*np*other + 0]; influx += B_cell*b_face*flux*tm.fractionalflow_[other]; } else { - outflux += flux; + outflux += flux; // Because B_cell*b_face = 1 for outflow faces } - // comp_term -= flux; } } } double operator()(double s) const { // return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx + s*comp_term); - return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx); + return s - B_cell*z0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx) + s*comp_term; } }; @@ -333,7 +335,7 @@ namespace Opm gf[1] = gravflux[pos]; } s0 = tm.saturation_[cell]; - dtpv = tm.dt_/tm.porevolume_[cell]; + dtpv = tm.dt_/tm.porevolume0_[cell]; } double operator()(double s) const @@ -467,6 +469,7 @@ namespace Opm void TransportModelCompressibleTwophase::solveGravity(const std::vector >& columns, const double* pressure, + const double* porevolume0, const double* porevolume, const double dt, std::vector& saturation) @@ -489,6 +492,7 @@ namespace Opm } // Set up other variables. + porevolume0_ = porevolume0; porevolume_ = porevolume; dt_ = dt; toWaterSat(saturation, saturation_); diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index d41deef6e..fda83fbcf 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -47,6 +47,7 @@ namespace Opm /// \param[in] darcyflux Array of signed face fluxes. /// \param[in] pressure Array of cell pressures /// \param[in] surfacevol0 Array of surface volumes at start of timestep + /// \param[in] porevolume0 Array of pore volumes at start of timestep. /// \param[in] porevolume Array of pore volumes. /// \param[in] source Transport source term. /// \param[in] dt Time step. @@ -54,6 +55,7 @@ namespace Opm void solve(const double* darcyflux, const double* pressure, const double* surfacevol0, + const double* porevolume0, const double* porevolume, const double* source, const double dt, @@ -71,6 +73,7 @@ namespace Opm /// \TODO: Implement this. void solveGravity(const std::vector >& columns, const double* pressure, + const double* porevolume0, const double* porevolume, const double dt, std::vector& saturation); @@ -96,6 +99,7 @@ namespace Opm const double* darcyflux_; // one flux per grid face const double* surfacevol0_; // one per phase per cell + const double* porevolume0_; // one volume per cell const double* porevolume_; // one volume per cell const double* source_; // one source per cell double dt_; From 937b85e88f22e666b7913dd304abc66e3ed380df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 19 Jul 2012 14:45:15 +0200 Subject: [PATCH 05/58] Bugfix in CompressibleTpfa for gravity case. Gravity acceleration should be a factor in the face gravity potential. --- opm/core/pressure/CompressibleTpfa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/pressure/CompressibleTpfa.cpp b/opm/core/pressure/CompressibleTpfa.cpp index 7d936d6e9..154f06336 100644 --- a/opm/core/pressure/CompressibleTpfa.cpp +++ b/opm/core/pressure/CompressibleTpfa.cpp @@ -341,7 +341,7 @@ namespace Opm const double depth_diff = face_depth - grid_.cell_centroids[c[j]*dim + dim - 1]; props_.density(1, &cell_A_[np*np*c[j]], &gravcontrib[j][0]); for (int p = 0; p < np; ++p) { - gravcontrib[j][p] *= depth_diff; + gravcontrib[j][p] *= depth_diff*grav; } } else { std::fill(gravcontrib[j].begin(), gravcontrib[j].end(), 0.0); From 6ab748721836f04890f55cc41f5c2d0fbd09d3a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 19 Jul 2012 15:34:42 +0200 Subject: [PATCH 06/58] Whitespace cleanup. --- .../TransportModelCompressibleTwophase.cpp | 460 +++++++++--------- 1 file changed, 230 insertions(+), 230 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index 8d221f924..ce8ebb97e 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -39,38 +39,38 @@ namespace Opm TransportModelCompressibleTwophase::TransportModelCompressibleTwophase(const UnstructuredGrid& grid, - const Opm::BlackoilPropertiesInterface& props, - const double tol, - const int maxit) - : grid_(grid), - props_(props), - tol_(tol), - maxit_(maxit), - darcyflux_(0), - source_(0), - dt_(0.0), - saturation_(grid.number_of_cells, -1.0), - fractionalflow_(grid.number_of_cells, -1.0), - mob_(2*grid.number_of_cells, -1.0), + const Opm::BlackoilPropertiesInterface& props, + const double tol, + const int maxit) + : grid_(grid), + props_(props), + tol_(tol), + maxit_(maxit), + darcyflux_(0), + source_(0), + dt_(0.0), + saturation_(grid.number_of_cells, -1.0), + fractionalflow_(grid.number_of_cells, -1.0), + mob_(2*grid.number_of_cells, -1.0), ia_upw_(grid.number_of_cells + 1, -1), - ja_upw_(grid.number_of_faces, -1), - ia_downw_(grid.number_of_cells + 1, -1), - ja_downw_(grid.number_of_faces, -1) + ja_upw_(grid.number_of_faces, -1), + ia_downw_(grid.number_of_cells + 1, -1), + ja_downw_(grid.number_of_faces, -1) { - if (props.numPhases() != 2) { - THROW("Property object must have 2 phases"); - } + if (props.numPhases() != 2) { + THROW("Property object must have 2 phases"); + } int np = props.numPhases(); - int num_cells = props.numCells(); - visc_.resize(np*num_cells); + int num_cells = props.numCells(); + visc_.resize(np*num_cells); A_.resize(np*np*num_cells); - smin_.resize(np*num_cells); - smax_.resize(np*num_cells); - allcells_.resize(num_cells); - for (int i = 0; i < num_cells; ++i) { - allcells_[i] = i; - } - props.satRange(props.numCells(), &allcells_[0], &smin_[0], &smax_[0]); + smin_.resize(np*num_cells); + smax_.resize(np*num_cells); + allcells_.resize(num_cells); + for (int i = 0; i < num_cells; ++i) { + allcells_[i] = i; + } + props.satRange(props.numCells(), &allcells_[0], &smin_[0], &smax_[0]); } void TransportModelCompressibleTwophase::solve(const double* darcyflux, @@ -82,30 +82,30 @@ namespace Opm const double dt, std::vector& saturation) { - darcyflux_ = darcyflux; + darcyflux_ = darcyflux; surfacevol0_ = surfacevol0; porevolume0_ = porevolume0; porevolume_ = porevolume; - source_ = source; - dt_ = dt; + source_ = source; + dt_ = dt; toWaterSat(saturation, saturation_); props_.viscosity(props_.numCells(), pressure, NULL, &allcells_[0], &visc_[0], NULL); props_.matrix(props_.numCells(), pressure, NULL, &allcells_[0], &A_[0], NULL); - std::vector seq(grid_.number_of_cells); - std::vector comp(grid_.number_of_cells + 1); - int ncomp; - compute_sequence_graph(&grid_, darcyflux_, - &seq[0], &comp[0], &ncomp, - &ia_upw_[0], &ja_upw_[0]); - const int nf = grid_.number_of_faces; - std::vector neg_darcyflux(nf); - std::transform(darcyflux, darcyflux + nf, neg_darcyflux.begin(), std::negate()); - compute_sequence_graph(&grid_, &neg_darcyflux[0], - &seq[0], &comp[0], &ncomp, - &ia_downw_[0], &ja_downw_[0]); - reorderAndTransport(grid_, darcyflux); + std::vector seq(grid_.number_of_cells); + std::vector comp(grid_.number_of_cells + 1); + int ncomp; + compute_sequence_graph(&grid_, darcyflux_, + &seq[0], &comp[0], &ncomp, + &ia_upw_[0], &ja_upw_[0]); + const int nf = grid_.number_of_faces; + std::vector neg_darcyflux(nf); + std::transform(darcyflux, darcyflux + nf, neg_darcyflux.begin(), std::negate()); + compute_sequence_graph(&grid_, &neg_darcyflux[0], + &seq[0], &comp[0], &ncomp, + &ia_downw_[0], &ja_downw_[0]); + reorderAndTransport(grid_, darcyflux); toBothSat(saturation_, saturation); } @@ -116,187 +116,187 @@ namespace Opm // r(s) = s - B*z0 + dt/pv*( influx + outflux*f(s) ) // // @@@ What about the source term - // + // // where influx is water influx, outflux is total outflux. // We need the formula influx = B_i sum_{j->i} b_j v_{ij} - B_i q_w. // outflux = B_i sum_{i->j} b_i v_{ij} - B_i q = sum_{i->j} v_{ij} - B_i q // Influxes are negative, outfluxes positive. struct TransportModelCompressibleTwophase::Residual { - int cell; + int cell; double B_cell; - double z0; - double influx; // B_i sum_j b_j min(v_ij, 0)*f(s_j) - B_i q_w - double outflux; // sum_j max(v_ij, 0) - B_i q + double z0; + double influx; // B_i sum_j b_j min(v_ij, 0)*f(s_j) - B_i q_w + double outflux; // sum_j max(v_ij, 0) - B_i q // @@@ TODO: figure out change to rock-comp. terms with fluid compr. double comp_term; // Now: used to be: q - sum_j v_ij - double dtpv; // dt/pv(i) - const TransportModelCompressibleTwophase& tm; - explicit Residual(const TransportModelCompressibleTwophase& tmodel, int cell_index) - : tm(tmodel) - { - cell = cell_index; + double dtpv; // dt/pv(i) + const TransportModelCompressibleTwophase& tm; + explicit Residual(const TransportModelCompressibleTwophase& tmodel, int cell_index) + : tm(tmodel) + { + cell = cell_index; const int np = tm.props_.numPhases(); - z0 = tm.surfacevol0_[np*cell + 0]; // I.e. water surface volume + z0 = tm.surfacevol0_[np*cell + 0]; // I.e. water surface volume B_cell = 1.0/tm.A_[np*np*cell + 0]; double src_flux = -tm.source_[cell]; bool src_is_inflow = src_flux < 0.0; - influx = src_is_inflow ? B_cell*src_flux : 0.0; - outflux = !src_is_inflow ? B_cell*src_flux : 0.0; + influx = src_is_inflow ? B_cell*src_flux : 0.0; + outflux = !src_is_inflow ? B_cell*src_flux : 0.0; comp_term = (tm.porevolume_[cell] - tm.porevolume0_[cell])/tm.porevolume0_[cell]; - dtpv = tm.dt_/tm.porevolume0_[cell]; - for (int i = tm.grid_.cell_facepos[cell]; i < tm.grid_.cell_facepos[cell+1]; ++i) { - const int f = tm.grid_.cell_faces[i]; - double flux; - int other; - // Compute cell flux - if (cell == tm.grid_.face_cells[2*f]) { - flux = tm.darcyflux_[f]; - other = tm.grid_.face_cells[2*f+1]; - } else { - flux =-tm.darcyflux_[f]; - other = tm.grid_.face_cells[2*f]; - } - // Add flux to influx or outflux, if interior. - if (other != -1) { - if (flux < 0.0) { + dtpv = tm.dt_/tm.porevolume0_[cell]; + for (int i = tm.grid_.cell_facepos[cell]; i < tm.grid_.cell_facepos[cell+1]; ++i) { + const int f = tm.grid_.cell_faces[i]; + double flux; + int other; + // Compute cell flux + if (cell == tm.grid_.face_cells[2*f]) { + flux = tm.darcyflux_[f]; + other = tm.grid_.face_cells[2*f+1]; + } else { + flux =-tm.darcyflux_[f]; + other = tm.grid_.face_cells[2*f]; + } + // Add flux to influx or outflux, if interior. + if (other != -1) { + if (flux < 0.0) { const double b_face = tm.A_[np*np*other + 0]; - influx += B_cell*b_face*flux*tm.fractionalflow_[other]; - } else { - outflux += flux; // Because B_cell*b_face = 1 for outflow faces - } - } - } - } - double operator()(double s) const - { - // return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx + s*comp_term); - return s - B_cell*z0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx) + s*comp_term; - } + influx += B_cell*b_face*flux*tm.fractionalflow_[other]; + } else { + outflux += flux; // Because B_cell*b_face = 1 for outflow faces + } + } + } + } + double operator()(double s) const + { + // return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx + s*comp_term); + return s - B_cell*z0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx) + s*comp_term; + } }; void TransportModelCompressibleTwophase::solveSingleCell(const int cell) { - Residual res(*this, cell); - int iters_used; - saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); - fractionalflow_[cell] = fracFlow(saturation_[cell], cell); + Residual res(*this, cell); + int iters_used; + saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); + fractionalflow_[cell] = fracFlow(saturation_[cell], cell); } void TransportModelCompressibleTwophase::solveMultiCell(const int num_cells, const int* cells) { - // Experiment: when a cell changes more than the tolerance, - // mark all downwind cells as needing updates. After - // computing a single update in each cell, use marks - // to guide further updating. Clear mark in cell when - // its solution gets updated. - // Verdict: this is a good one! Approx. halved total time. - std::vector needs_update(num_cells, 1); - // This one also needs the mapping from all cells to - // the strongly connected subset to filter out connections - std::vector pos(grid_.number_of_cells, -1); - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - pos[cell] = i; - } + // Experiment: when a cell changes more than the tolerance, + // mark all downwind cells as needing updates. After + // computing a single update in each cell, use marks + // to guide further updating. Clear mark in cell when + // its solution gets updated. + // Verdict: this is a good one! Approx. halved total time. + std::vector needs_update(num_cells, 1); + // This one also needs the mapping from all cells to + // the strongly connected subset to filter out connections + std::vector pos(grid_.number_of_cells, -1); + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + pos[cell] = i; + } - // Note: partially copied from below. - const double tol = 1e-9; - const int max_iters = 300; - // Must store s0 before we start. - std::vector s0(num_cells); - // Must set initial fractional flows before we start. - // Also, we compute the # of upstream neighbours. - // std::vector num_upstream(num_cells); - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - fractionalflow_[cell] = fracFlow(saturation_[cell], cell); - s0[i] = saturation_[cell]; - // num_upstream[i] = ia_upw_[cell + 1] - ia_upw_[cell]; - } - // Solve once in each cell. - // std::vector fully_marked_stack; - // fully_marked_stack.reserve(num_cells); - int num_iters = 0; - int update_count = 0; // Change name/meaning to cells_updated? - do { - update_count = 0; // Must reset count for every iteration. - for (int i = 0; i < num_cells; ++i) { - // while (!fully_marked_stack.empty()) { - // // std::cout << "# fully marked cells = " << fully_marked_stack.size() << std::endl; - // const int fully_marked_ci = fully_marked_stack.back(); - // fully_marked_stack.pop_back(); - // ++update_count; - // const int cell = cells[fully_marked_ci]; - // const double old_s = saturation_[cell]; - // saturation_[cell] = s0[fully_marked_ci]; - // solveSingleCell(cell); - // const double s_change = std::fabs(saturation_[cell] - old_s); - // if (s_change > tol) { - // // Mark downwind cells. - // for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { - // const int downwind_cell = ja_downw_[j]; - // int ci = pos[downwind_cell]; - // ++needs_update[ci]; - // if (needs_update[ci] == num_upstream[ci]) { - // fully_marked_stack.push_back(ci); - // } - // } - // } - // // Unmark this cell. - // needs_update[fully_marked_ci] = 0; - // } - if (!needs_update[i]) { - continue; - } - ++update_count; - const int cell = cells[i]; - const double old_s = saturation_[cell]; - saturation_[cell] = s0[i]; - solveSingleCell(cell); - const double s_change = std::fabs(saturation_[cell] - old_s); - if (s_change > tol) { - // Mark downwind cells. - for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { - const int downwind_cell = ja_downw_[j]; - int ci = pos[downwind_cell]; + // Note: partially copied from below. + const double tol = 1e-9; + const int max_iters = 300; + // Must store s0 before we start. + std::vector s0(num_cells); + // Must set initial fractional flows before we start. + // Also, we compute the # of upstream neighbours. + // std::vector num_upstream(num_cells); + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + fractionalflow_[cell] = fracFlow(saturation_[cell], cell); + s0[i] = saturation_[cell]; + // num_upstream[i] = ia_upw_[cell + 1] - ia_upw_[cell]; + } + // Solve once in each cell. + // std::vector fully_marked_stack; + // fully_marked_stack.reserve(num_cells); + int num_iters = 0; + int update_count = 0; // Change name/meaning to cells_updated? + do { + update_count = 0; // Must reset count for every iteration. + for (int i = 0; i < num_cells; ++i) { + // while (!fully_marked_stack.empty()) { + // // std::cout << "# fully marked cells = " << fully_marked_stack.size() << std::endl; + // const int fully_marked_ci = fully_marked_stack.back(); + // fully_marked_stack.pop_back(); + // ++update_count; + // const int cell = cells[fully_marked_ci]; + // const double old_s = saturation_[cell]; + // saturation_[cell] = s0[fully_marked_ci]; + // solveSingleCell(cell); + // const double s_change = std::fabs(saturation_[cell] - old_s); + // if (s_change > tol) { + // // Mark downwind cells. + // for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { + // const int downwind_cell = ja_downw_[j]; + // int ci = pos[downwind_cell]; + // ++needs_update[ci]; + // if (needs_update[ci] == num_upstream[ci]) { + // fully_marked_stack.push_back(ci); + // } + // } + // } + // // Unmark this cell. + // needs_update[fully_marked_ci] = 0; + // } + if (!needs_update[i]) { + continue; + } + ++update_count; + const int cell = cells[i]; + const double old_s = saturation_[cell]; + saturation_[cell] = s0[i]; + solveSingleCell(cell); + const double s_change = std::fabs(saturation_[cell] - old_s); + if (s_change > tol) { + // Mark downwind cells. + for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { + const int downwind_cell = ja_downw_[j]; + int ci = pos[downwind_cell]; if (ci != -1) { needs_update[ci] = 1; } - // ++needs_update[ci]; - // if (needs_update[ci] == num_upstream[ci]) { - // fully_marked_stack.push_back(ci); - // } - } - } - // Unmark this cell. - needs_update[i] = 0; - } - // std::cout << "Iter = " << num_iters << " update_count = " << update_count - // << " # marked cells = " - // << std::accumulate(needs_update.begin(), needs_update.end(), 0) << std::endl; - } while (update_count > 0 && ++num_iters < max_iters); + // ++needs_update[ci]; + // if (needs_update[ci] == num_upstream[ci]) { + // fully_marked_stack.push_back(ci); + // } + } + } + // Unmark this cell. + needs_update[i] = 0; + } + // std::cout << "Iter = " << num_iters << " update_count = " << update_count + // << " # marked cells = " + // << std::accumulate(needs_update.begin(), needs_update.end(), 0) << std::endl; + } while (update_count > 0 && ++num_iters < max_iters); - // Done with iterations, check if we succeeded. - if (update_count > 0) { - THROW("In solveMultiCell(), we did not converge after " - << num_iters << " iterations. Remaining update count = " << update_count); - } - std::cout << "Solved " << num_cells << " cell multicell problem in " - << num_iters << " iterations." << std::endl; + // Done with iterations, check if we succeeded. + if (update_count > 0) { + THROW("In solveMultiCell(), we did not converge after " + << num_iters << " iterations. Remaining update count = " << update_count); + } + std::cout << "Solved " << num_cells << " cell multicell problem in " + << num_iters << " iterations." << std::endl; } double TransportModelCompressibleTwophase::fracFlow(double s, int cell) const { - double sat[2] = { s, 1.0 - s }; - double mob[2]; - props_.relperm(1, sat, &cell, mob, 0); - mob[0] /= visc_[2*cell + 0]; - mob[1] /= visc_[2*cell + 1]; - return mob[0]/(mob[0] + mob[1]); + double sat[2] = { s, 1.0 - s }; + double mob[2]; + props_.relperm(1, sat, &cell, mob, 0); + mob[0] /= visc_[2*cell + 0]; + mob[1] /= visc_[2*cell + 1]; + return mob[0]/(mob[0] + mob[1]); } @@ -309,19 +309,19 @@ namespace Opm // struct TransportModelCompressibleTwophase::GravityResidual { - int cell; + int cell; int nbcell[2]; - double s0; - double dtpv; // dt/pv(i) + double s0; + double dtpv; // dt/pv(i) double gf[2]; - const TransportModelCompressibleTwophase& tm; - explicit GravityResidual(const TransportModelCompressibleTwophase& tmodel, + const TransportModelCompressibleTwophase& tm; + explicit GravityResidual(const TransportModelCompressibleTwophase& tmodel, const std::vector& cells, const int pos, const double* gravflux) // Always oriented towards next in column. Size = colsize - 1. - : tm(tmodel) - { - cell = cells[pos]; + : tm(tmodel) + { + cell = cells[pos]; nbcell[0] = -1; gf[0] = 0.0; if (pos > 0) { @@ -334,40 +334,40 @@ namespace Opm nbcell[1] = cells[pos + 1]; gf[1] = gravflux[pos]; } - s0 = tm.saturation_[cell]; - dtpv = tm.dt_/tm.porevolume0_[cell]; - - } - double operator()(double s) const - { - double res = s - s0; + s0 = tm.saturation_[cell]; + dtpv = tm.dt_/tm.porevolume0_[cell]; + + } + double operator()(double s) const + { + double res = s - s0; double mobcell[2]; tm.mobility(s, cell, mobcell); for (int nb = 0; nb < 2; ++nb) { - if (nbcell[nb] != -1) { + if (nbcell[nb] != -1) { double m[2]; if (gf[nb] < 0.0) { m[0] = mobcell[0]; m[1] = tm.mob_[2*nbcell[nb] + 1]; - } else { + } else { m[0] = tm.mob_[2*nbcell[nb]]; m[1] = mobcell[1]; - } - if (m[0] + m[1] > 0.0) { + } + if (m[0] + m[1] > 0.0) { res += -dtpv*gf[nb]*m[0]*m[1]/(m[0] + m[1]); } - } + } } return res; - } + } }; void TransportModelCompressibleTwophase::mobility(double s, int cell, double* mob) const { - double sat[2] = { s, 1.0 - s }; - props_.relperm(1, sat, &cell, mob, 0); - mob[0] /= visc_[0]; - mob[1] /= visc_[1]; + double sat[2] = { s, 1.0 - s }; + props_.relperm(1, sat, &cell, mob, 0); + mob[0] /= visc_[0]; + mob[1] /= visc_[1]; } @@ -409,7 +409,7 @@ namespace Opm saturation_[cell] = RootFinder::solve(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); } saturation_[cell] = std::min(std::max(saturation_[cell], smin_[2*cell]), smax_[2*cell]); - mobility(saturation_[cell], cell, &mob_[2*cell]); + mobility(saturation_[cell], cell, &mob_[2*cell]); } @@ -420,17 +420,17 @@ namespace Opm const int nc = cells.size(); std::vector col_gravflux(nc - 1); for (int ci = 0; ci < nc - 1; ++ci) { - const int cell = cells[ci]; - const int next_cell = cells[ci + 1]; - for (int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) { - const int face = grid_.cell_faces[j]; - const int c1 = grid_.face_cells[2*face + 0]; + const int cell = cells[ci]; + const int next_cell = cells[ci + 1]; + for (int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) { + const int face = grid_.cell_faces[j]; + const int c1 = grid_.face_cells[2*face + 0]; const int c2 = grid_.face_cells[2*face + 1]; - if (c1 == next_cell || c2 == next_cell) { + if (c1 == next_cell || c2 == next_cell) { const double gf = gravflux_[face]; col_gravflux[ci] = (c1 == cell) ? gf : -gf; - } - } + } + } } // Store initial saturation s0 @@ -440,7 +440,7 @@ namespace Opm } // Solve single cell problems, repeating if necessary. - double max_s_change = 0.0; + double max_s_change = 0.0; int num_iters = 0; do { max_s_change = 0.0; @@ -456,12 +456,12 @@ namespace Opm std::fabs(saturation_[cells[ci2]] - old_s[1]))); } // std::cout << "Iter = " << num_iters << " max_s_change = " << max_s_change << std::endl; - } while (max_s_change > tol_ && ++num_iters < maxit_); + } while (max_s_change > tol_ && ++num_iters < maxit_); - if (max_s_change > tol_) { - THROW("In solveGravityColumn(), we did not converge after " - << num_iters << " iterations. Delta s = " << max_s_change); - } + if (max_s_change > tol_) { + THROW("In solveGravityColumn(), we did not converge after " + << num_iters << " iterations. Delta s = " << max_s_change); + } return num_iters + 1; } From 497c45b78b10ca36caf976e5cd48526c628cb0c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 10 Aug 2012 10:12:45 +0200 Subject: [PATCH 07/58] Constructors of *FromDeck classes now take an UnstructuredGrid. This is a change from taking a vector containing the mapping to deck-consistent logical cartesian indices. The mapping is contained in the UnstructuredGrid::global_cell member, and may be null. The change therefore saves the overhead of constructing a vector as a copy of the data in the grid or (if null) as an identity mapping. --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 6 ++-- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 11 +++--- opm/core/fluid/IncompPropertiesFromDeck.cpp | 6 ++-- opm/core/fluid/IncompPropertiesFromDeck.hpp | 11 +++--- opm/core/fluid/RockFromDeck.cpp | 35 ++++++++++--------- opm/core/fluid/RockFromDeck.hpp | 12 ++++--- opm/core/fluid/SaturationPropsFromDeck.hpp | 11 ++++-- 7 files changed, 54 insertions(+), 38 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index 0eb23cb07..004e6f88f 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -23,11 +23,11 @@ namespace Opm { BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const std::vector& global_cell) + const UnstructuredGrid& grid) { - rock_.init(deck, global_cell); + rock_.init(deck, grid); pvt_.init(deck); - satprops_.init(deck, global_cell); + satprops_.init(deck, grid); if (pvt_.numPhases() != satprops_.numPhases()) { THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index 9c20b5683..a2a6c3de9 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -27,6 +27,8 @@ #include #include +struct UnstructuredGrid; + namespace Opm { @@ -35,12 +37,13 @@ namespace Opm class BlackoilPropertiesFromDeck : public BlackoilPropertiesInterface { public: - /// Construct from deck and cell mapping. - /// \param deck eclipse input parser - /// \param global_cell mapping from cell indices (typically from a processed grid) + /// Initialize from deck and grid. + /// \param deck Deck input parser + /// \param grid Grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const std::vector& global_cell); + const UnstructuredGrid& grid); /// Destructor. virtual ~BlackoilPropertiesFromDeck(); diff --git a/opm/core/fluid/IncompPropertiesFromDeck.cpp b/opm/core/fluid/IncompPropertiesFromDeck.cpp index e61e13c80..570154bf6 100644 --- a/opm/core/fluid/IncompPropertiesFromDeck.cpp +++ b/opm/core/fluid/IncompPropertiesFromDeck.cpp @@ -27,11 +27,11 @@ namespace Opm { IncompPropertiesFromDeck::IncompPropertiesFromDeck(const EclipseGridParser& deck, - const std::vector& global_cell) + const UnstructuredGrid& grid) { - rock_.init(deck, global_cell); + rock_.init(deck, grid); pvt_.init(deck); - satprops_.init(deck, global_cell); + satprops_.init(deck, grid); if (pvt_.numPhases() != satprops_.numPhases()) { THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data (" << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); diff --git a/opm/core/fluid/IncompPropertiesFromDeck.hpp b/opm/core/fluid/IncompPropertiesFromDeck.hpp index d17dd1b7d..68623e5cc 100644 --- a/opm/core/fluid/IncompPropertiesFromDeck.hpp +++ b/opm/core/fluid/IncompPropertiesFromDeck.hpp @@ -26,6 +26,8 @@ #include #include +struct UnstructuredGrid; + namespace Opm { @@ -43,12 +45,13 @@ namespace Opm class IncompPropertiesFromDeck : public IncompPropertiesInterface { public: - /// Construct from deck and cell mapping. - /// \param deck eclipse input parser - /// \param global_cell mapping from cell indices (typically from a processed grid) + /// Initialize from deck and grid. + /// \param deck Deck input parser + /// \param grid Grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. IncompPropertiesFromDeck(const EclipseGridParser& deck, - const std::vector& global_cell); + const UnstructuredGrid& grid); /// Destructor. virtual ~IncompPropertiesFromDeck(); diff --git a/opm/core/fluid/RockFromDeck.cpp b/opm/core/fluid/RockFromDeck.cpp index 947779047..6568e8cc3 100644 --- a/opm/core/fluid/RockFromDeck.cpp +++ b/opm/core/fluid/RockFromDeck.cpp @@ -19,7 +19,7 @@ #include - +#include #include namespace Opm @@ -53,28 +53,29 @@ namespace Opm /// Initialize from deck and cell mapping. /// \param deck Deck input parser - /// \param global_cell mapping from cell indices (typically from a processed grid) + /// \param grid grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. void RockFromDeck::init(const EclipseGridParser& deck, - const std::vector& global_cell) + const UnstructuredGrid& grid) { - assignPorosity(deck, global_cell); - permfield_valid_.assign(global_cell.size(), false); + assignPorosity(deck, grid); + permfield_valid_.assign(grid.number_of_cells, false); const double perm_threshold = 0.0; // Maybe turn into parameter? - assignPermeability(deck, global_cell, perm_threshold); + assignPermeability(deck, grid, perm_threshold); } void RockFromDeck::assignPorosity(const EclipseGridParser& parser, - const std::vector& global_cell) + const UnstructuredGrid& grid) { - porosity_.assign(global_cell.size(), 1.0); - + porosity_.assign(grid.number_of_cells, 1.0); + const int* gc = grid.global_cell; if (parser.hasField("PORO")) { const std::vector& poro = parser.getFloatingPointValue("PORO"); - for (int c = 0; c < int(porosity_.size()); ++c) { - porosity_[c] = poro[global_cell[c]]; + const int deck_pos = (gc == NULL) ? c : gc[c]; + porosity_[c] = poro[deck_pos]; } } } @@ -82,14 +83,16 @@ namespace Opm void RockFromDeck::assignPermeability(const EclipseGridParser& parser, - const std::vector& global_cell, + const UnstructuredGrid& grid, double perm_threshold) { const int dim = 3; const int num_global_cells = numGlobalCells(parser); + const int nc = grid.number_of_cells; + ASSERT (num_global_cells > 0); - permeability_.assign(dim * dim * global_cell.size(), 0.0); + permeability_.assign(dim * dim * nc, 0.0); std::vector*> tensor; tensor.reserve(10); @@ -111,13 +114,13 @@ namespace Opm // chosen) default value... // if (tensor.size() > 1) { - const int nc = global_cell.size(); - int off = 0; + const int* gc = grid.global_cell; + int off = 0; for (int c = 0; c < nc; ++c, off += dim*dim) { // SharedPermTensor K(dim, dim, &permeability_[off]); int kix = 0; - const int glob = global_cell[c]; + const int glob = (gc == NULL) ? c : gc[c]; for (int i = 0; i < dim; ++i) { for (int j = 0; j < dim; ++j, ++kix) { diff --git a/opm/core/fluid/RockFromDeck.hpp b/opm/core/fluid/RockFromDeck.hpp index abd9c14c3..65027e425 100644 --- a/opm/core/fluid/RockFromDeck.hpp +++ b/opm/core/fluid/RockFromDeck.hpp @@ -24,6 +24,7 @@ #include #include +struct UnstructuredGrid; namespace Opm { @@ -34,12 +35,13 @@ namespace Opm /// Default constructor. RockFromDeck(); - /// Initialize from deck and cell mapping. + /// Initialize from deck and grid. /// \param deck Deck input parser - /// \param global_cell mapping from cell indices (typically from a processed grid) + /// \param grid Grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. void init(const EclipseGridParser& deck, - const std::vector& global_cell); + const UnstructuredGrid& grid); /// \return D, the number of spatial dimensions. Always 3 for deck input. int numDimensions() const @@ -69,9 +71,9 @@ namespace Opm private: void assignPorosity(const EclipseGridParser& parser, - const std::vector& global_cell); + const UnstructuredGrid& grid); void assignPermeability(const EclipseGridParser& parser, - const std::vector& global_cell, + const UnstructuredGrid& grid, const double perm_threshold); std::vector porosity_; diff --git a/opm/core/fluid/SaturationPropsFromDeck.hpp b/opm/core/fluid/SaturationPropsFromDeck.hpp index 7c8be8d45..b83a12711 100644 --- a/opm/core/fluid/SaturationPropsFromDeck.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck.hpp @@ -25,6 +25,8 @@ #include #include +struct UnstructuredGrid; + namespace Opm { @@ -34,10 +36,13 @@ namespace Opm /// Default constructor. SaturationPropsFromDeck(); - /// Initialize from deck. - /// global_cell maps from grid cells to their original logical Cartesian indices. + /// Initialize from deck and grid. + /// \param deck Deck input parser + /// \param grid Grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) + /// to logical cartesian indices consistent with the deck. void init(const EclipseGridParser& deck, - const std::vector& global_cell); + const UnstructuredGrid& grid); /// \return P, the number of phases. int numPhases() const; From 1f7ec7fa39f58b63cc99f2cce7634f293a480a7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Tue, 14 Aug 2012 09:36:19 +0200 Subject: [PATCH 08/58] Changed to extrapolation outside tables for pormult. Added facetags to the grid structure. Changed default fluid to Linear. --- opm/core/fluid/RockCompressibility.cpp | 10 +++++++--- opm/core/fluid/SaturationPropsBasic.cpp | 3 ++- opm/core/linalg/LinearSolverFactory.cpp | 12 ++++++++++-- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/opm/core/fluid/RockCompressibility.cpp b/opm/core/fluid/RockCompressibility.cpp index 17d86bebc..104861013 100644 --- a/opm/core/fluid/RockCompressibility.cpp +++ b/opm/core/fluid/RockCompressibility.cpp @@ -69,7 +69,8 @@ namespace Opm const double cpnorm = rock_comp_*(pressure - pref_); return (1.0 + cpnorm + 0.5*cpnorm*cpnorm); } else { - return Opm::linearInterpolation(p_, poromult_, pressure); + // return Opm::linearInterpolation(p_, poromult_, pressure); + return Opm::linearInterpolationExtrap(p_, poromult_, pressure); } } @@ -78,8 +79,11 @@ namespace Opm if (p_.empty()) { return rock_comp_; } else { - const double poromult = Opm::linearInterpolation(p_, poromult_, pressure); - const double dporomultdp = Opm::linearInterpolationDerivative(p_, poromult_, pressure); + //const double poromult = Opm::linearInterpolation(p_, poromult_, pressure); + //const double dporomultdp = Opm::linearInterpolationDerivative(p_, poromult_, pressure); + const double poromult = Opm::linearInterpolationExtrap(p_, poromult_, pressure); + const double dporomultdp = Opm::linearInterpolationDerivativeExtrap(p_, poromult_, pressure); + return dporomultdp/poromult; } } diff --git a/opm/core/fluid/SaturationPropsBasic.cpp b/opm/core/fluid/SaturationPropsBasic.cpp index 8249a31f1..760f934d4 100644 --- a/opm/core/fluid/SaturationPropsBasic.cpp +++ b/opm/core/fluid/SaturationPropsBasic.cpp @@ -114,7 +114,8 @@ namespace Opm THROW("SaturationPropsBasic::init() illegal num_phases: " << num_phases); } num_phases_ = num_phases; - std::string rpf = param.getDefault("relperm_func", std::string("Unset")); + //std::string rpf = param.getDefault("relperm_func", std::string("Unset")); + std::string rpf = param.getDefault("relperm_func", std::string("Linear")); if (rpf == "Constant") { relperm_func_ = Constant; if(num_phases!=1){ diff --git a/opm/core/linalg/LinearSolverFactory.cpp b/opm/core/linalg/LinearSolverFactory.cpp index 9b6d89095..98552c84c 100644 --- a/opm/core/linalg/LinearSolverFactory.cpp +++ b/opm/core/linalg/LinearSolverFactory.cpp @@ -30,6 +30,10 @@ #if HAVE_DUNE_ISTL #include #endif +#if HAVE_AGMG +#include +#endif + #include #include @@ -69,8 +73,12 @@ namespace Opm solver_.reset(new LinearSolverIstl(param)); #endif } - - else { + else if (ls == "agmg") { +#if HAVE_AGMG + solver_.reset(new LinearSolverAGMG(param)); +#endif + } + else { THROW("Linear solver " << ls << " is unknown."); } From 7cad95c6c7c5e554e025cb38805e1c9d96f2bb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C3=A5rd=20Skaflestad?= Date: Tue, 14 Aug 2012 11:05:09 +0200 Subject: [PATCH 09/58] Restore coding conventions. Inadvertently lost in commit 064184b. --- opm/core/linalg/LinearSolverFactory.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/opm/core/linalg/LinearSolverFactory.cpp b/opm/core/linalg/LinearSolverFactory.cpp index 98552c84c..4e2f3679b 100644 --- a/opm/core/linalg/LinearSolverFactory.cpp +++ b/opm/core/linalg/LinearSolverFactory.cpp @@ -30,6 +30,7 @@ #if HAVE_DUNE_ISTL #include #endif + #if HAVE_AGMG #include #endif @@ -73,12 +74,14 @@ namespace Opm solver_.reset(new LinearSolverIstl(param)); #endif } - else if (ls == "agmg") { + + else if (ls == "agmg") { #if HAVE_AGMG solver_.reset(new LinearSolverAGMG(param)); #endif - } - else { + } + + else { THROW("Linear solver " << ls << " is unknown."); } From f90f313af67a973d789b9cd7cd635fe2c16c6afb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 14 Aug 2012 11:25:59 +0200 Subject: [PATCH 10/58] Gravity segregation column solver for compressible case implemented. --- .../TransportModelCompressibleTwophase.cpp | 53 ++++++++++++++----- .../TransportModelCompressibleTwophase.hpp | 16 ++++-- 2 files changed, 50 insertions(+), 19 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index ce8ebb97e..f55f67edb 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -254,6 +254,8 @@ namespace Opm ++update_count; const int cell = cells[i]; const double old_s = saturation_[cell]; + // solveSingleCell() requires saturation_[cell] + // to be s0. saturation_[cell] = s0[i]; solveSingleCell(cell); const double s_change = std::fabs(saturation_[cell] - old_s); @@ -305,8 +307,9 @@ namespace Opm // Residual function r(s) for a single-cell implicit Euler gravity segregation // - // r(s) = s - s0 + dt/pv*sum_{j adj i}( gravmod_ij * gf_ij ). + // [[ incompressible was: r(s) = s - s0 + dt/pv*sum_{j adj i}( gravmod_ij * gf_ij ) ]] // + // r(s) = s - B*z0 + dt/pv*( influx + outflux*f(s) ) struct TransportModelCompressibleTwophase::GravityResidual { int cell; @@ -372,32 +375,52 @@ namespace Opm - void TransportModelCompressibleTwophase::initGravity(const double* grav) + void TransportModelCompressibleTwophase::initGravity() { - // Set up gravflux_ = T_ij g (rho_w - rho_o) (z_i - z_j) + // Set up transmissibilities. std::vector htrans(grid_.cell_facepos[grid_.number_of_cells]); const int nf = grid_.number_of_faces; - const int dim = grid_.dimensions; - gravflux_.resize(nf); + trans_.resize(nf); tpfa_htrans_compute(const_cast(&grid_), props_.permeability(), &htrans[0]); - tpfa_trans_compute(const_cast(&grid_), &htrans[0], &gravflux_[0]); + tpfa_trans_compute(const_cast(&grid_), &htrans[0], &trans_[0]); + } - const double delta_rho = 0.0;// props_.density()[0] - props_.density()[1]; - THROW("TransportModelCompressibleTwophase gravity solver not done yet."); // See line above... + + + + void TransportModelCompressibleTwophase::initGravityDynamic(const double* grav) + { + // Set up gravflux_ = T_ij g [ (b_w,i rho_w,S - b_o,i rho_o,S) (z_i - z_f) + // + (b_w,j rho_w,S - b_o,j rho_o,S) (z_f - z_j) ] + // But b_w,i * rho_w,S = rho_w,i, which we conmpute with a call to props_.density(). + // We assume that we already have stored T_ij in trans_. + // We also assume that the A_ matrices are updated from an earlier call to solve(). + const int nc = grid_.number_of_cells; + const int nf = grid_.number_of_faces; + const int np = props_.numPhases(); + ASSERT(np == 2); + const int dim = grid_.dimensions; + density_.resize(nc*np); + props_.density(grid_.number_of_cells, &A_[0], &density_[0]); + std::fill(gravflux_.begin(), gravflux_.end(), 0.0); for (int f = 0; f < nf; ++f) { const int* c = &grid_.face_cells[2*f]; - double gdz = 0.0; + const double signs[2] = { 1.0, -1.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]); + for (int ci = 0; ci < 2; ++ci) { + double gdz = 0.0; + for (int d = 0; d < dim; ++d) { + gdz += grav[d]*(grid_.cell_centroids[dim*c[ci] + d] - grid_.face_centroids[dim*f + d]); + } + gravflux_[f] += signs[ci]*trans_[f]*gdz*(density_[2*c[ci]] - density_[2*c[ci] + 1]); } } - gravflux_[f] *= delta_rho*gdz; } } + void TransportModelCompressibleTwophase::solveSingleCellGravity(const std::vector& cells, const int pos, const double* gravflux) @@ -470,10 +493,13 @@ namespace Opm void TransportModelCompressibleTwophase::solveGravity(const std::vector >& columns, const double* pressure, const double* porevolume0, - const double* porevolume, const double dt, + const double* grav, std::vector& saturation) { + // Assume that solve() has already been called, so that A_ is current. + initGravityDynamic(grav); + // Initialize mobilities. const int nc = grid_.number_of_cells; std::vector cells(nc); @@ -493,7 +519,6 @@ namespace Opm // Set up other variables. porevolume0_ = porevolume0; - porevolume_ = porevolume; dt_ = dt; toWaterSat(saturation, saturation_); diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index fda83fbcf..c9f7e96a2 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -48,7 +48,7 @@ namespace Opm /// \param[in] pressure Array of cell pressures /// \param[in] surfacevol0 Array of surface volumes at start of timestep /// \param[in] porevolume0 Array of pore volumes at start of timestep. - /// \param[in] porevolume Array of pore volumes. + /// \param[in] porevolume Array of pore volumes at end of timestep. /// \param[in] source Transport source term. /// \param[in] dt Time step. /// \param[in, out] saturation Phase saturations. @@ -62,20 +62,23 @@ namespace Opm std::vector& saturation); /// Initialise quantities needed by gravity solver. - /// \param[in] grav gravity vector - void initGravity(const double* grav); + void initGravity(); /// Solve for gravity segregation. /// This uses a column-wise nonlinear Gauss-Seidel approach. /// It assumes that the input columns contain cells in a single /// vertical stack, that do not interact with other columns (for /// gravity segregation. - /// \TODO: Implement this. + /// \param[in] columns Vector of cell-columns. + /// \param[in] porevolume0 Array of pore volumes at start of timestep. + /// \param[in] dt Time step. + /// \param[in] grav Gravity vector. + /// \param[in, out] saturation Phase saturations. void solveGravity(const std::vector >& columns, const double* pressure, const double* porevolume0, - const double* porevolume, const double dt, + const double* grav, std::vector& saturation); private: @@ -85,6 +88,7 @@ namespace Opm const int pos, const double* gravflux); int solveGravityColumn(const std::vector& cells); + void initGravityDynamic(const double* grav); private: const UnstructuredGrid& grid_; @@ -106,6 +110,8 @@ namespace Opm std::vector saturation_; // P (= num. phases) per cell std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell // For gravity segregation. + std::vector trans_; + std::vector density_; std::vector gravflux_; std::vector mob_; std::vector s0_; From 547efbe7d14e7d83b4aa4436637e8d4b82b31310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 17 Aug 2012 10:36:57 +0200 Subject: [PATCH 11/58] Added function cfs_tpfa_res_comprock_assemble(). This is intended to handle cases with both fluid and rock compressibility. --- opm/core/pressure/tpfa/cfs_tpfa_residual.c | 73 ++++++++++++++++++++++ opm/core/pressure/tpfa/cfs_tpfa_residual.h | 16 +++++ 2 files changed, 89 insertions(+) diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.c b/opm/core/pressure/tpfa/cfs_tpfa_residual.c index 7a52db1e5..ab79dbce7 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.c +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.c @@ -1213,6 +1213,79 @@ cfs_tpfa_res_assemble(struct UnstructuredGrid *G , } +/* ---------------------------------------------------------------------- */ +void +cfs_tpfa_res_comprock_assemble( + struct UnstructuredGrid *G , + double dt , + struct cfs_tpfa_res_forces *forces , + const double *zc , + struct compr_quantities_gen *cq , + const double *trans , + const double *gravcap_f, + const double *cpress , + const double *wpress , + const double *porevol , + const double *porevol0 , + const double *rock_comp, + struct cfs_tpfa_res_data *h ) +/* ---------------------------------------------------------------------- */ +{ + /* We want to add this term to the usual residual: + * + * (porevol(pressure)-porevol(initial_pressure))/dt. + * + * Its derivative (for the diagonal term of the Jacobian) is: + * + * porevol(pressure)*rock_comp(pressure)/dt + */ + + int c, w, well_is_neumann, rock_is_incomp; + size_t j; + double dpvdt; + const struct Wells* W; + + /* Assemble usual system (without rock compressibility). */ + cfs_tpfa_res_assemble(G, dt, forces, zc, cq, trans, gravcap_f, + cpress, wpress, porevol, h); + + /* Check if we have only Neumann wells. */ + well_is_neumann = 1; + W = forces->wells->W; + for (w = 0; well_is_neumann && w < W->number_of_wells; w++) { + if ((W->ctrls[w]->current >= 0) && /* OPEN? */ + (W->ctrls[w]->type[ W->ctrls[w]->current ] == BHP)) { + well_is_neumann = 0; + } + } + + /* If we made a singularity-removing adjustment in the + regular assembly, we undo it here. */ + if (well_is_neumann && h->pimpl->is_incomp) { + h->J->sa[0] /= 2; + } + + /* Add new terms to residual and Jacobian. */ + rock_is_incomp = 1; + for (c = 0; c < G->number_of_cells; c++) { + j = csrmatrix_elm_index(c, c, h->J); + + dpvdt = (porevol[c] - porevol0[c]) / dt; + if (dpvdt != 0.0 || rock_comp[c] != 0.0) { + rock_is_incomp = 0; + } + + h->J->sa[j] += porevol[c] * rock_comp[c] / dt; + h->F[c] -= dpvdt; + } + + /* Re-do the singularity-removing adjustment if necessary */ + if (rock_is_incomp && well_is_neumann && h->pimpl->is_incomp) { + h->J->sa[0] *= 2; + } +} + + /* ---------------------------------------------------------------------- */ void cfs_tpfa_res_flux(struct UnstructuredGrid *G , diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.h b/opm/core/pressure/tpfa/cfs_tpfa_residual.h index 4fde3ba39..6a86c61bc 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.h +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.h @@ -72,6 +72,22 @@ cfs_tpfa_res_assemble(struct UnstructuredGrid *G, const double *porevol, struct cfs_tpfa_res_data *h); +void +cfs_tpfa_res_comprock_assemble( + struct UnstructuredGrid *G, + double dt, + struct cfs_tpfa_res_forces *forces, + const double *zc, + struct compr_quantities_gen *cq, + const double *trans, + const double *gravcap_f, + const double *cpress, + const double *wpress, + const double *porevol, + const double *porevol0, + const double *rock_comp, + struct cfs_tpfa_res_data *h); + void cfs_tpfa_res_flux(struct UnstructuredGrid *G , struct cfs_tpfa_res_forces *forces , From d67f49bac807b29f5e5a1470d2b8b7ea0b9305a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 17 Aug 2012 10:38:41 +0200 Subject: [PATCH 12/58] Class CompressibleTpfa now handles rock compressibility. --- opm/core/pressure/CompressibleTpfa.cpp | 39 ++++++++++++++++++++++---- opm/core/pressure/CompressibleTpfa.hpp | 38 ++++++++++++++----------- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/opm/core/pressure/CompressibleTpfa.cpp b/opm/core/pressure/CompressibleTpfa.cpp index 154f06336..dbd7ea47a 100644 --- a/opm/core/pressure/CompressibleTpfa.cpp +++ b/opm/core/pressure/CompressibleTpfa.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -58,6 +59,7 @@ namespace Opm /// 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, @@ -66,6 +68,7 @@ namespace Opm const struct Wells* wells) : grid_(grid), props_(props), + rock_comp_props_(rock_comp_props), linsolver_(linsolver), residual_tol_(residual_tol), change_tol_(change_tol), @@ -74,7 +77,6 @@ namespace Opm wells_(wells), htrans_(grid.cell_facepos[ grid.number_of_cells ]), trans_ (grid.number_of_faces), - porevol_(grid.number_of_cells), allcells_(grid.number_of_cells) { if (wells_ && (wells_->number_of_phases != props.numPhases())) { @@ -86,7 +88,12 @@ namespace Opm UnstructuredGrid* gg = const_cast(&grid_); tpfa_htrans_compute(gg, props.permeability(), &htrans_[0]); tpfa_trans_compute(gg, &htrans_[0], &trans_[0]); - computePorevolume(grid_, props.porosity(), porevol_); + // 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; } @@ -230,6 +237,9 @@ namespace Opm const WellState& /*well_state*/) { computeWellPotentials(state); + if (rock_comp_props_ && rock_comp_props_->isActive()) { + computePorevolume(grid_, props_.porosity(), *rock_comp_props_, state.pressure(), initial_porevol_); + } } @@ -252,6 +262,8 @@ namespace Opm // std::vector face_gravcap_; // std::vector wellperf_A_; // std::vector wellperf_phasemob_; + // std::vector porevol_; // Only modified if rock_comp_props_ is non-null. + // std::vector rock_comp_; // Empty unless rock_comp_props_ is non-null. computeCellDynamicData(dt, state, well_state); computeFaceDynamicData(dt, state, well_state); computeWellDynamicData(dt, state, well_state); @@ -273,6 +285,8 @@ namespace Opm // std::vector cell_viscosity_; // std::vector cell_phasemob_; // std::vector cell_voldisc_; + // std::vector porevol_; // Only modified if rock_comp_props_ is non-null. + // std::vector rock_comp_; // Empty unless rock_comp_props_ is non-null. const int nc = grid_.number_of_cells; const int np = props_.numPhases(); const double* cell_p = &state.pressure()[0]; @@ -296,6 +310,14 @@ namespace Opm // TODO: Check this! cell_voldisc_.clear(); cell_voldisc_.resize(nc, 0.0); + + if (rock_comp_props_ && rock_comp_props_->isActive()) { + computePorevolume(grid_, props_.porosity(), *rock_comp_props_, state.pressure(), porevol_); + rock_comp_.resize(nc); + for (int cell = 0; cell < nc; ++cell) { + rock_comp_[cell] = rock_comp_props_->rockComp(state.pressure()[cell]); + } + } } @@ -465,9 +487,16 @@ namespace Opm cq.Af = &face_A_[0]; cq.phasemobf = &face_phasemob_[0]; cq.voldiscr = &cell_voldisc_[0]; - cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], - &face_gravcap_[0], cell_press, well_bhp, - &porevol_[0], h_); + if (rock_comp_props_ == NULL) { + cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], + &face_gravcap_[0], cell_press, well_bhp, + &porevol_[0], h_); + } else { + cfs_tpfa_res_comprock_assemble(gg, dt, &forces, z, &cq, &trans_[0], + &face_gravcap_[0], cell_press, well_bhp, + &porevol_[0], &initial_porevol_[0], + &rock_comp_[0], h_); + } } diff --git a/opm/core/pressure/CompressibleTpfa.hpp b/opm/core/pressure/CompressibleTpfa.hpp index 8233ee17b..8a2857f21 100644 --- a/opm/core/pressure/CompressibleTpfa.hpp +++ b/opm/core/pressure/CompressibleTpfa.hpp @@ -33,6 +33,7 @@ namespace Opm class BlackoilState; class BlackoilPropertiesInterface; + class RockCompressibility; class LinearSolverInterface; class WellState; @@ -44,23 +45,25 @@ namespace Opm { public: /// 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. + /// \param[in] grid A 2d or 3d grid. + /// \param[in] props Rock and fluid properties. + /// \param[in] rock_comp_props Rock compressibility properties. May be null. + /// \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(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, + const RockCompressibility* rock_comp_props, const LinearSolverInterface& linsolver, const double residual_tol, const double change_tol, @@ -107,6 +110,7 @@ namespace Opm // ------ Data that will remain unmodified after construction. ------ const UnstructuredGrid& grid_; const BlackoilPropertiesInterface& props_; + const RockCompressibility* rock_comp_props_; const LinearSolverInterface& linsolver_; const double residual_tol_; const double change_tol_; @@ -115,7 +119,6 @@ namespace Opm const Wells* wells_; // May be NULL, outside may modify controls (only) between calls to solve(). std::vector htrans_; std::vector trans_ ; - std::vector porevol_; std::vector allcells_; // ------ Internal data for the cfs_tpfa_res solver. ------ @@ -123,6 +126,7 @@ namespace Opm // ------ Data that will be modified for every solve. ------ std::vector wellperf_gpot_; + std::vector initial_porevol_; // ------ Data that will be modified for every solver iteration. ------ std::vector cell_A_; @@ -135,6 +139,8 @@ namespace Opm std::vector face_gravcap_; std::vector wellperf_A_; std::vector wellperf_phasemob_; + std::vector porevol_; // Only modified if rock_comp_props_ is non-null. + std::vector rock_comp_; // Empty unless rock_comp_props_ is non-null. // The update to be applied to the pressures (cell and bhp). std::vector pressure_increment_; From 61fdf4a8b6fda787ab3e752082c33aa04f1c3cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 17 Aug 2012 10:56:27 +0200 Subject: [PATCH 13/58] Bugfix: call *comprock* method only if active rock compressibility. --- opm/core/pressure/CompressibleTpfa.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/pressure/CompressibleTpfa.cpp b/opm/core/pressure/CompressibleTpfa.cpp index dbd7ea47a..d28db5a33 100644 --- a/opm/core/pressure/CompressibleTpfa.cpp +++ b/opm/core/pressure/CompressibleTpfa.cpp @@ -487,7 +487,7 @@ namespace Opm cq.Af = &face_A_[0]; cq.phasemobf = &face_phasemob_[0]; cq.voldiscr = &cell_voldisc_[0]; - if (rock_comp_props_ == NULL) { + if (rock_comp_props_ == NULL || !rock_comp_props_->isActive()) { cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], &face_gravcap_[0], cell_press, well_bhp, &porevol_[0], h_); From ded1424cc928599081a66a580d8dc07a30026fee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 17 Aug 2012 12:40:15 +0200 Subject: [PATCH 14/58] Whitespace cleanup. --- .../TransportModelCompressibleTwophase.hpp | 92 +-- .../reorder/TransportModelTwophase.cpp | 744 +++++++++--------- .../reorder/TransportModelTwophase.hpp | 88 +-- 3 files changed, 462 insertions(+), 462 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index c9f7e96a2..19c44b22d 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -33,33 +33,33 @@ namespace Opm class TransportModelCompressibleTwophase : public TransportModelInterface { public: - /// Construct solver. - /// \param[in] grid A 2d or 3d grid. - /// \param[in] props Rock and fluid properties. - /// \param[in] tol Tolerance used in the solver. - /// \param[in] maxit Maximum number of non-linear iterations used. - TransportModelCompressibleTwophase(const UnstructuredGrid& grid, + /// Construct solver. + /// \param[in] grid A 2d or 3d grid. + /// \param[in] props Rock and fluid properties. + /// \param[in] tol Tolerance used in the solver. + /// \param[in] maxit Maximum number of non-linear iterations used. + TransportModelCompressibleTwophase(const UnstructuredGrid& grid, const Opm::BlackoilPropertiesInterface& props, const double tol, const int maxit); - /// Solve for saturation at next timestep. - /// \param[in] darcyflux Array of signed face fluxes. - /// \param[in] pressure Array of cell pressures - /// \param[in] surfacevol0 Array of surface volumes at start of timestep - /// \param[in] porevolume0 Array of pore volumes at start of timestep. - /// \param[in] porevolume Array of pore volumes at end of timestep. - /// \param[in] source Transport source term. - /// \param[in] dt Time step. - /// \param[in, out] saturation Phase saturations. - void solve(const double* darcyflux, + /// Solve for saturation at next timestep. + /// \param[in] darcyflux Array of signed face fluxes. + /// \param[in] pressure Array of cell pressures + /// \param[in] surfacevol0 Array of surface volumes at start of timestep + /// \param[in] porevolume0 Array of pore volumes at start of timestep. + /// \param[in] porevolume Array of pore volumes at end of timestep. + /// \param[in] source Transport source term. + /// \param[in] dt Time step. + /// \param[in, out] saturation Phase saturations. + void solve(const double* darcyflux, const double* pressure, const double* surfacevol0, const double* porevolume0, const double* porevolume, - const double* source, - const double dt, - std::vector& saturation); + const double* source, + const double dt, + std::vector& saturation); /// Initialise quantities needed by gravity solver. void initGravity(); @@ -69,11 +69,11 @@ namespace Opm /// It assumes that the input columns contain cells in a single /// vertical stack, that do not interact with other columns (for /// gravity segregation. - /// \param[in] columns Vector of cell-columns. - /// \param[in] porevolume0 Array of pore volumes at start of timestep. - /// \param[in] dt Time step. - /// \param[in] grav Gravity vector. - /// \param[in, out] saturation Phase saturations. + /// \param[in] columns Vector of cell-columns. + /// \param[in] porevolume0 Array of pore volumes at start of timestep. + /// \param[in] dt Time step. + /// \param[in] grav Gravity vector. + /// \param[in, out] saturation Phase saturations. void solveGravity(const std::vector >& columns, const double* pressure, const double* porevolume0, @@ -82,8 +82,8 @@ namespace Opm std::vector& saturation); private: - virtual void solveSingleCell(const int cell); - virtual void solveMultiCell(const int num_cells, const int* cells); + virtual void solveSingleCell(const int cell); + virtual void solveMultiCell(const int num_cells, const int* cells); void solveSingleCellGravity(const std::vector& cells, const int pos, const double* gravflux); @@ -91,24 +91,24 @@ namespace Opm void initGravityDynamic(const double* grav); private: - const UnstructuredGrid& grid_; - const BlackoilPropertiesInterface& props_; + const UnstructuredGrid& grid_; + const BlackoilPropertiesInterface& props_; std::vector allcells_; std::vector visc_; std::vector A_; - std::vector smin_; - std::vector smax_; - double tol_; - double maxit_; + std::vector smin_; + std::vector smax_; + double tol_; + double maxit_; - const double* darcyflux_; // one flux per grid face - const double* surfacevol0_; // one per phase per cell - const double* porevolume0_; // one volume per cell - const double* porevolume_; // one volume per cell - const double* source_; // one source per cell - double dt_; + const double* darcyflux_; // one flux per grid face + const double* surfacevol0_; // one per phase per cell + const double* porevolume0_; // one volume per cell + const double* porevolume_; // one volume per cell + const double* source_; // one source per cell + double dt_; std::vector saturation_; // P (= num. phases) per cell - std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell + std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell // For gravity segregation. std::vector trans_; std::vector density_; @@ -116,14 +116,14 @@ namespace Opm std::vector mob_; std::vector s0_; - // Storing the upwind and downwind graphs for experiments. - std::vector ia_upw_; - std::vector ja_upw_; - std::vector ia_downw_; - std::vector ja_downw_; + // Storing the upwind and downwind graphs for experiments. + std::vector ia_upw_; + std::vector ja_upw_; + std::vector ia_downw_; + std::vector ja_downw_; - struct Residual; - double fracFlow(double s, int cell) const; + struct Residual; + double fracFlow(double s, int cell) const; struct GravityResidual; void mobility(double s, int cell, double* mob) const; diff --git a/opm/core/transport/reorder/TransportModelTwophase.cpp b/opm/core/transport/reorder/TransportModelTwophase.cpp index ff6d2c05d..b3630ea73 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelTwophase.cpp @@ -41,68 +41,68 @@ namespace Opm TransportModelTwophase::TransportModelTwophase(const UnstructuredGrid& grid, - const Opm::IncompPropertiesInterface& props, - const double tol, - const int maxit) - : grid_(grid), - props_(props), - tol_(tol), - maxit_(maxit), - darcyflux_(0), - source_(0), - dt_(0.0), - saturation_(grid.number_of_cells, -1.0), - fractionalflow_(grid.number_of_cells, -1.0), - mob_(2*grid.number_of_cells, -1.0) + const Opm::IncompPropertiesInterface& props, + const double tol, + const int maxit) + : grid_(grid), + props_(props), + tol_(tol), + maxit_(maxit), + darcyflux_(0), + source_(0), + dt_(0.0), + saturation_(grid.number_of_cells, -1.0), + fractionalflow_(grid.number_of_cells, -1.0), + mob_(2*grid.number_of_cells, -1.0) #ifdef EXPERIMENT_GAUSS_SEIDEL - , ia_upw_(grid.number_of_cells + 1, -1), - ja_upw_(grid.number_of_faces, -1), - ia_downw_(grid.number_of_cells + 1, -1), - ja_downw_(grid.number_of_faces, -1) + , ia_upw_(grid.number_of_cells + 1, -1), + ja_upw_(grid.number_of_faces, -1), + ia_downw_(grid.number_of_cells + 1, -1), + ja_downw_(grid.number_of_faces, -1) #endif { - if (props.numPhases() != 2) { - THROW("Property object must have 2 phases"); - } - visc_ = props.viscosity(); - int num_cells = props.numCells(); - smin_.resize(props.numPhases()*num_cells); - smax_.resize(props.numPhases()*num_cells); - std::vector cells(num_cells); - for (int i = 0; i < num_cells; ++i) { - cells[i] = i; - } - props.satRange(props.numCells(), &cells[0], &smin_[0], &smax_[0]); + if (props.numPhases() != 2) { + THROW("Property object must have 2 phases"); + } + visc_ = props.viscosity(); + int num_cells = props.numCells(); + smin_.resize(props.numPhases()*num_cells); + smax_.resize(props.numPhases()*num_cells); + std::vector cells(num_cells); + for (int i = 0; i < num_cells; ++i) { + cells[i] = i; + } + props.satRange(props.numCells(), &cells[0], &smin_[0], &smax_[0]); } void TransportModelTwophase::solve(const double* darcyflux, const double* porevolume, - const double* source, - const double dt, - std::vector& saturation) + const double* source, + const double dt, + std::vector& saturation) { - darcyflux_ = darcyflux; + darcyflux_ = darcyflux; porevolume_ = porevolume; - source_ = source; - dt_ = dt; + source_ = source; + dt_ = dt; toWaterSat(saturation, saturation_); #ifdef EXPERIMENT_GAUSS_SEIDEL - std::vector seq(grid_.number_of_cells); - std::vector comp(grid_.number_of_cells + 1); - int ncomp; - compute_sequence_graph(&grid_, darcyflux_, - &seq[0], &comp[0], &ncomp, - &ia_upw_[0], &ja_upw_[0]); - const int nf = grid_.number_of_faces; - std::vector neg_darcyflux(nf); - std::transform(darcyflux, darcyflux + nf, neg_darcyflux.begin(), std::negate()); - compute_sequence_graph(&grid_, &neg_darcyflux[0], - &seq[0], &comp[0], &ncomp, - &ia_downw_[0], &ja_downw_[0]); + std::vector seq(grid_.number_of_cells); + std::vector comp(grid_.number_of_cells + 1); + int ncomp; + compute_sequence_graph(&grid_, darcyflux_, + &seq[0], &comp[0], &ncomp, + &ia_upw_[0], &ja_upw_[0]); + const int nf = grid_.number_of_faces; + std::vector neg_darcyflux(nf); + std::transform(darcyflux, darcyflux + nf, neg_darcyflux.begin(), std::negate()); + compute_sequence_graph(&grid_, &neg_darcyflux[0], + &seq[0], &comp[0], &ncomp, + &ia_downw_[0], &ja_downw_[0]); #endif - reorderAndTransport(grid_, darcyflux); + reorderAndTransport(grid_, darcyflux); toBothSat(saturation_, saturation); } @@ -114,330 +114,330 @@ namespace Opm // Influxes are negative, outfluxes positive. struct TransportModelTwophase::Residual { - int cell; - double s0; - double influx; // sum_j min(v_ij, 0)*f(s_j) + q_w - double outflux; // sum_j max(v_ij, 0) - q + int cell; + double s0; + double influx; // sum_j min(v_ij, 0)*f(s_j) + q_w + double outflux; // sum_j max(v_ij, 0) - q double comp_term; // q - sum_j v_ij - double dtpv; // dt/pv(i) - const TransportModelTwophase& tm; - explicit Residual(const TransportModelTwophase& tmodel, int cell_index) - : tm(tmodel) - { - cell = cell_index; - s0 = tm.saturation_[cell]; + double dtpv; // dt/pv(i) + const TransportModelTwophase& tm; + explicit Residual(const TransportModelTwophase& tmodel, int cell_index) + : tm(tmodel) + { + cell = cell_index; + s0 = tm.saturation_[cell]; double src_flux = -tm.source_[cell]; bool src_is_inflow = src_flux < 0.0; - influx = src_is_inflow ? src_flux : 0.0; - outflux = !src_is_inflow ? src_flux : 0.0; + influx = src_is_inflow ? src_flux : 0.0; + outflux = !src_is_inflow ? src_flux : 0.0; comp_term = tm.source_[cell]; // Note: this assumes that all source flux is water. - dtpv = tm.dt_/tm.porevolume_[cell]; + dtpv = tm.dt_/tm.porevolume_[cell]; - for (int i = tm.grid_.cell_facepos[cell]; i < tm.grid_.cell_facepos[cell+1]; ++i) { - int f = tm.grid_.cell_faces[i]; - double flux; - int other; - // Compute cell flux - if (cell == tm.grid_.face_cells[2*f]) { - flux = tm.darcyflux_[f]; - other = tm.grid_.face_cells[2*f+1]; - } else { - flux =-tm.darcyflux_[f]; - other = tm.grid_.face_cells[2*f]; - } - // Add flux to influx or outflux, if interior. - if (other != -1) { - if (flux < 0.0) { - influx += flux*tm.fractionalflow_[other]; - } else { - outflux += flux; - } + for (int i = tm.grid_.cell_facepos[cell]; i < tm.grid_.cell_facepos[cell+1]; ++i) { + int f = tm.grid_.cell_faces[i]; + double flux; + int other; + // Compute cell flux + if (cell == tm.grid_.face_cells[2*f]) { + flux = tm.darcyflux_[f]; + other = tm.grid_.face_cells[2*f+1]; + } else { + flux =-tm.darcyflux_[f]; + other = tm.grid_.face_cells[2*f]; + } + // Add flux to influx or outflux, if interior. + if (other != -1) { + if (flux < 0.0) { + influx += flux*tm.fractionalflow_[other]; + } else { + outflux += flux; + } comp_term -= flux; - } - } - } - double operator()(double s) const - { - return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx + s*comp_term); - } + } + } + } + double operator()(double s) const + { + return s - s0 + dtpv*(outflux*tm.fracFlow(s, cell) + influx + s*comp_term); + } }; void TransportModelTwophase::solveSingleCell(const int cell) { - Residual res(*this, cell); - // const double r0 = res(saturation_[cell]); - // if (std::fabs(r0) < tol_) { - // return; - // } - int iters_used; - // saturation_[cell] = modifiedRegulaFalsi(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); - saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); - fractionalflow_[cell] = fracFlow(saturation_[cell], cell); + Residual res(*this, cell); + // const double r0 = res(saturation_[cell]); + // if (std::fabs(r0) < tol_) { + // return; + // } + int iters_used; + // saturation_[cell] = modifiedRegulaFalsi(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); + saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); + fractionalflow_[cell] = fracFlow(saturation_[cell], cell); } // namespace { - // class TofComputer - // { - // public: - // TofComputer(const int num_cells, - // const int* ia, - // const int* ja, - // const int startcell, - // std::vector& tof) - // : ia_(ia), - // ja_(ja) - // { - // tof.clear(); - // tof.resize(num_cells, num_cells); - // tof[startcell] = 0; - // tof_ = &tof[0]; - // visitTof(startcell); - // } + // class TofComputer + // { + // public: + // TofComputer(const int num_cells, + // const int* ia, + // const int* ja, + // const int startcell, + // std::vector& tof) + // : ia_(ia), + // ja_(ja) + // { + // tof.clear(); + // tof.resize(num_cells, num_cells); + // tof[startcell] = 0; + // tof_ = &tof[0]; + // visitTof(startcell); + // } - // private: - // const int* ia_; - // const int* ja_; - // int* tof_; + // private: + // const int* ia_; + // const int* ja_; + // int* tof_; - // void visitTof(const int cell) - // { - // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { - // const int nb_cell = ja_[j]; - // if (tof_[nb_cell] > tof_[cell] + 1) { - // tof_[nb_cell] = tof_[cell] + 1; - // visitTof(nb_cell); - // } - // } - // } + // void visitTof(const int cell) + // { + // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { + // const int nb_cell = ja_[j]; + // if (tof_[nb_cell] > tof_[cell] + 1) { + // tof_[nb_cell] = tof_[cell] + 1; + // visitTof(nb_cell); + // } + // } + // } - // }; + // }; // } // anon namespace void TransportModelTwophase::solveMultiCell(const int num_cells, const int* cells) { - // std::ofstream os("dump"); - // std::copy(cells, cells + num_cells, std::ostream_iterator(os, "\n")); + // std::ofstream os("dump"); + // std::copy(cells, cells + num_cells, std::ostream_iterator(os, "\n")); - // Experiment: try a breath-first search to build a more suitable ordering. - // Verdict: failed to improve #iterations. - // { - // std::vector pos(grid_.number_of_cells, -1); - // for (int i = 0; i < num_cells; ++i) { - // const int cell = cells[i]; - // pos[cell] = i; - // } - // std::vector done_pos(num_cells, 0); - // std::vector upstream_pos; - // std::vector new_pos; - // upstream_pos.push_back(0); - // done_pos[0] = 1; - // int current = 0; - // while (int(new_pos.size()) < num_cells) { - // const int i = upstream_pos[current++]; - // new_pos.push_back(i); - // const int cell = cells[i]; - // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { - // const int opos = pos[ja_[j]]; - // if (!done_pos[opos]) { - // upstream_pos.push_back(opos); - // done_pos[opos] = 1; - // } - // } - // } - // std::reverse(new_pos.begin(), new_pos.end()); - // std::copy(new_pos.begin(), new_pos.end(), const_cast(cells)); - // } + // Experiment: try a breath-first search to build a more suitable ordering. + // Verdict: failed to improve #iterations. + // { + // std::vector pos(grid_.number_of_cells, -1); + // for (int i = 0; i < num_cells; ++i) { + // const int cell = cells[i]; + // pos[cell] = i; + // } + // std::vector done_pos(num_cells, 0); + // std::vector upstream_pos; + // std::vector new_pos; + // upstream_pos.push_back(0); + // done_pos[0] = 1; + // int current = 0; + // while (int(new_pos.size()) < num_cells) { + // const int i = upstream_pos[current++]; + // new_pos.push_back(i); + // const int cell = cells[i]; + // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { + // const int opos = pos[ja_[j]]; + // if (!done_pos[opos]) { + // upstream_pos.push_back(opos); + // done_pos[opos] = 1; + // } + // } + // } + // std::reverse(new_pos.begin(), new_pos.end()); + // std::copy(new_pos.begin(), new_pos.end(), const_cast(cells)); + // } - // Experiment: try a random ordering. - // Verdict: amazingly, reduced #iterations by approx. 25%! - // int* c = const_cast(cells); - // std::random_shuffle(c, c + num_cells); + // Experiment: try a random ordering. + // Verdict: amazingly, reduced #iterations by approx. 25%! + // int* c = const_cast(cells); + // std::random_shuffle(c, c + num_cells); - // Experiment: compute topological tof from first cell. - // Verdict: maybe useful, not tried to exploit it yet. - // std::vector tof; - // TofComputer comp(grid_.number_of_cells, &ia_[0], &ja_[0], cells[0], tof); - // std::ofstream tofdump("tofdump"); - // std::copy(tof.begin(), tof.end(), std::ostream_iterator(tofdump, "\n")); + // Experiment: compute topological tof from first cell. + // Verdict: maybe useful, not tried to exploit it yet. + // std::vector tof; + // TofComputer comp(grid_.number_of_cells, &ia_[0], &ja_[0], cells[0], tof); + // std::ofstream tofdump("tofdump"); + // std::copy(tof.begin(), tof.end(), std::ostream_iterator(tofdump, "\n")); - // Experiment: implement a metric measuring badness of ordering - // as average distance in (cyclic) ordering from - // upstream neighbours. - // Verdict: does not seem to predict #iterations very well, if at all. - // std::vector pos(grid_.number_of_cells, -1); - // for (int i = 0; i < num_cells; ++i) { - // const int cell = cells[i]; - // pos[cell] = i; - // } - // double diffsum = 0; - // for (int i = 0; i < num_cells; ++i) { - // const int cell = cells[i]; - // int num_upstream = 0; - // int loc_diffsum = 0; - // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { - // const int opos = pos[ja_[j]]; - // if (opos == -1) { - // std::cout << "Hmmm" << std::endl; - // continue; - // } - // ++num_upstream; - // const int diff = (i - opos + num_cells) % num_cells; - // loc_diffsum += diff; - // } - // diffsum += double(loc_diffsum)/double(num_upstream); - // } - // std::cout << "Average distance from upstream neighbours: " << diffsum/double(num_cells) - // << std::endl; + // Experiment: implement a metric measuring badness of ordering + // as average distance in (cyclic) ordering from + // upstream neighbours. + // Verdict: does not seem to predict #iterations very well, if at all. + // std::vector pos(grid_.number_of_cells, -1); + // for (int i = 0; i < num_cells; ++i) { + // const int cell = cells[i]; + // pos[cell] = i; + // } + // double diffsum = 0; + // for (int i = 0; i < num_cells; ++i) { + // const int cell = cells[i]; + // int num_upstream = 0; + // int loc_diffsum = 0; + // for (int j = ia_[cell]; j < ia_[cell+1]; ++j) { + // const int opos = pos[ja_[j]]; + // if (opos == -1) { + // std::cout << "Hmmm" << std::endl; + // continue; + // } + // ++num_upstream; + // const int diff = (i - opos + num_cells) % num_cells; + // loc_diffsum += diff; + // } + // diffsum += double(loc_diffsum)/double(num_upstream); + // } + // std::cout << "Average distance from upstream neighbours: " << diffsum/double(num_cells) + // << std::endl; #ifdef EXPERIMENT_GAUSS_SEIDEL - // Experiment: when a cell changes more than the tolerance, - // mark all downwind cells as needing updates. After - // computing a single update in each cell, use marks - // to guide further updating. Clear mark in cell when - // its solution gets updated. - // Verdict: this is a good one! Approx. halved total time. - std::vector needs_update(num_cells, 1); - // This one also needs the mapping from all cells to - // the strongly connected subset to filter out connections - std::vector pos(grid_.number_of_cells, -1); - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - pos[cell] = i; - } + // Experiment: when a cell changes more than the tolerance, + // mark all downwind cells as needing updates. After + // computing a single update in each cell, use marks + // to guide further updating. Clear mark in cell when + // its solution gets updated. + // Verdict: this is a good one! Approx. halved total time. + std::vector needs_update(num_cells, 1); + // This one also needs the mapping from all cells to + // the strongly connected subset to filter out connections + std::vector pos(grid_.number_of_cells, -1); + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + pos[cell] = i; + } - // Note: partially copied from below. - const double tol = 1e-9; - const int max_iters = 300; - // Must store s0 before we start. - std::vector s0(num_cells); - // Must set initial fractional flows before we start. - // Also, we compute the # of upstream neighbours. - // std::vector num_upstream(num_cells); - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - fractionalflow_[cell] = fracFlow(saturation_[cell], cell); - s0[i] = saturation_[cell]; - // num_upstream[i] = ia_upw_[cell + 1] - ia_upw_[cell]; - } - // Solve once in each cell. - // std::vector fully_marked_stack; - // fully_marked_stack.reserve(num_cells); - int num_iters = 0; - int update_count = 0; // Change name/meaning to cells_updated? - do { - update_count = 0; // Must reset count for every iteration. - for (int i = 0; i < num_cells; ++i) { - // while (!fully_marked_stack.empty()) { - // // std::cout << "# fully marked cells = " << fully_marked_stack.size() << std::endl; - // const int fully_marked_ci = fully_marked_stack.back(); - // fully_marked_stack.pop_back(); - // ++update_count; - // const int cell = cells[fully_marked_ci]; - // const double old_s = saturation_[cell]; - // saturation_[cell] = s0[fully_marked_ci]; - // solveSingleCell(cell); - // const double s_change = std::fabs(saturation_[cell] - old_s); - // if (s_change > tol) { - // // Mark downwind cells. - // for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { - // const int downwind_cell = ja_downw_[j]; - // int ci = pos[downwind_cell]; - // ++needs_update[ci]; - // if (needs_update[ci] == num_upstream[ci]) { - // fully_marked_stack.push_back(ci); - // } - // } - // } - // // Unmark this cell. - // needs_update[fully_marked_ci] = 0; - // } - if (!needs_update[i]) { - continue; - } - ++update_count; - const int cell = cells[i]; - const double old_s = saturation_[cell]; - saturation_[cell] = s0[i]; - solveSingleCell(cell); - const double s_change = std::fabs(saturation_[cell] - old_s); - if (s_change > tol) { - // Mark downwind cells. - for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { - const int downwind_cell = ja_downw_[j]; - int ci = pos[downwind_cell]; + // Note: partially copied from below. + const double tol = 1e-9; + const int max_iters = 300; + // Must store s0 before we start. + std::vector s0(num_cells); + // Must set initial fractional flows before we start. + // Also, we compute the # of upstream neighbours. + // std::vector num_upstream(num_cells); + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + fractionalflow_[cell] = fracFlow(saturation_[cell], cell); + s0[i] = saturation_[cell]; + // num_upstream[i] = ia_upw_[cell + 1] - ia_upw_[cell]; + } + // Solve once in each cell. + // std::vector fully_marked_stack; + // fully_marked_stack.reserve(num_cells); + int num_iters = 0; + int update_count = 0; // Change name/meaning to cells_updated? + do { + update_count = 0; // Must reset count for every iteration. + for (int i = 0; i < num_cells; ++i) { + // while (!fully_marked_stack.empty()) { + // // std::cout << "# fully marked cells = " << fully_marked_stack.size() << std::endl; + // const int fully_marked_ci = fully_marked_stack.back(); + // fully_marked_stack.pop_back(); + // ++update_count; + // const int cell = cells[fully_marked_ci]; + // const double old_s = saturation_[cell]; + // saturation_[cell] = s0[fully_marked_ci]; + // solveSingleCell(cell); + // const double s_change = std::fabs(saturation_[cell] - old_s); + // if (s_change > tol) { + // // Mark downwind cells. + // for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { + // const int downwind_cell = ja_downw_[j]; + // int ci = pos[downwind_cell]; + // ++needs_update[ci]; + // if (needs_update[ci] == num_upstream[ci]) { + // fully_marked_stack.push_back(ci); + // } + // } + // } + // // Unmark this cell. + // needs_update[fully_marked_ci] = 0; + // } + if (!needs_update[i]) { + continue; + } + ++update_count; + const int cell = cells[i]; + const double old_s = saturation_[cell]; + saturation_[cell] = s0[i]; + solveSingleCell(cell); + const double s_change = std::fabs(saturation_[cell] - old_s); + if (s_change > tol) { + // Mark downwind cells. + for (int j = ia_downw_[cell]; j < ia_downw_[cell+1]; ++j) { + const int downwind_cell = ja_downw_[j]; + int ci = pos[downwind_cell]; if (ci != -1) { needs_update[ci] = 1; } - // ++needs_update[ci]; - // if (needs_update[ci] == num_upstream[ci]) { - // fully_marked_stack.push_back(ci); - // } - } - } - // Unmark this cell. - needs_update[i] = 0; - } - // std::cout << "Iter = " << num_iters << " update_count = " << update_count - // << " # marked cells = " - // << std::accumulate(needs_update.begin(), needs_update.end(), 0) << std::endl; - } while (update_count > 0 && ++num_iters < max_iters); + // ++needs_update[ci]; + // if (needs_update[ci] == num_upstream[ci]) { + // fully_marked_stack.push_back(ci); + // } + } + } + // Unmark this cell. + needs_update[i] = 0; + } + // std::cout << "Iter = " << num_iters << " update_count = " << update_count + // << " # marked cells = " + // << std::accumulate(needs_update.begin(), needs_update.end(), 0) << std::endl; + } while (update_count > 0 && ++num_iters < max_iters); - // Done with iterations, check if we succeeded. - if (update_count > 0) { - THROW("In solveMultiCell(), we did not converge after " - << num_iters << " iterations. Remaining update count = " << update_count); - } - std::cout << "Solved " << num_cells << " cell multicell problem in " - << num_iters << " iterations." << std::endl; + // Done with iterations, check if we succeeded. + if (update_count > 0) { + THROW("In solveMultiCell(), we did not converge after " + << num_iters << " iterations. Remaining update count = " << update_count); + } + std::cout << "Solved " << num_cells << " cell multicell problem in " + << num_iters << " iterations." << std::endl; #else - double max_s_change = 0.0; - const double tol = 1e-9; - const int max_iters = 300; - int num_iters = 0; - // Must store s0 before we start. - std::vector s0(num_cells); - // Must set initial fractional flows before we start. - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - fractionalflow_[cell] = fracFlow(saturation_[cell], cell); - s0[i] = saturation_[cell]; - } - do { - max_s_change = 0.0; - for (int i = 0; i < num_cells; ++i) { - const int cell = cells[i]; - const double old_s = saturation_[cell]; - saturation_[cell] = s0[i]; - solveSingleCell(cell); - double s_change = std::fabs(saturation_[cell] - old_s); - // std::cout << "cell = " << cell << " delta s = " << s_change << std::endl; - if (max_s_change < s_change) { - max_s_change = s_change; - } - } - // std::cout << "Iter = " << num_iters << " max_s_change = " << max_s_change - // << " in cell " << max_change_cell << std::endl; - } while (max_s_change > tol && ++num_iters < max_iters); - if (max_s_change > tol) { - THROW("In solveMultiCell(), we did not converge after " - << num_iters << " iterations. Delta s = " << max_s_change); - } - std::cout << "Solved " << num_cells << " cell multicell problem in " - << num_iters << " iterations." << std::endl; + double max_s_change = 0.0; + const double tol = 1e-9; + const int max_iters = 300; + int num_iters = 0; + // Must store s0 before we start. + std::vector s0(num_cells); + // Must set initial fractional flows before we start. + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + fractionalflow_[cell] = fracFlow(saturation_[cell], cell); + s0[i] = saturation_[cell]; + } + do { + max_s_change = 0.0; + for (int i = 0; i < num_cells; ++i) { + const int cell = cells[i]; + const double old_s = saturation_[cell]; + saturation_[cell] = s0[i]; + solveSingleCell(cell); + double s_change = std::fabs(saturation_[cell] - old_s); + // std::cout << "cell = " << cell << " delta s = " << s_change << std::endl; + if (max_s_change < s_change) { + max_s_change = s_change; + } + } + // std::cout << "Iter = " << num_iters << " max_s_change = " << max_s_change + // << " in cell " << max_change_cell << std::endl; + } while (max_s_change > tol && ++num_iters < max_iters); + if (max_s_change > tol) { + THROW("In solveMultiCell(), we did not converge after " + << num_iters << " iterations. Delta s = " << max_s_change); + } + std::cout << "Solved " << num_cells << " cell multicell problem in " + << num_iters << " iterations." << std::endl; #endif // EXPERIMENT_GAUSS_SEIDEL } double TransportModelTwophase::fracFlow(double s, int cell) const { - double sat[2] = { s, 1.0 - s }; - double mob[2]; - props_.relperm(1, sat, &cell, mob, 0); - mob[0] /= visc_[0]; - mob[1] /= visc_[1]; - return mob[0]/(mob[0] + mob[1]); + double sat[2] = { s, 1.0 - s }; + double mob[2]; + props_.relperm(1, sat, &cell, mob, 0); + mob[0] /= visc_[0]; + mob[1] /= visc_[1]; + return mob[0]/(mob[0] + mob[1]); } @@ -450,19 +450,19 @@ namespace Opm // struct TransportModelTwophase::GravityResidual { - int cell; + int cell; int nbcell[2]; - double s0; - double dtpv; // dt/pv(i) + double s0; + double dtpv; // dt/pv(i) double gf[2]; - const TransportModelTwophase& tm; - explicit GravityResidual(const TransportModelTwophase& tmodel, + const TransportModelTwophase& tm; + explicit GravityResidual(const TransportModelTwophase& tmodel, const std::vector& cells, const int pos, const double* gravflux) // Always oriented towards next in column. Size = colsize - 1. - : tm(tmodel) - { - cell = cells[pos]; + : tm(tmodel) + { + cell = cells[pos]; nbcell[0] = -1; gf[0] = 0.0; if (pos > 0) { @@ -475,40 +475,40 @@ namespace Opm nbcell[1] = cells[pos + 1]; gf[1] = gravflux[pos]; } - s0 = tm.saturation_[cell]; - dtpv = tm.dt_/tm.porevolume_[cell]; - - } - double operator()(double s) const - { - double res = s - s0; + s0 = tm.saturation_[cell]; + dtpv = tm.dt_/tm.porevolume_[cell]; + + } + double operator()(double s) const + { + double res = s - s0; double mobcell[2]; tm.mobility(s, cell, mobcell); for (int nb = 0; nb < 2; ++nb) { - if (nbcell[nb] != -1) { + if (nbcell[nb] != -1) { double m[2]; if (gf[nb] < 0.0) { m[0] = mobcell[0]; m[1] = tm.mob_[2*nbcell[nb] + 1]; - } else { + } else { m[0] = tm.mob_[2*nbcell[nb]]; m[1] = mobcell[1]; - } - if (m[0] + m[1] > 0.0) { + } + if (m[0] + m[1] > 0.0) { res += -dtpv*gf[nb]*m[0]*m[1]/(m[0] + m[1]); } - } + } } return res; - } + } }; void TransportModelTwophase::mobility(double s, int cell, double* mob) const { - double sat[2] = { s, 1.0 - s }; - props_.relperm(1, sat, &cell, mob, 0); - mob[0] /= visc_[0]; - mob[1] /= visc_[1]; + double sat[2] = { s, 1.0 - s }; + props_.relperm(1, sat, &cell, mob, 0); + mob[0] /= visc_[0]; + mob[1] /= visc_[1]; } @@ -548,7 +548,7 @@ namespace Opm saturation_[cell] = RootFinder::solve(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); } saturation_[cell] = std::min(std::max(saturation_[cell], smin_[2*cell]), smax_[2*cell]); - mobility(saturation_[cell], cell, &mob_[2*cell]); + mobility(saturation_[cell], cell, &mob_[2*cell]); } @@ -559,17 +559,17 @@ namespace Opm const int nc = cells.size(); std::vector col_gravflux(nc - 1); for (int ci = 0; ci < nc - 1; ++ci) { - const int cell = cells[ci]; - const int next_cell = cells[ci + 1]; - for (int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) { - const int face = grid_.cell_faces[j]; - const int c1 = grid_.face_cells[2*face + 0]; + const int cell = cells[ci]; + const int next_cell = cells[ci + 1]; + for (int j = grid_.cell_facepos[cell]; j < grid_.cell_facepos[cell+1]; ++j) { + const int face = grid_.cell_faces[j]; + const int c1 = grid_.face_cells[2*face + 0]; const int c2 = grid_.face_cells[2*face + 1]; - if (c1 == next_cell || c2 == next_cell) { + if (c1 == next_cell || c2 == next_cell) { const double gf = gravflux_[face]; col_gravflux[ci] = (c1 == cell) ? gf : -gf; - } - } + } + } } // Store initial saturation s0 @@ -579,7 +579,7 @@ namespace Opm } // Solve single cell problems, repeating if necessary. - double max_s_change = 0.0; + double max_s_change = 0.0; int num_iters = 0; do { max_s_change = 0.0; @@ -595,12 +595,12 @@ namespace Opm std::fabs(saturation_[cells[ci2]] - old_s[1]))); } // std::cout << "Iter = " << num_iters << " max_s_change = " << max_s_change << std::endl; - } while (max_s_change > tol_ && ++num_iters < maxit_); + } while (max_s_change > tol_ && ++num_iters < maxit_); - if (max_s_change > tol_) { - THROW("In solveGravityColumn(), we did not converge after " - << num_iters << " iterations. Delta s = " << max_s_change); - } + if (max_s_change > tol_) { + THROW("In solveGravityColumn(), we did not converge after " + << num_iters << " iterations. Delta s = " << max_s_change); + } return num_iters + 1; } diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index ca302c18a..74ed2bfe4 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -35,27 +35,27 @@ namespace Opm class TransportModelTwophase : public TransportModelInterface { public: - /// Construct solver. - /// \param[in] grid A 2d or 3d grid. - /// \param[in] props Rock and fluid properties. - /// \param[in] tol Tolerance used in the solver. - /// \param[in] maxit Maximum number of non-linear iterations used. - TransportModelTwophase(const UnstructuredGrid& grid, - const Opm::IncompPropertiesInterface& props, - const double tol, - const int maxit); + /// Construct solver. + /// \param[in] grid A 2d or 3d grid. + /// \param[in] props Rock and fluid properties. + /// \param[in] tol Tolerance used in the solver. + /// \param[in] maxit Maximum number of non-linear iterations used. + TransportModelTwophase(const UnstructuredGrid& grid, + const Opm::IncompPropertiesInterface& props, + const double tol, + const int maxit); - /// Solve for saturation at next timestep. - /// \param[in] darcyflux Array of signed face fluxes. - /// \param[in] porevolume Array of pore volumes. - /// \param[in] source Transport source term. - /// \param[in] dt Time step. - /// \param[in, out] saturation Phase saturations. - void solve(const double* darcyflux, + /// Solve for saturation at next timestep. + /// \param[in] darcyflux Array of signed face fluxes. + /// \param[in] porevolume Array of pore volumes. + /// \param[in] source Transport source term. + /// \param[in] dt Time step. + /// \param[in, out] saturation Phase saturations. + void solve(const double* darcyflux, const double* porevolume, - const double* source, - const double dt, - std::vector& saturation); + const double* source, + const double dt, + std::vector& saturation); /// Initialise quantities needed by gravity solver. /// \param[in] grav gravity vector @@ -66,18 +66,18 @@ namespace Opm /// It assumes that the input columns contain cells in a single /// vertical stack, that do not interact with other columns (for /// gravity segregation. - /// \param[in] columns Vector of cell-columns. - /// \param[in] porevolume Array of pore volumes. - /// \param[in] dt Time step. - /// \param[in, out] saturation Phase saturations. + /// \param[in] columns Vector of cell-columns. + /// \param[in] porevolume Array of pore volumes. + /// \param[in] dt Time step. + /// \param[in, out] saturation Phase saturations. void solveGravity(const std::vector >& columns, const double* porevolume, const double dt, std::vector& saturation); private: - virtual void solveSingleCell(const int cell); - virtual void solveMultiCell(const int num_cells, const int* cells); + virtual void solveSingleCell(const int cell); + virtual void solveMultiCell(const int num_cells, const int* cells); void solveSingleCellGravity(const std::vector& cells, const int pos, @@ -85,33 +85,33 @@ namespace Opm int solveGravityColumn(const std::vector& cells); private: - const UnstructuredGrid& grid_; - const IncompPropertiesInterface& props_; - const double* visc_; - std::vector smin_; - std::vector smax_; - double tol_; - double maxit_; + const UnstructuredGrid& grid_; + const IncompPropertiesInterface& props_; + const double* visc_; + std::vector smin_; + std::vector smax_; + double tol_; + double maxit_; - const double* darcyflux_; // one flux per grid face - const double* porevolume_; // one volume per cell - const double* source_; // one source per cell - double dt_; + const double* darcyflux_; // one flux per grid face + const double* porevolume_; // one volume per cell + const double* source_; // one source per cell + double dt_; std::vector saturation_; // one per cell, only water saturation! - std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell + std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell // For gravity segregation. std::vector gravflux_; std::vector mob_; std::vector s0_; - // Storing the upwind and downwind graphs for experiments. - std::vector ia_upw_; - std::vector ja_upw_; - std::vector ia_downw_; - std::vector ja_downw_; + // Storing the upwind and downwind graphs for experiments. + std::vector ia_upw_; + std::vector ja_upw_; + std::vector ia_downw_; + std::vector ja_downw_; - struct Residual; - double fracFlow(double s, int cell) const; + struct Residual; + double fracFlow(double s, int cell) const; struct GravityResidual; void mobility(double s, int cell, double* mob) const; From b470ab8d50e7ff8a7fc41231a86447172b3f62bf Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Mon, 20 Aug 2012 15:18:24 +0200 Subject: [PATCH 15/58] Fix initialization bug. --- .../transport/reorder/TransportModelCompressibleTwophase.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index f55f67edb..531aca4f5 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -381,6 +381,7 @@ namespace Opm std::vector 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(&grid_), props_.permeability(), &htrans[0]); tpfa_trans_compute(const_cast(&grid_), &htrans[0], &trans_[0]); } From 50ff22141d495a7457179d3fdaacb21efdfe9413 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Tue, 21 Aug 2012 09:57:36 +0200 Subject: [PATCH 16/58] Added writing of timings in param format --- opm/core/simulator/SimulatorReport.cpp | 6 ++++++ opm/core/simulator/SimulatorReport.hpp | 1 + 2 files changed, 7 insertions(+) diff --git a/opm/core/simulator/SimulatorReport.cpp b/opm/core/simulator/SimulatorReport.cpp index 1fa264597..763262608 100644 --- a/opm/core/simulator/SimulatorReport.cpp +++ b/opm/core/simulator/SimulatorReport.cpp @@ -42,6 +42,12 @@ namespace Opm << "\n Pressure time: " << pressure_time << "\n Transport time: " << transport_time << std::endl; } + void SimulatorReport::reportParam(std::ostream& os) + { + os << "/timing/total_time=" << total_time + << "\n/timing/pressure/total_time=" << pressure_time + << "\n/timing/transport/total_time=" << transport_time << std::endl; + } } // namespace Opm diff --git a/opm/core/simulator/SimulatorReport.hpp b/opm/core/simulator/SimulatorReport.hpp index a763156c1..8e7cb2e85 100644 --- a/opm/core/simulator/SimulatorReport.hpp +++ b/opm/core/simulator/SimulatorReport.hpp @@ -38,6 +38,7 @@ namespace Opm void operator+=(const SimulatorReport& sr); /// Print a report to the given stream. void report(std::ostream& os); + void reportParam(std::ostream& os); }; } // namespace Opm From 7e1e1e795138e58efea48f75e20ae7ee92dc2175 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Tue, 21 Aug 2012 10:20:59 +0200 Subject: [PATCH 17/58] Fixed sign error and replaced porevol->porevol0. --- opm/core/pressure/tpfa/cfs_tpfa_residual.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.c b/opm/core/pressure/tpfa/cfs_tpfa_residual.c index ab79dbce7..b3ca1f9d8 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.c +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.c @@ -1247,7 +1247,7 @@ cfs_tpfa_res_comprock_assemble( /* Assemble usual system (without rock compressibility). */ cfs_tpfa_res_assemble(G, dt, forces, zc, cq, trans, gravcap_f, - cpress, wpress, porevol, h); + cpress, wpress, porevol0, h); /* Check if we have only Neumann wells. */ well_is_neumann = 1; @@ -1276,7 +1276,7 @@ cfs_tpfa_res_comprock_assemble( } h->J->sa[j] += porevol[c] * rock_comp[c] / dt; - h->F[c] -= dpvdt; + h->F[c] += dpvdt; } /* Re-do the singularity-removing adjustment if necessary */ From 5743225be2e769463e733ffd0f946cf81793fcea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Tue, 21 Aug 2012 15:23:46 +0200 Subject: [PATCH 18/58] added writing of reorder iterations for each cell --- opm/core/transport/reorder/TransportModelTwophase.cpp | 11 +++++++---- opm/core/transport/reorder/TransportModelTwophase.hpp | 10 ++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelTwophase.cpp b/opm/core/transport/reorder/TransportModelTwophase.cpp index b3630ea73..49cafa49a 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelTwophase.cpp @@ -52,6 +52,7 @@ namespace Opm source_(0), dt_(0.0), saturation_(grid.number_of_cells, -1.0), + reorder_iterations_(grid.number_of_cells, 0), fractionalflow_(grid.number_of_cells, -1.0), mob_(2*grid.number_of_cells, -1.0) #ifdef EXPERIMENT_GAUSS_SEIDEL @@ -101,7 +102,7 @@ namespace Opm &seq[0], &comp[0], &ncomp, &ia_downw_[0], &ja_downw_[0]); #endif - + std::fill(reorder_iterations_.begin(),reorder_iterations_.end(),0); reorderAndTransport(grid_, darcyflux); toBothSat(saturation_, saturation); } @@ -170,9 +171,11 @@ namespace Opm // if (std::fabs(r0) < tol_) { // return; // } - int iters_used; + int iters_used=0; // saturation_[cell] = modifiedRegulaFalsi(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); + // add if it is iteration on an out loop + reorder_iterations_[cell] = reorder_iterations_[cell] + iters_used; fractionalflow_[cell] = fracFlow(saturation_[cell], cell); } @@ -544,8 +547,9 @@ namespace Opm const int cell = cells[pos]; GravityResidual res(*this, cells, pos, gravflux); if (std::fabs(res(saturation_[cell])) > tol_) { - int iters_used; + int iters_used=0; saturation_[cell] = RootFinder::solve(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); + reorder_iterations_[cell] = reorder_iterations_[cell] + iters_used; } saturation_[cell] = std::min(std::max(saturation_[cell], smin_[2*cell]), smax_[2*cell]); mobility(saturation_[cell], cell, &mob_[2*cell]); @@ -641,7 +645,6 @@ namespace Opm toBothSat(saturation_, saturation); } - } // namespace Opm diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index 74ed2bfe4..692976079 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -23,7 +23,7 @@ #include #include #include - +#include struct UnstructuredGrid; namespace Opm @@ -74,7 +74,8 @@ namespace Opm const double* porevolume, const double dt, std::vector& saturation); - + void reportIterations(std::ostream &os); + const std::vector& getReorderIterations(){return reorder_iterations_;}; private: virtual void solveSingleCell(const int cell); virtual void solveMultiCell(const int num_cells, const int* cells); @@ -83,8 +84,7 @@ namespace Opm const int pos, const double* gravflux); int solveGravityColumn(const std::vector& cells); - - private: + private: const UnstructuredGrid& grid_; const IncompPropertiesInterface& props_; const double* visc_; @@ -99,6 +99,8 @@ namespace Opm double dt_; std::vector saturation_; // one per cell, only water saturation! std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell + std::vector reorder_iterations_; + //std::vector reorder_fval_; // For gravity segregation. std::vector gravflux_; std::vector mob_; From 712ccb0309beafca969b66848c4ba9552b31e5e5 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Tue, 21 Aug 2012 17:09:19 +0200 Subject: [PATCH 19/58] Corrected typo in comment. --- opm/core/pressure/tpfa/ifs_tpfa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/pressure/tpfa/ifs_tpfa.c b/opm/core/pressure/tpfa/ifs_tpfa.c index 94e3d6383..0e69bc491 100644 --- a/opm/core/pressure/tpfa/ifs_tpfa.c +++ b/opm/core/pressure/tpfa/ifs_tpfa.c @@ -771,7 +771,7 @@ ifs_tpfa_assemble_comprock_increment(struct UnstructuredGrid *G , assemble_incompressible(G, F, trans, gpress, h, &system_singular, &ok); /* We want to solve a Newton step for the residual - * (porevol(pressure)-porevol(initial_pressure))/dt + residual_for_imcompressible + * (porevol(pressure)-porevol(initial_pressure))/dt + residual_for_incompressible * */ From 52ab67201d80a33d92f74fe9658c6792d62b9518 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Tue, 21 Aug 2012 17:10:49 +0200 Subject: [PATCH 20/58] Changed way to get total number of cells. --- opm/core/fluid/RockFromDeck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/fluid/RockFromDeck.cpp b/opm/core/fluid/RockFromDeck.cpp index 6568e8cc3..02f675567 100644 --- a/opm/core/fluid/RockFromDeck.cpp +++ b/opm/core/fluid/RockFromDeck.cpp @@ -87,7 +87,7 @@ namespace Opm double perm_threshold) { const int dim = 3; - const int num_global_cells = numGlobalCells(parser); + const int num_global_cells = grid.cartdims[0]*grid.cartdims[1]*grid.cartdims[2]; const int nc = grid.number_of_cells; ASSERT (num_global_cells > 0); From 660f14df3b9d6cdbaf8456e273cee6a55ef7db81 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Tue, 21 Aug 2012 17:12:07 +0200 Subject: [PATCH 21/58] Corrected bug (residual should not be divided by dt). --- opm/core/pressure/tpfa/cfs_tpfa_residual.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.c b/opm/core/pressure/tpfa/cfs_tpfa_residual.c index b3ca1f9d8..fb8ee8795 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.c +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.c @@ -1242,7 +1242,7 @@ cfs_tpfa_res_comprock_assemble( int c, w, well_is_neumann, rock_is_incomp; size_t j; - double dpvdt; + double dpv; const struct Wells* W; /* Assemble usual system (without rock compressibility). */ @@ -1270,13 +1270,13 @@ cfs_tpfa_res_comprock_assemble( for (c = 0; c < G->number_of_cells; c++) { j = csrmatrix_elm_index(c, c, h->J); - dpvdt = (porevol[c] - porevol0[c]) / dt; - if (dpvdt != 0.0 || rock_comp[c] != 0.0) { + dpv = (porevol[c] - porevol0[c]); + if (dpv != 0.0 || rock_comp[c] != 0.0) { rock_is_incomp = 0; } - h->J->sa[j] += porevol[c] * rock_comp[c] / dt; - h->F[c] += dpvdt; + h->J->sa[j] += porevol[c] * rock_comp[c]; + h->F[c] += dpv; } /* Re-do the singularity-removing adjustment if necessary */ From 9ed0923279fbd33355c6ba95cee5edef148cfdb6 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Wed, 22 Aug 2012 10:11:32 +0200 Subject: [PATCH 22/58] Update surface volume in transport solver. --- .../TransportModelCompressibleTwophase.cpp | 15 ++++++++++++--- .../TransportModelCompressibleTwophase.hpp | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index 531aca4f5..06708da70 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -75,15 +75,15 @@ namespace Opm void TransportModelCompressibleTwophase::solve(const double* darcyflux, const double* pressure, - const double* surfacevol0, const double* porevolume0, const double* porevolume, const double* source, const double dt, - std::vector& saturation) + std::vector& saturation, + std::vector& surfacevol) { darcyflux_ = darcyflux; - surfacevol0_ = surfacevol0; + surfacevol0_ = &surfacevol[0]; porevolume0_ = porevolume0; porevolume_ = porevolume; source_ = source; @@ -107,6 +107,15 @@ namespace Opm &ia_downw_[0], &ja_downw_[0]); reorderAndTransport(grid_, darcyflux); toBothSat(saturation_, saturation); + + // Compute surface volume as a postprocessing step from saturation and A_ + surfacevol = saturation; + const int np = props_.numPhases(); + for (int cell = 0; cell < grid_.number_of_cells; ++cell) { + for (int phase = 0; phase < np; ++phase) { + surfacevol[np*cell + phase] *= A_[np*np*cell + np*phase + phase]; + } + } } // Residual function r(s) for a single-cell implicit Euler transport diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index 19c44b22d..542363cd3 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -54,12 +54,12 @@ namespace Opm /// \param[in, out] saturation Phase saturations. void solve(const double* darcyflux, const double* pressure, - const double* surfacevol0, const double* porevolume0, const double* porevolume, const double* source, const double dt, - std::vector& saturation); + std::vector& saturation, + std::vector& surfacevol); /// Initialise quantities needed by gravity solver. void initGravity(); From 010715ad03a5c0ee67cd5be44e3ef130214175b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 22 Aug 2012 12:31:59 +0200 Subject: [PATCH 23/58] Document and check (primitive) for non-miscibility requirement. --- .../transport/reorder/TransportModelCompressibleTwophase.cpp | 5 +++++ .../transport/reorder/TransportModelCompressibleTwophase.hpp | 2 ++ 2 files changed, 7 insertions(+) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index 06708da70..98aeefdf5 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -93,6 +93,11 @@ namespace Opm props_.viscosity(props_.numCells(), pressure, NULL, &allcells_[0], &visc_[0], NULL); props_.matrix(props_.numCells(), pressure, NULL, &allcells_[0], &A_[0], NULL); + // Check non-miscibility requirement (only done for first cell). + if (A_[1] != 0.0 || A_[2] != 0.0) { + THROW("TransportModelCompressibleTwophase requires a property object without miscibility."); + } + std::vector seq(grid_.number_of_cells); std::vector comp(grid_.number_of_cells + 1); int ncomp; diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index 542363cd3..5b82ed624 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -30,6 +30,8 @@ namespace Opm class BlackoilPropertiesInterface; + /// Implements a reordering transport solver for compressible, + /// non-miscible two-phase flow. class TransportModelCompressibleTwophase : public TransportModelInterface { public: From 96327164ccfc20db032358d172c58b805b437986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 23 Aug 2012 08:57:48 +0200 Subject: [PATCH 24/58] Added computeSurfacevol() method. The method is called by the reordering transport solver after computing new saturations in order to update the surface volumes. --- .../TransportModelCompressibleTwophase.cpp | 11 ++----- opm/core/utility/miscUtilitiesBlackoil.cpp | 30 +++++++++++++++++++ opm/core/utility/miscUtilitiesBlackoil.hpp | 19 ++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index 98aeefdf5..b81a7e60a 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include @@ -112,15 +113,9 @@ namespace Opm &ia_downw_[0], &ja_downw_[0]); reorderAndTransport(grid_, darcyflux); toBothSat(saturation_, saturation); - + // Compute surface volume as a postprocessing step from saturation and A_ - surfacevol = saturation; - const int np = props_.numPhases(); - for (int cell = 0; cell < grid_.number_of_cells; ++cell) { - for (int phase = 0; phase < np; ++phase) { - surfacevol[np*cell + phase] *= A_[np*np*cell + np*phase + phase]; - } - } + computeSurfacevol(grid_.number_of_cells, props_.numPhases(), &A_[0], &saturation[0], &surfacevol[0]); } // Residual function r(s) for a single-cell implicit Euler transport diff --git a/opm/core/utility/miscUtilitiesBlackoil.cpp b/opm/core/utility/miscUtilitiesBlackoil.cpp index af088e059..1c8bceee2 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.cpp +++ b/opm/core/utility/miscUtilitiesBlackoil.cpp @@ -220,5 +220,35 @@ namespace Opm } } + /// Computes the surface volume densities from saturations by the formula + /// z = A s + /// for a number of data points, where z is the surface volume density, + /// s is the saturation (both as column vectors) and A is the + /// phase-to-component relation matrix. + /// @param[in] n number of data points + /// @param[in] np number of phases, must be 2 or 3 + /// @param[in] A array containing n square matrices of size num_phases^2, + /// in Fortran ordering, typically the output of a call + /// to the matrix() method of a BlackoilProperties* class. + /// @param[in] saturation concatenated saturation values (for all P phases) + /// @param[out] surfacevol concatenated surface-volume values (for all P phases) + void computeSurfacevol(const int n, + const int np, + const double* A, + const double* saturation, + double* surfacevol) + { + // Note: since this is a simple matrix-vector product, it can + // be done by a BLAS call, but then we have to reorder the A + // matrix data. + std::fill(surfacevol, surfacevol + n*np, 0.0); + for (int i = 0; i < n; ++i) { + for (int row = 0; row < np; ++row) { + for (int col = 0; col < np; ++col) { + surfacevol[i*np + row] += A[i*np*np + row*np + col] * saturation[i*np + col]; + } + } + } + } } // namespace Opm diff --git a/opm/core/utility/miscUtilitiesBlackoil.hpp b/opm/core/utility/miscUtilitiesBlackoil.hpp index 929d42ecd..4a3d6448a 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.hpp +++ b/opm/core/utility/miscUtilitiesBlackoil.hpp @@ -112,6 +112,25 @@ namespace Opm const std::vector& s, std::vector& fractional_flows); + + /// Computes the surface volume densities from saturations by the formula + /// z = A s + /// for a number of data points, where z is the surface volume density, + /// s is the saturation (both as column vectors) and A is the + /// phase-to-component relation matrix. + /// @param[in] n number of data points + /// @param[in] np number of phases, must be 2 or 3 + /// @param[in] A array containing n square matrices of size num_phases, + /// in Fortran ordering, typically the output of a call + /// to the matrix() method of a BlackoilProperties* class. + /// @param[in] saturation concatenated saturation values (for all P phases) + /// @param[out] surfacevol concatenated surface-volume values (for all P phases) + void computeSurfacevol(const int n, + const int np, + const double* A, + const double* saturation, + double* surfacevol); + } // namespace Opm #endif // OPM_MISCUTILITIESBLACKOIL_HEADER_INCLUDED From e96421dbd776a60c481cfda061cd8e5956691ac2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 23 Aug 2012 08:59:09 +0200 Subject: [PATCH 25/58] Whitespace cleanup. --- opm/core/utility/miscUtilitiesBlackoil.cpp | 82 +++++++++++----------- opm/core/utility/miscUtilitiesBlackoil.hpp | 26 +++---- 2 files changed, 54 insertions(+), 54 deletions(-) diff --git a/opm/core/utility/miscUtilitiesBlackoil.cpp b/opm/core/utility/miscUtilitiesBlackoil.cpp index 1c8bceee2..548aaa23a 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.cpp +++ b/opm/core/utility/miscUtilitiesBlackoil.cpp @@ -48,39 +48,39 @@ namespace Opm void computeInjectedProduced(const BlackoilPropertiesInterface& props, const std::vector& press, const std::vector& z, - const std::vector& s, - const std::vector& src, - const double dt, - double* injected, - double* produced) + const std::vector& s, + const std::vector& src, + const double dt, + double* injected, + double* produced) { - const int num_cells = src.size(); - const int np = s.size()/src.size(); - if (int(s.size()) != num_cells*np) { - THROW("Sizes of s and src vectors do not match."); - } - std::fill(injected, injected + np, 0.0); - std::fill(produced, produced + np, 0.0); + const int num_cells = src.size(); + const int np = s.size()/src.size(); + if (int(s.size()) != num_cells*np) { + THROW("Sizes of s and src vectors do not match."); + } + std::fill(injected, injected + np, 0.0); + std::fill(produced, produced + np, 0.0); std::vector visc(np); - std::vector mob(np); - for (int c = 0; c < num_cells; ++c) { - if (src[c] > 0.0) { - injected[0] += src[c]*dt; - } else if (src[c] < 0.0) { - const double flux = -src[c]*dt; - const double* sat = &s[np*c]; - props.relperm(1, sat, &c, &mob[0], 0); + std::vector mob(np); + for (int c = 0; c < num_cells; ++c) { + if (src[c] > 0.0) { + injected[0] += src[c]*dt; + } else if (src[c] < 0.0) { + const double flux = -src[c]*dt; + const double* sat = &s[np*c]; + props.relperm(1, sat, &c, &mob[0], 0); props.viscosity(1, &press[c], &z[np*c], &c, &visc[0], 0); - double totmob = 0.0; - for (int p = 0; p < np; ++p) { - mob[p] /= visc[p]; - totmob += mob[p]; - } - for (int p = 0; p < np; ++p) { - produced[p] += (mob[p]/totmob)*flux; - } - } - } + double totmob = 0.0; + for (int p = 0; p < np; ++p) { + mob[p] /= visc[p]; + totmob += mob[p]; + } + for (int p = 0; p < np; ++p) { + produced[p] += (mob[p]/totmob)*flux; + } + } + } } @@ -93,11 +93,11 @@ namespace Opm /// @param[in] s saturation values (for all phases) /// @param[out] totmob total mobilities. void computeTotalMobility(const Opm::BlackoilPropertiesInterface& props, - const std::vector& cells, + const std::vector& cells, const std::vector& press, const std::vector& z, - const std::vector& s, - std::vector& totmob) + const std::vector& s, + std::vector& totmob) { std::vector pmobc; @@ -126,12 +126,12 @@ namespace Opm /// @param[out] totmob total mobility /// @param[out] omega fractional-flow weighted fluid densities. void computeTotalMobilityOmega(const Opm::BlackoilPropertiesInterface& props, - const std::vector& cells, + const std::vector& cells, const std::vector& p, const std::vector& z, - const std::vector& s, - std::vector& totmob, - std::vector& omega) + const std::vector& s, + std::vector& totmob, + std::vector& omega) { std::vector pmobc; @@ -185,10 +185,10 @@ namespace Opm props.relperm(nc, &s[0], &cells[0], &pmobc[0], dpmobc); - std::transform(pmobc.begin(), pmobc.end(), - mu.begin(), - pmobc.begin(), - std::divides()); + std::transform(pmobc.begin(), pmobc.end(), + mu.begin(), + pmobc.begin(), + std::divides()); } /// Computes the fractional flow for each cell in the cells argument diff --git a/opm/core/utility/miscUtilitiesBlackoil.hpp b/opm/core/utility/miscUtilitiesBlackoil.hpp index 4a3d6448a..565acc6ef 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.hpp +++ b/opm/core/utility/miscUtilitiesBlackoil.hpp @@ -46,11 +46,11 @@ namespace Opm void computeInjectedProduced(const BlackoilPropertiesInterface& props, const std::vector& p, const std::vector& z, - const std::vector& s, - const std::vector& src, - const double dt, - double* injected, - double* produced); + const std::vector& s, + const std::vector& src, + const double dt, + double* injected, + double* produced); /// @brief Computes total mobility for a set of saturation values. /// @param[in] props rock and fluid properties @@ -60,11 +60,11 @@ namespace Opm /// @param[in] s saturation values (for all phases) /// @param[out] totmob total mobilities. void computeTotalMobility(const Opm::BlackoilPropertiesInterface& props, - const std::vector& cells, + const std::vector& cells, const std::vector& p, const std::vector& z, - const std::vector& s, - std::vector& totmob); + const std::vector& s, + std::vector& totmob); /// @brief Computes total mobility and omega for a set of saturation values. /// @param[in] props rock and fluid properties @@ -75,12 +75,12 @@ namespace Opm /// @param[out] totmob total mobility /// @param[out] omega fractional-flow weighted fluid densities. void computeTotalMobilityOmega(const Opm::BlackoilPropertiesInterface& props, - const std::vector& cells, + const std::vector& cells, const std::vector& p, const std::vector& z, - const std::vector& s, - std::vector& totmob, - std::vector& omega); + const std::vector& s, + std::vector& totmob, + std::vector& omega); /// @brief Computes phase mobilities for a set of saturation values. @@ -96,7 +96,7 @@ namespace Opm const std::vector& z, const std::vector& s, std::vector& pmobc); - + /// Computes the fractional flow for each cell in the cells argument /// @param[in] props rock and fluid properties From 983a29691c856444baf3b1dde998de1da1bb2cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 23 Aug 2012 14:00:04 +0200 Subject: [PATCH 26/58] Function cfs_tpfa_residual_assemble() and friends now return singularity flag. The singularity flag is true if there are no pressure conditions and no compressibility (so the absolute values of the pressure solution will be arbitrary). --- opm/core/pressure/tpfa/cfs_tpfa_residual.c | 42 ++++++++++------------ opm/core/pressure/tpfa/cfs_tpfa_residual.h | 13 +++++-- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.c b/opm/core/pressure/tpfa/cfs_tpfa_residual.c index fb8ee8795..eb8dc8f34 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.c +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.c @@ -1156,7 +1156,7 @@ cfs_tpfa_res_construct(struct UnstructuredGrid *G , /* ---------------------------------------------------------------------- */ -void +int cfs_tpfa_res_assemble(struct UnstructuredGrid *G , double dt , struct cfs_tpfa_res_forces *forces , @@ -1170,7 +1170,7 @@ cfs_tpfa_res_assemble(struct UnstructuredGrid *G , struct cfs_tpfa_res_data *h ) /* ---------------------------------------------------------------------- */ { - int res_is_neumann, well_is_neumann, c, np2; + int res_is_neumann, well_is_neumann, c, np2, singular; csrmatrix_zero( h->J); vector_zero (h->J->m, h->F); @@ -1207,14 +1207,17 @@ cfs_tpfa_res_assemble(struct UnstructuredGrid *G , assemble_sources(dt, forces->src, h); } - if (res_is_neumann && well_is_neumann && h->pimpl->is_incomp) { - h->J->sa[0] *= 2; + singular = res_is_neumann && well_is_neumann && h->pimpl->is_incomp; + if (singular) { + h->J->sa[0] *= 2.0; } + + return singular; } /* ---------------------------------------------------------------------- */ -void +int cfs_tpfa_res_comprock_assemble( struct UnstructuredGrid *G , double dt , @@ -1240,29 +1243,18 @@ cfs_tpfa_res_comprock_assemble( * porevol(pressure)*rock_comp(pressure)/dt */ - int c, w, well_is_neumann, rock_is_incomp; + int c, rock_is_incomp, singular; size_t j; - double dpv; - const struct Wells* W; + double dpv; /* Assemble usual system (without rock compressibility). */ - cfs_tpfa_res_assemble(G, dt, forces, zc, cq, trans, gravcap_f, - cpress, wpress, porevol0, h); - - /* Check if we have only Neumann wells. */ - well_is_neumann = 1; - W = forces->wells->W; - for (w = 0; well_is_neumann && w < W->number_of_wells; w++) { - if ((W->ctrls[w]->current >= 0) && /* OPEN? */ - (W->ctrls[w]->type[ W->ctrls[w]->current ] == BHP)) { - well_is_neumann = 0; - } - } + singular = cfs_tpfa_res_assemble(G, dt, forces, zc, cq, trans, gravcap_f, + cpress, wpress, porevol0, h); /* If we made a singularity-removing adjustment in the regular assembly, we undo it here. */ - if (well_is_neumann && h->pimpl->is_incomp) { - h->J->sa[0] /= 2; + if (singular) { + h->J->sa[0] /= 2.0; } /* Add new terms to residual and Jacobian. */ @@ -1280,9 +1272,11 @@ cfs_tpfa_res_comprock_assemble( } /* Re-do the singularity-removing adjustment if necessary */ - if (rock_is_incomp && well_is_neumann && h->pimpl->is_incomp) { - h->J->sa[0] *= 2; + if (rock_is_incomp && singular) { + h->J->sa[0] *= 2.0; } + + return rock_is_incomp && singular; } diff --git a/opm/core/pressure/tpfa/cfs_tpfa_residual.h b/opm/core/pressure/tpfa/cfs_tpfa_residual.h index 6a86c61bc..5eddeed68 100644 --- a/opm/core/pressure/tpfa/cfs_tpfa_residual.h +++ b/opm/core/pressure/tpfa/cfs_tpfa_residual.h @@ -59,7 +59,11 @@ cfs_tpfa_res_construct(struct UnstructuredGrid *G , void cfs_tpfa_res_destroy(struct cfs_tpfa_res_data *h); -void +/* Return value is 1 if the assembled matrix was adjusted to remove a + singularity. This happens if all fluids are incompressible and + there are no pressure conditions on wells or boundaries. + Otherwise return 0. */ +int cfs_tpfa_res_assemble(struct UnstructuredGrid *G, double dt, struct cfs_tpfa_res_forces *forces, @@ -72,7 +76,12 @@ cfs_tpfa_res_assemble(struct UnstructuredGrid *G, const double *porevol, struct cfs_tpfa_res_data *h); -void +/* Return value is 1 if the assembled matrix was adjusted to remove a + singularity. This happens if all fluids are incompressible, the + rock is incompressible, and there are no pressure conditions on + wells or boundaries. + Otherwise return 0. */ +int cfs_tpfa_res_comprock_assemble( struct UnstructuredGrid *G, double dt, From 73949f892e91e4d07cdf63c966c593f9ca64a347 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 23 Aug 2012 14:03:20 +0200 Subject: [PATCH 27/58] New singularPressure() method propagates singularity information. --- opm/core/pressure/CompressibleTpfa.cpp | 36 ++++++++++++++++++++------ opm/core/pressure/CompressibleTpfa.hpp | 18 +++++++++---- 2 files changed, 41 insertions(+), 13 deletions(-) diff --git a/opm/core/pressure/CompressibleTpfa.cpp b/opm/core/pressure/CompressibleTpfa.cpp index d28db5a33..67d3a651a 100644 --- a/opm/core/pressure/CompressibleTpfa.cpp +++ b/opm/core/pressure/CompressibleTpfa.cpp @@ -77,7 +77,8 @@ namespace Opm wells_(wells), htrans_(grid.cell_facepos[ grid.number_of_cells ]), trans_ (grid.number_of_faces), - allcells_(grid.number_of_cells) + allcells_(grid.number_of_cells), + singular_(false) { if (wells_ && (wells_->number_of_phases != props.numPhases())) { THROW("Inconsistent number of phases specified (wells vs. props): " @@ -189,6 +190,21 @@ namespace Opm + /// @brief After solve(), was the resulting pressure singular. + /// Returns true if the pressure is singular in the following + /// sense: if everything is incompressible and there are no + /// pressure conditions, the absolute values of the pressure + /// solution are arbitrary. (But the differences in pressure + /// are significant.) + bool CompressibleTpfa::singularPressure() const + { + return singular_; + } + + + + + /// Compute well potentials. void CompressibleTpfa::computeWellPotentials(const BlackoilState& state) { @@ -487,16 +503,20 @@ namespace Opm cq.Af = &face_A_[0]; cq.phasemobf = &face_phasemob_[0]; cq.voldiscr = &cell_voldisc_[0]; + int was_adjusted = 0; if (rock_comp_props_ == NULL || !rock_comp_props_->isActive()) { - cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], - &face_gravcap_[0], cell_press, well_bhp, - &porevol_[0], h_); + was_adjusted = + cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], + &face_gravcap_[0], cell_press, well_bhp, + &porevol_[0], h_); } else { - cfs_tpfa_res_comprock_assemble(gg, dt, &forces, z, &cq, &trans_[0], - &face_gravcap_[0], cell_press, well_bhp, - &porevol_[0], &initial_porevol_[0], - &rock_comp_[0], h_); + was_adjusted = + cfs_tpfa_res_comprock_assemble(gg, dt, &forces, z, &cq, &trans_[0], + &face_gravcap_[0], cell_press, well_bhp, + &porevol_[0], &initial_porevol_[0], + &rock_comp_[0], h_); } + singular_ = (was_adjusted == 1); } diff --git a/opm/core/pressure/CompressibleTpfa.hpp b/opm/core/pressure/CompressibleTpfa.hpp index 8a2857f21..9fc5c43fd 100644 --- a/opm/core/pressure/CompressibleTpfa.hpp +++ b/opm/core/pressure/CompressibleTpfa.hpp @@ -81,6 +81,14 @@ namespace Opm BlackoilState& state, WellState& well_state); + /// @brief After solve(), was the resulting pressure singular. + /// Returns true if the pressure is singular in the following + /// sense: if everything is incompressible and there are no + /// pressure conditions, the absolute values of the pressure + /// solution are arbitrary. (But the differences in pressure + /// are significant.) + bool singularPressure() const; + private: void computePerSolveDynamicData(const double dt, const BlackoilState& state, @@ -143,11 +151,11 @@ namespace Opm std::vector rock_comp_; // Empty unless rock_comp_props_ is non-null. // The update to be applied to the pressures (cell and bhp). std::vector pressure_increment_; - - - - - + // True if the matrix assembled would be singular but for the + // adjustment made in the cfs_*_assemble() calls. This happens + // if everything is incompressible and there are no pressure + // conditions. + bool singular_; }; } // namespace Opm From caff665c1026d8463727c1c7b510ffd2cf4aebff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 23 Aug 2012 14:45:23 +0200 Subject: [PATCH 28/58] Fixed solveGravity(): now properly modifies surfacevolume. Also: - solveGravity() interface changed to take surface volume as a parameter, - gravity vector is now given in initGravity() instead of solveGravity(), for consistency with the incompressible solver. --- .../TransportModelCompressibleTwophase.cpp | 22 +++++++++++++------ .../TransportModelCompressibleTwophase.hpp | 13 ++++++----- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index b81a7e60a..c2d503275 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -39,7 +39,8 @@ namespace Opm typedef RegulaFalsi RootFinder; - TransportModelCompressibleTwophase::TransportModelCompressibleTwophase(const UnstructuredGrid& grid, + TransportModelCompressibleTwophase::TransportModelCompressibleTwophase( + const UnstructuredGrid& grid, const Opm::BlackoilPropertiesInterface& props, const double tol, const int maxit) @@ -52,6 +53,7 @@ namespace Opm dt_(0.0), saturation_(grid.number_of_cells, -1.0), fractionalflow_(grid.number_of_cells, -1.0), + gravity_(0), mob_(2*grid.number_of_cells, -1.0), ia_upw_(grid.number_of_cells + 1, -1), ja_upw_(grid.number_of_faces, -1), @@ -384,7 +386,7 @@ namespace Opm - void TransportModelCompressibleTwophase::initGravity() + void TransportModelCompressibleTwophase::initGravity(const double* grav) { // Set up transmissibilities. std::vector htrans(grid_.cell_facepos[grid_.number_of_cells]); @@ -393,12 +395,15 @@ namespace Opm gravflux_.resize(nf); tpfa_htrans_compute(const_cast(&grid_), props_.permeability(), &htrans[0]); tpfa_trans_compute(const_cast(&grid_), &htrans[0], &trans_[0]); + + // Remember gravity vector. + gravity_ = grav; } - void TransportModelCompressibleTwophase::initGravityDynamic(const double* grav) + void TransportModelCompressibleTwophase::initGravityDynamic() { // Set up gravflux_ = T_ij g [ (b_w,i rho_w,S - b_o,i rho_o,S) (z_i - z_f) // + (b_w,j rho_w,S - b_o,j rho_o,S) (z_f - z_j) ] @@ -420,7 +425,7 @@ namespace Opm for (int ci = 0; ci < 2; ++ci) { double gdz = 0.0; for (int d = 0; d < dim; ++d) { - gdz += grav[d]*(grid_.cell_centroids[dim*c[ci] + d] - grid_.face_centroids[dim*f + d]); + gdz += gravity_[d]*(grid_.cell_centroids[dim*c[ci] + d] - grid_.face_centroids[dim*f + d]); } gravflux_[f] += signs[ci]*trans_[f]*gdz*(density_[2*c[ci]] - density_[2*c[ci] + 1]); } @@ -504,11 +509,11 @@ namespace Opm const double* pressure, const double* porevolume0, const double dt, - const double* grav, - std::vector& saturation) + std::vector& saturation, + std::vector& surfacevol) { // Assume that solve() has already been called, so that A_ is current. - initGravityDynamic(grav); + initGravityDynamic(); // Initialize mobilities. const int nc = grid_.number_of_cells; @@ -541,6 +546,9 @@ namespace Opm std::cout << "Gauss-Seidel column solver average iterations: " << double(num_iters)/double(columns.size()) << std::endl; toBothSat(saturation_, saturation); + + // Compute surface volume as a postprocessing step from saturation and A_ + computeSurfacevol(grid_.number_of_cells, props_.numPhases(), &A_[0], &saturation[0], &surfacevol[0]); } } // namespace Opm diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp index 5b82ed624..4ee93e0af 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.hpp @@ -54,6 +54,7 @@ namespace Opm /// \param[in] source Transport source term. /// \param[in] dt Time step. /// \param[in, out] saturation Phase saturations. + /// \param[in, out] surfacevol Surface volume densities for each phase. void solve(const double* darcyflux, const double* pressure, const double* porevolume0, @@ -64,7 +65,8 @@ namespace Opm std::vector& surfacevol); /// Initialise quantities needed by gravity solver. - void initGravity(); + /// \param[in] grav Gravity vector + void initGravity(const double* grav); /// Solve for gravity segregation. /// This uses a column-wise nonlinear Gauss-Seidel approach. @@ -74,14 +76,14 @@ namespace Opm /// \param[in] columns Vector of cell-columns. /// \param[in] porevolume0 Array of pore volumes at start of timestep. /// \param[in] dt Time step. - /// \param[in] grav Gravity vector. /// \param[in, out] saturation Phase saturations. + /// \param[in, out] surfacevol Surface volume densities for each phase. void solveGravity(const std::vector >& columns, const double* pressure, const double* porevolume0, const double dt, - const double* grav, - std::vector& saturation); + std::vector& saturation, + std::vector& surfacevol); private: virtual void solveSingleCell(const int cell); @@ -90,7 +92,7 @@ namespace Opm const int pos, const double* gravflux); int solveGravityColumn(const std::vector& cells); - void initGravityDynamic(const double* grav); + void initGravityDynamic(); private: const UnstructuredGrid& grid_; @@ -112,6 +114,7 @@ namespace Opm std::vector saturation_; // P (= num. phases) per cell std::vector fractionalflow_; // = m[0]/(m[0] + m[1]) per cell // For gravity segregation. + const double* gravity_; std::vector trans_; std::vector density_; std::vector gravflux_; From c7bbf1146cb126e45e05b122601d0601d130320e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 24 Aug 2012 08:18:59 +0200 Subject: [PATCH 29/58] Removed unneeded function numGlobalCells(). --- opm/core/fluid/RockFromDeck.cpp | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/opm/core/fluid/RockFromDeck.cpp b/opm/core/fluid/RockFromDeck.cpp index 02f675567..7ba8903fd 100644 --- a/opm/core/fluid/RockFromDeck.cpp +++ b/opm/core/fluid/RockFromDeck.cpp @@ -36,8 +36,6 @@ namespace Opm PermeabilityKind fillTensor(const EclipseGridParser& parser, std::vector*>& tensor, std::tr1::array& kmap); - - int numGlobalCells(const EclipseGridParser& parser); } // anonymous namespace @@ -334,26 +332,6 @@ namespace Opm return kind; } - int numGlobalCells(const EclipseGridParser& parser) - { - int ngc = -1; - - if (parser.hasField("DIMENS")) { - const std::vector& - dims = parser.getIntegerValue("DIMENS"); - - ngc = dims[0] * dims[1] * dims[2]; - } - else if (parser.hasField("SPECGRID")) { - const SPECGRID& sgr = parser.getSPECGRID(); - - ngc = sgr.dimensions[ 0 ]; - ngc *= sgr.dimensions[ 1 ]; - ngc *= sgr.dimensions[ 2 ]; - } - - return ngc; - } } // anonymous namespace } // namespace Opm From a26c6779c64f6e227e0d6d705e2ca42f45c50067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Fri, 24 Aug 2012 12:52:41 +0200 Subject: [PATCH 30/58] Corrected typing pointed out by atgeirr in respose to pullrequest --- opm/core/transport/reorder/TransportModelTwophase.cpp | 8 ++++++-- opm/core/transport/reorder/TransportModelTwophase.hpp | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelTwophase.cpp b/opm/core/transport/reorder/TransportModelTwophase.cpp index 49cafa49a..b6451809b 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelTwophase.cpp @@ -171,7 +171,7 @@ namespace Opm // if (std::fabs(r0) < tol_) { // return; // } - int iters_used=0; + int iters_used = 0; // saturation_[cell] = modifiedRegulaFalsi(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); saturation_[cell] = RootFinder::solve(res, saturation_[cell], 0.0, 1.0, maxit_, tol_, iters_used); // add if it is iteration on an out loop @@ -547,7 +547,7 @@ namespace Opm const int cell = cells[pos]; GravityResidual res(*this, cells, pos, gravflux); if (std::fabs(res(saturation_[cell])) > tol_) { - int iters_used=0; + int iters_used = 0; saturation_[cell] = RootFinder::solve(res, smin_[2*cell], smax_[2*cell], maxit_, tol_, iters_used); reorder_iterations_[cell] = reorder_iterations_[cell] + iters_used; } @@ -645,6 +645,10 @@ namespace Opm toBothSat(saturation_, saturation); } + void TransportModelTwophase::getReorderIterations() + { + return reorder_iterations_; + }; } // namespace Opm diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index 692976079..358baaa31 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -74,7 +74,9 @@ namespace Opm const double* porevolume, const double dt, std::vector& saturation); - void reportIterations(std::ostream &os); + //// Return reorder iterations + //// + //// \param[out] vector of iteration per cell const std::vector& getReorderIterations(){return reorder_iterations_;}; private: virtual void solveSingleCell(const int cell); From 46fb4884106883fb5e8d14d26c0531290bf8279a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Fri, 24 Aug 2012 13:31:23 +0200 Subject: [PATCH 31/58] Minor code cleanup in TransportModelTwophase. --- .../transport/reorder/TransportModelTwophase.cpp | 14 +++++++++----- .../transport/reorder/TransportModelTwophase.hpp | 9 +++++---- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelTwophase.cpp b/opm/core/transport/reorder/TransportModelTwophase.cpp index b6451809b..2740d065e 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelTwophase.cpp @@ -52,8 +52,8 @@ namespace Opm source_(0), dt_(0.0), saturation_(grid.number_of_cells, -1.0), - reorder_iterations_(grid.number_of_cells, 0), fractionalflow_(grid.number_of_cells, -1.0), + reorder_iterations_(grid.number_of_cells, 0), mob_(2*grid.number_of_cells, -1.0) #ifdef EXPERIMENT_GAUSS_SEIDEL , ia_upw_(grid.number_of_cells + 1, -1), @@ -107,6 +107,13 @@ namespace Opm toBothSat(saturation_, saturation); } + + const std::vector& TransportModelTwophase::getReorderIterations() const + { + return reorder_iterations_; + } + + // Residual function r(s) for a single-cell implicit Euler transport // // r(s) = s - s0 + dt/pv*( influx + outflux*f(s) ) @@ -645,10 +652,7 @@ namespace Opm toBothSat(saturation_, saturation); } - void TransportModelTwophase::getReorderIterations() - { - return reorder_iterations_; - }; + } // namespace Opm diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index 358baaa31..3630ada8f 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -74,10 +74,11 @@ namespace Opm const double* porevolume, const double dt, std::vector& saturation); - //// Return reorder iterations - //// + + //// Return the number of iterations used by the reordering solver. //// \param[out] vector of iteration per cell - const std::vector& getReorderIterations(){return reorder_iterations_;}; + const std::vector& getReorderIterations() const; + private: virtual void solveSingleCell(const int cell); virtual void solveMultiCell(const int num_cells, const int* cells); @@ -86,7 +87,7 @@ namespace Opm const int pos, const double* gravflux); int solveGravityColumn(const std::vector& cells); - private: + private: const UnstructuredGrid& grid_; const IncompPropertiesInterface& props_; const double* visc_; From 0da049f4c8cb1b37f91119994b8830f7d59a42a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Fri, 24 Aug 2012 13:39:42 +0200 Subject: [PATCH 32/58] Corrected mistake from moving function calls. --- opm/core/transport/reorder/TransportModelTwophase.cpp | 2 +- opm/core/transport/reorder/TransportModelTwophase.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/transport/reorder/TransportModelTwophase.cpp b/opm/core/transport/reorder/TransportModelTwophase.cpp index b6451809b..3346d28ea 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelTwophase.cpp @@ -645,7 +645,7 @@ namespace Opm toBothSat(saturation_, saturation); } - void TransportModelTwophase::getReorderIterations() + const std::vector& TransportModelTwophase::getReorderIterations() { return reorder_iterations_; }; diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index 358baaa31..64449f9f1 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -77,7 +77,7 @@ namespace Opm //// Return reorder iterations //// //// \param[out] vector of iteration per cell - const std::vector& getReorderIterations(){return reorder_iterations_;}; + const std::vector& getReorderIterations(); private: virtual void solveSingleCell(const int cell); virtual void solveMultiCell(const int num_cells, const int* cells); From 0a8ac1ddb52bd9e92daee9b1fc79f6c936d1c1f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 27 Aug 2012 09:48:06 +0200 Subject: [PATCH 33/58] Minor revision, mostly whitespace cleanup and comments. --- opm/core/pressure/CompressibleTpfa.cpp | 6 +++--- opm/core/pressure/CompressibleTpfa.hpp | 16 ++++++++-------- .../TransportModelCompressibleTwophase.cpp | 2 +- .../transport/reorder/TransportModelTwophase.hpp | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/opm/core/pressure/CompressibleTpfa.cpp b/opm/core/pressure/CompressibleTpfa.cpp index 67d3a651a..954e07fa4 100644 --- a/opm/core/pressure/CompressibleTpfa.cpp +++ b/opm/core/pressure/CompressibleTpfa.cpp @@ -504,13 +504,13 @@ namespace Opm cq.phasemobf = &face_phasemob_[0]; cq.voldiscr = &cell_voldisc_[0]; int was_adjusted = 0; - if (rock_comp_props_ == NULL || !rock_comp_props_->isActive()) { - was_adjusted = + if (! (rock_comp_props_ && rock_comp_props_->isActive())) { + was_adjusted = cfs_tpfa_res_assemble(gg, dt, &forces, z, &cq, &trans_[0], &face_gravcap_[0], cell_press, well_bhp, &porevol_[0], h_); } else { - was_adjusted = + was_adjusted = cfs_tpfa_res_comprock_assemble(gg, dt, &forces, z, &cq, &trans_[0], &face_gravcap_[0], cell_press, well_bhp, &porevol_[0], &initial_porevol_[0], diff --git a/opm/core/pressure/CompressibleTpfa.hpp b/opm/core/pressure/CompressibleTpfa.hpp index 9fc5c43fd..054ac2e4f 100644 --- a/opm/core/pressure/CompressibleTpfa.hpp +++ b/opm/core/pressure/CompressibleTpfa.hpp @@ -61,7 +61,7 @@ namespace Opm /// and completions does not change during the /// run. However, controls (only) are allowed /// to change. - CompressibleTpfa(const UnstructuredGrid& grid, + CompressibleTpfa(const UnstructuredGrid& grid, const BlackoilPropertiesInterface& props, const RockCompressibility* rock_comp_props, const LinearSolverInterface& linsolver, @@ -71,8 +71,8 @@ namespace Opm const double* gravity, const Wells* wells); - /// Destructor. - ~CompressibleTpfa(); + /// Destructor. + ~CompressibleTpfa(); /// Solve the pressure equation by Newton-Raphson scheme. /// May throw an exception if the number of iterations @@ -112,11 +112,11 @@ namespace Opm void solveIncrement(); double residualNorm() const; double incrementNorm() const; - void computeResults(BlackoilState& state, + void computeResults(BlackoilState& state, WellState& well_state) const; // ------ Data that will remain unmodified after construction. ------ - const UnstructuredGrid& grid_; + const UnstructuredGrid& grid_; const BlackoilPropertiesInterface& props_; const RockCompressibility* rock_comp_props_; const LinearSolverInterface& linsolver_; @@ -125,12 +125,12 @@ namespace Opm const int maxiter_; const double* gravity_; // May be NULL const Wells* wells_; // May be NULL, outside may modify controls (only) between calls to solve(). - std::vector htrans_; - std::vector trans_ ; + std::vector htrans_; + std::vector trans_ ; std::vector allcells_; // ------ Internal data for the cfs_tpfa_res solver. ------ - struct cfs_tpfa_res_data* h_; + struct cfs_tpfa_res_data* h_; // ------ Data that will be modified for every solve. ------ std::vector wellperf_gpot_; diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index c2d503275..697f94a57 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -96,7 +96,7 @@ namespace Opm props_.viscosity(props_.numCells(), pressure, NULL, &allcells_[0], &visc_[0], NULL); props_.matrix(props_.numCells(), pressure, NULL, &allcells_[0], &A_[0], NULL); - // Check non-miscibility requirement (only done for first cell). + // Check immiscibility requirement (only done for first cell). if (A_[1] != 0.0 || A_[2] != 0.0) { THROW("TransportModelCompressibleTwophase requires a property object without miscibility."); } diff --git a/opm/core/transport/reorder/TransportModelTwophase.hpp b/opm/core/transport/reorder/TransportModelTwophase.hpp index 3630ada8f..97386c8af 100644 --- a/opm/core/transport/reorder/TransportModelTwophase.hpp +++ b/opm/core/transport/reorder/TransportModelTwophase.hpp @@ -76,7 +76,7 @@ namespace Opm std::vector& saturation); //// Return the number of iterations used by the reordering solver. - //// \param[out] vector of iteration per cell + //// \return vector of iteration per cell const std::vector& getReorderIterations() const; private: From 9bb76d74cc7987ab9696d1f135976edf6d2fc6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 27 Aug 2012 11:19:22 +0200 Subject: [PATCH 34/58] Fixed bug in matrix multiplication (matrix has Fortran element order). --- opm/core/utility/miscUtilitiesBlackoil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/utility/miscUtilitiesBlackoil.cpp b/opm/core/utility/miscUtilitiesBlackoil.cpp index 548aaa23a..74eb1c9c5 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.cpp +++ b/opm/core/utility/miscUtilitiesBlackoil.cpp @@ -245,7 +245,7 @@ namespace Opm for (int i = 0; i < n; ++i) { for (int row = 0; row < np; ++row) { for (int col = 0; col < np; ++col) { - surfacevol[i*np + row] += A[i*np*np + row*np + col] * saturation[i*np + col]; + surfacevol[i*np + row] += A[i*np*np + row + col*np] * saturation[i*np + col]; } } } From 9ef601496459f753b575da822db1c07dce14aed5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Mon, 27 Aug 2012 12:20:03 +0200 Subject: [PATCH 35/58] Addes support for initialisation of three phases using SWOF and SGOF --- opm/core/utility/initState_impl.hpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/opm/core/utility/initState_impl.hpp b/opm/core/utility/initState_impl.hpp index c50db8a91..f66704348 100644 --- a/opm/core/utility/initState_impl.hpp +++ b/opm/core/utility/initState_impl.hpp @@ -512,11 +512,12 @@ namespace Opm State& state) { const int num_phases = props.numPhases(); - if (num_phases != 2) { - THROW("initStateFromDeck(): currently handling only two-phase scenarios."); - } + state.init(grid, num_phases); if (deck.hasField("EQUIL")) { + if (num_phases != 2) { + THROW("initStateFromDeck(): currently handling only two-phase scenarios."); + } // Set saturations depending on oil-water contact. const EQUIL& equil= deck.getEQUIL(); if (equil.equil.size() != 1) { @@ -535,11 +536,22 @@ namespace Opm const std::vector& sw_deck = deck.getFloatingPointValue("SWAT"); const std::vector& p_deck = deck.getFloatingPointValue("PRESSURE"); const int num_cells = grid.number_of_cells; - for (int c = 0; c < num_cells; ++c) { - int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; - s[2*c] = sw_deck[c_deck]; - s[2*c + 1] = 1.0 - s[2*c]; - p[c] = p_deck[c_deck]; + if(num_phases == 2){ + for (int c = 0; c < num_cells; ++c) { + int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; + s[2*c] = sw_deck[c_deck]; + s[2*c + 1] = 1.0 - s[2*c]; + p[c] = p_deck[c_deck]; + } + }else{ + const std::vector& sg_deck = deck.getFloatingPointValue("SGAS"); + for (int c = 0; c < num_cells; ++c) { + int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; + s[2*c] = sw_deck[c_deck]; + s[2*c + 1] = 1.0 - (sw_deck[c_deck] + sg_deck[c_deck]); + s[2*c + 2] = sg_deck[c_deck]; + p[c] = p_deck[c_deck]; + } } } else { THROW("initStateFromDeck(): we must either have EQUIL, or both SWAT and PRESSURE."); From cf9b9cdf20c0150059a944ae3f7a218b2d9ca568 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Mon, 27 Aug 2012 12:22:32 +0200 Subject: [PATCH 36/58] Started work on supporting 3 phases for wellreport. --- opm/core/utility/miscUtilities.cpp | 45 +++++++++++++++++++----------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/opm/core/utility/miscUtilities.cpp b/opm/core/utility/miscUtilities.cpp index 16c59b17e..cc7ff1276 100644 --- a/opm/core/utility/miscUtilities.cpp +++ b/opm/core/utility/miscUtilities.cpp @@ -574,9 +574,10 @@ namespace Opm { int nw = well_bhp.size(); ASSERT(nw == wells.number_of_wells); - if (props.numPhases() != 2) { - THROW("WellReport for now assumes two phase flow."); - } + int np = props.numPhases(); + //if (props.numPhases() != 2) { + // THROW("WellReport for now assumes two phase flow."); + //} const double* visc = props.viscosity(); std::vector data_now; data_now.reserve(1 + 3*nw); @@ -586,7 +587,8 @@ namespace Opm double well_rate_total = 0.0; double well_rate_water = 0.0; for (int perf = wells.well_connpos[w]; perf < wells.well_connpos[w + 1]; ++perf) { - const double perf_rate = well_perfrates[perf]*(unit::day/unit::second); + const double perf_rate = unit::convert::to(well_perfrates[perf], + unit::cubic(unit::meter)/unit::day); well_rate_total += perf_rate; if (perf_rate > 0.0) { // Injection. @@ -594,11 +596,14 @@ namespace Opm } else { // Production. const int cell = wells.well_cells[perf]; - double mob[2]; + double mob[np]; props.relperm(1, &saturation[2*cell], &cell, mob, 0); - mob[0] /= visc[0]; - mob[1] /= visc[1]; - const double fracflow = mob[0]/(mob[0] + mob[1]); + double tmob=0; + for(int i=0; i < np; ++i){ + mob[i] /= visc[i]; + tmob += mob[i]; + } + const double fracflow = mob[0]/tmob; well_rate_water += perf_rate*fracflow; } } @@ -627,9 +632,10 @@ namespace Opm // TODO: refactor, since this is almost identical to the other push(). int nw = well_bhp.size(); ASSERT(nw == wells.number_of_wells); - if (props.numPhases() != 2) { - THROW("WellReport for now assumes two phase flow."); - } + int np = props.numPhases(); + //if (props.numPhases() != 2) { + // THROW("WellReport for now assumes two phase flow."); + //} std::vector data_now; data_now.reserve(1 + 3*nw); data_now.push_back(time/unit::day); @@ -640,20 +646,25 @@ namespace Opm for (int perf = wells.well_connpos[w]; perf < wells.well_connpos[w + 1]; ++perf) { const double perf_rate = well_perfrates[perf]*(unit::day/unit::second); well_rate_total += perf_rate; - if (perf_rate > 0.0) { + if (perf_rate > 0.0) { // Injection. well_rate_water += perf_rate*wells.comp_frac[0]; } else { // Production. const int cell = wells.well_cells[perf]; - double mob[2]; + double mob[np]; props.relperm(1, &s[2*cell], &cell, mob, 0); - double visc[2]; + double visc[np]; props.viscosity(1, &p[cell], &z[2*cell], &cell, visc, 0); - mob[0] /= visc[0]; - mob[1] /= visc[1]; - const double fracflow = mob[0]/(mob[0] + mob[1]); + double tmob=0; + for(int i=0; i < np; ++i){ + mob[i] /= visc[i]; + tmob += mob[i]; + } + const double fracflow = mob[0]/(tmob); well_rate_water += perf_rate*fracflow; + //const double fracflow = mob[0]/(tmob); + //well_rate_water += perf_rate*fracflow; } } data_now.push_back(well_rate_total); From 5182fef48d18ee6b47f41578c57e811dcbb83c5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 27 Aug 2012 13:17:27 +0200 Subject: [PATCH 37/58] Switch loop ordering for better cache performance. --- opm/core/utility/miscUtilitiesBlackoil.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/core/utility/miscUtilitiesBlackoil.cpp b/opm/core/utility/miscUtilitiesBlackoil.cpp index 74eb1c9c5..6f4f75565 100644 --- a/opm/core/utility/miscUtilitiesBlackoil.cpp +++ b/opm/core/utility/miscUtilitiesBlackoil.cpp @@ -243,8 +243,8 @@ namespace Opm // matrix data. std::fill(surfacevol, surfacevol + n*np, 0.0); for (int i = 0; i < n; ++i) { - for (int row = 0; row < np; ++row) { - for (int col = 0; col < np; ++col) { + for (int col = 0; col < np; ++col) { + for (int row = 0; row < np; ++row) { surfacevol[i*np + row] += A[i*np*np + row + col*np] * saturation[i*np + col]; } } From af8a6fa7da151c9a8930610f9c0489c39a070674 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Mon, 27 Aug 2012 13:19:04 +0200 Subject: [PATCH 38/58] Changed private->protected and added virtual to make class derivation. --- opm/core/pressure/CompressibleTpfa.hpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/opm/core/pressure/CompressibleTpfa.hpp b/opm/core/pressure/CompressibleTpfa.hpp index 9fc5c43fd..affada84e 100644 --- a/opm/core/pressure/CompressibleTpfa.hpp +++ b/opm/core/pressure/CompressibleTpfa.hpp @@ -90,16 +90,15 @@ namespace Opm bool singularPressure() const; private: - void computePerSolveDynamicData(const double dt, - const BlackoilState& state, - const WellState& well_state); - void computeWellPotentials(const BlackoilState& state); + virtual void computePerSolveDynamicData(const double dt, + const BlackoilState& state, + const WellState& well_state); void computePerIterationDynamicData(const double dt, const BlackoilState& state, const WellState& well_state); - void computeCellDynamicData(const double dt, - const BlackoilState& state, - const WellState& well_state); + virtual void computeCellDynamicData(const double dt, + const BlackoilState& state, + const WellState& well_state); void computeFaceDynamicData(const double dt, const BlackoilState& state, const WellState& well_state); @@ -114,6 +113,8 @@ namespace Opm double incrementNorm() const; void computeResults(BlackoilState& state, WellState& well_state) const; + protected: + void computeWellPotentials(const BlackoilState& state); // ------ Data that will remain unmodified after construction. ------ const UnstructuredGrid& grid_; From d9cff689b49f382a20ed61c28ef64180a2cea5f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 27 Aug 2012 16:48:21 +0200 Subject: [PATCH 39/58] Added class SinglePvtDead, add parameter 'props_use_spline' to simulators. Recall that the class that used to be called SinglePvtDead has been renamed to SinglePvtDeadSpline. If 'props_use_spline' is true, that class is used (this is the default), which makes a monotone spline that is uniformly, densely sampled. The new class simply uses linear interpolation in the input tables. --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 5 +++-- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 3 ++- opm/core/fluid/blackoil/BlackoilPvtProperties.hpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index 004e6f88f..e7244d87c 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -23,10 +23,11 @@ namespace Opm { BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid) + const UnstructuredGrid& grid, + const bool use_spline) { rock_.init(deck, grid); - pvt_.init(deck); + pvt_.init(deck, use_spline); satprops_.init(deck, grid); if (pvt_.numPhases() != satprops_.numPhases()) { THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index a2a6c3de9..c434b7f4b 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -43,7 +43,8 @@ namespace Opm /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid); + const UnstructuredGrid& grid, + const bool use_spline); /// Destructor. virtual ~BlackoilPropertiesFromDeck(); diff --git a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp index 627f266b7..ca193a4d4 100644 --- a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp +++ b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp @@ -47,7 +47,7 @@ namespace Opm BlackoilPvtProperties(); /// Initialize from deck. - void init(const EclipseGridParser& deck); + void init(const EclipseGridParser& deck, const bool use_spline); /// Number of active phases. int numPhases() const; From 7a79bd1872ff5e3207c96d7dfcb98dae0194521e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 27 Aug 2012 17:56:01 +0200 Subject: [PATCH 40/58] Enable choice of spline-smoothed saturation props (or not). --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 22 +- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 3 +- opm/core/fluid/IncompPropertiesFromDeck.hpp | 2 +- opm/core/fluid/SaturationPropsFromDeck.hpp | 45 ++- .../fluid/SaturationPropsFromDeck_impl.hpp | 271 ++++++++++++++++++ opm/core/fluid/SaturationPropsInterface.hpp | 85 ++++++ 6 files changed, 397 insertions(+), 31 deletions(-) create mode 100644 opm/core/fluid/SaturationPropsFromDeck_impl.hpp create mode 100644 opm/core/fluid/SaturationPropsInterface.hpp diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index e7244d87c..fdc9519cf 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -28,10 +28,20 @@ namespace Opm { rock_.init(deck, grid); pvt_.init(deck, use_spline); - satprops_.init(deck, grid); - if (pvt_.numPhases() != satprops_.numPhases()) { + // Unfortunate lack of pointer smartness here... + if (use_spline) { + SaturationPropsFromDeck<>* ptr = new SaturationPropsFromDeck<>(); + ptr->init(deck, grid); + satprops_.reset(ptr); + } else { + SaturationPropsFromDeck* ptr + = new SaturationPropsFromDeck(); + ptr->init(deck, grid); + satprops_.reset(ptr); + } + if (pvt_.numPhases() != satprops_->numPhases()) { THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ")."); } } @@ -236,7 +246,7 @@ namespace Opm double* kr, double* dkrds) const { - satprops_.relperm(n, s, cells, kr, dkrds); + satprops_->relperm(n, s, cells, kr, dkrds); } @@ -255,7 +265,7 @@ namespace Opm double* pc, double* dpcds) const { - satprops_.capPress(n, s, cells, pc, dpcds); + satprops_->capPress(n, s, cells, pc, dpcds); } @@ -271,7 +281,7 @@ namespace Opm double* smin, double* smax) const { - satprops_.satRange(n, cells, smin, smax); + satprops_->satRange(n, cells, smin, smax); } diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index c434b7f4b..60dc1e754 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -26,6 +26,7 @@ #include #include #include +#include struct UnstructuredGrid; @@ -166,7 +167,7 @@ namespace Opm private: RockFromDeck rock_; BlackoilPvtProperties pvt_; - SaturationPropsFromDeck satprops_; + boost::scoped_ptr satprops_; mutable std::vector B_; mutable std::vector dB_; mutable std::vector R_; diff --git a/opm/core/fluid/IncompPropertiesFromDeck.hpp b/opm/core/fluid/IncompPropertiesFromDeck.hpp index 68623e5cc..5820bb668 100644 --- a/opm/core/fluid/IncompPropertiesFromDeck.hpp +++ b/opm/core/fluid/IncompPropertiesFromDeck.hpp @@ -135,7 +135,7 @@ namespace Opm private: RockFromDeck rock_; PvtPropertiesIncompFromDeck pvt_; - SaturationPropsFromDeck satprops_; + SaturationPropsFromDeck<> satprops_; }; diff --git a/opm/core/fluid/SaturationPropsFromDeck.hpp b/opm/core/fluid/SaturationPropsFromDeck.hpp index b83a12711..a978bbac0 100644 --- a/opm/core/fluid/SaturationPropsFromDeck.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck.hpp @@ -20,8 +20,8 @@ #ifndef OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED #define OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED +#include #include -#include #include #include @@ -30,7 +30,23 @@ struct UnstructuredGrid; namespace Opm { - class SaturationPropsFromDeck : public BlackoilPhases + + /// Class storing saturation functions in a uniform table, + /// densely sampled from a monotone spline, + /// using linear interpolation. + class SatFuncSetUniform; + + /// Class storing saturation functions in a nonuniform table + /// using linear interpolation. + class SatFuncSetNonuniform; + + + /// Interface to saturation functions from deck. + /// Possible values for template argument: + /// SatFuncSetNonuniform, + /// SatFuncSetUniform (default). + template + class SaturationPropsFromDeck : public SaturationPropsInterface { public: /// Default constructor. @@ -88,30 +104,12 @@ namespace Opm private: PhaseUsage phase_usage_; - class SatFuncSet - { - public: - void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg); - void evalKr(const double* s, double* kr) const; - void evalKrDeriv(const double* s, double* kr, double* dkrds) const; - void evalPc(const double* s, double* pc) const; - void evalPcDeriv(const double* s, double* pc, double* dpcds) const; - double smin_[PhaseUsage::MaxNumPhases]; - double smax_[PhaseUsage::MaxNumPhases]; - private: - PhaseUsage phase_usage; // A copy of the outer class' phase_usage_. - UniformTableLinear krw_; - UniformTableLinear krow_; - UniformTableLinear pcow_; - UniformTableLinear krg_; - UniformTableLinear krog_; - UniformTableLinear pcog_; - double krocw_; // = krow_(s_wc) - }; std::vector satfuncset_; std::vector cell_to_func_; // = SATNUM - 1 - const SatFuncSet& funcForCell(const int cell) const; + typedef SatFuncSet Funcs; + + const Funcs& funcForCell(const int cell) const; }; @@ -119,6 +117,7 @@ namespace Opm } // namespace Opm +#include #endif // OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED diff --git a/opm/core/fluid/SaturationPropsFromDeck_impl.hpp b/opm/core/fluid/SaturationPropsFromDeck_impl.hpp new file mode 100644 index 000000000..f64f12bcf --- /dev/null +++ b/opm/core/fluid/SaturationPropsFromDeck_impl.hpp @@ -0,0 +1,271 @@ +/* + Copyright 2012 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED +#define OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED + + +#include +#include +#include +#include + +namespace Opm +{ + + /// Class storing saturation functions in a uniform table, + /// densely sampled from a monotone spline, + /// using linear interpolation. + class SatFuncSetUniform : public BlackoilPhases + { + public: + void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg); + void evalKr(const double* s, double* kr) const; + void evalKrDeriv(const double* s, double* kr, double* dkrds) const; + void evalPc(const double* s, double* pc) const; + void evalPcDeriv(const double* s, double* pc, double* dpcds) const; + double smin_[PhaseUsage::MaxNumPhases]; + double smax_[PhaseUsage::MaxNumPhases]; + private: + PhaseUsage phase_usage; // A copy of the outer class' phase_usage_. + UniformTableLinear krw_; + UniformTableLinear krow_; + UniformTableLinear pcow_; + UniformTableLinear krg_; + UniformTableLinear krog_; + UniformTableLinear pcog_; + double krocw_; // = krow_(s_wc) + }; + + + + + /// Class storing saturation functions in a nonuniform table + /// using linear interpolation. + class SatFuncSetNonuniform : public BlackoilPhases + { + public: + void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg); + void evalKr(const double* s, double* kr) const; + void evalKrDeriv(const double* s, double* kr, double* dkrds) const; + void evalPc(const double* s, double* pc) const; + void evalPcDeriv(const double* s, double* pc, double* dpcds) const; + double smin_[PhaseUsage::MaxNumPhases]; + double smax_[PhaseUsage::MaxNumPhases]; + private: + PhaseUsage phase_usage; // A copy of the outer class' phase_usage_. + NonuniformTableLinear krw_; + NonuniformTableLinear krow_; + NonuniformTableLinear pcow_; + NonuniformTableLinear krg_; + NonuniformTableLinear krog_; + NonuniformTableLinear pcog_; + double krocw_; // = krow_(s_wc) + }; + + + + // ----------- Methods of SaturationPropsFromDeck --------- + + + /// Default constructor. + template + SaturationPropsFromDeck::SaturationPropsFromDeck() + { + } + + /// Initialize from deck. + template + void SaturationPropsFromDeck::init(const EclipseGridParser& deck, + const UnstructuredGrid& grid) + { + phase_usage_ = phaseUsageFromDeck(deck); + + // Extract input data. + // Oil phase should be active. + if (!phase_usage_.phase_used[Liquid]) { + THROW("SaturationPropsFromDeck::init() -- oil phase must be active."); + } + + // Obtain SATNUM, if it exists, and create cell_to_func_. + // Otherwise, let the cell_to_func_ mapping be just empty. + int satfuncs_expected = 1; + if (deck.hasField("SATNUM")) { + const std::vector& satnum = deck.getIntegerValue("SATNUM"); + satfuncs_expected = *std::max_element(satnum.begin(), satnum.end()); + const int num_cells = grid.number_of_cells; + cell_to_func_.resize(num_cells); + const int* gc = grid.global_cell; + for (int cell = 0; cell < num_cells; ++cell) { + const int deck_pos = (gc == NULL) ? cell : gc[cell]; + cell_to_func_[cell] = satnum[deck_pos] - 1; + } + } + + // Find number of tables, check for consistency. + enum { Uninitialized = -1 }; + int num_tables = Uninitialized; + if (phase_usage_.phase_used[Aqua]) { + const SWOF::table_t& swof_table = deck.getSWOF().swof_; + num_tables = swof_table.size(); + if (num_tables < satfuncs_expected) { + THROW("Found " << num_tables << " SWOF tables, SATNUM specifies at least " << satfuncs_expected); + } + } + if (phase_usage_.phase_used[Vapour]) { + const SGOF::table_t& sgof_table = deck.getSGOF().sgof_; + int num_sgof_tables = sgof_table.size(); + if (num_sgof_tables < satfuncs_expected) { + THROW("Found " << num_tables << " SGOF tables, SATNUM specifies at least " << satfuncs_expected); + } + if (num_tables == Uninitialized) { + num_tables = num_sgof_tables; + } else if (num_tables != num_sgof_tables) { + THROW("Inconsistent number of tables in SWOF and SGOF."); + } + } + + // Initialize tables. + satfuncset_.resize(num_tables); + for (int table = 0; table < num_tables; ++table) { + satfuncset_[table].init(deck, table, phase_usage_); + } + } + + + + + /// \return P, the number of phases. + template + int SaturationPropsFromDeck::numPhases() const + { + return phase_usage_.num_phases; + } + + + + + /// Relative permeability. + /// \param[in] n Number of data points. + /// \param[in] s Array of nP saturation values. + /// \param[in] cells Array of n cell indices to be associated with the s values. + /// \param[out] kr Array of nP relperm values, array must be valid before calling. + /// \param[out] dkrds If non-null: array of nP^2 relperm derivative values, + /// array must be valid before calling. + /// The P^2 derivative matrix is + /// m_{ij} = \frac{dkr_i}{ds^j}, + /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) + template + void SaturationPropsFromDeck::relperm(const int n, + const double* s, + const int* cells, + double* kr, + double* dkrds) const + { + ASSERT (cells != 0); + + const int np = phase_usage_.num_phases; + if (dkrds) { +// #pragma omp parallel for + for (int i = 0; i < n; ++i) { + funcForCell(cells[i]).evalKrDeriv(s + np*i, kr + np*i, dkrds + np*np*i); + } + } else { +// #pragma omp parallel for + for (int i = 0; i < n; ++i) { + funcForCell(cells[i]).evalKr(s + np*i, kr + np*i); + } + } + } + + + + + /// Capillary pressure. + /// \param[in] n Number of data points. + /// \param[in] s Array of nP saturation values. + /// \param[in] cells Array of n cell indices to be associated with the s values. + /// \param[out] pc Array of nP capillary pressure values, array must be valid before calling. + /// \param[out] dpcds If non-null: array of nP^2 derivative values, + /// array must be valid before calling. + /// The P^2 derivative matrix is + /// m_{ij} = \frac{dpc_i}{ds^j}, + /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) + template + void SaturationPropsFromDeck::capPress(const int n, + const double* s, + const int* cells, + double* pc, + double* dpcds) const + { + ASSERT (cells != 0); + + const int np = phase_usage_.num_phases; + if (dpcds) { +// #pragma omp parallel for + for (int i = 0; i < n; ++i) { + funcForCell(cells[i]).evalPcDeriv(s + np*i, pc + np*i, dpcds + np*np*i); + } + } else { +// #pragma omp parallel for + for (int i = 0; i < n; ++i) { + funcForCell(cells[i]).evalPc(s + np*i, pc + np*i); + } + } + } + + + + + /// Obtain the range of allowable saturation values. + /// \param[in] n Number of data points. + /// \param[in] cells Array of n cell indices. + /// \param[out] smin Array of nP minimum s values, array must be valid before calling. + /// \param[out] smax Array of nP maximum s values, array must be valid before calling. + template + void SaturationPropsFromDeck::satRange(const int n, + const int* cells, + double* smin, + double* smax) const + { + ASSERT (cells != 0); + + const int np = phase_usage_.num_phases; + for (int i = 0; i < n; ++i) { + for (int p = 0; p < np; ++p) { + smin[np*i + p] = funcForCell(cells[i]).smin_[p]; + smax[np*i + p] = funcForCell(cells[i]).smax_[p]; + } + } + } + + + // Map the cell number to the correct function set. + template + const typename SaturationPropsFromDeck::Funcs& + SaturationPropsFromDeck::funcForCell(const int cell) const + { + return cell_to_func_.empty() ? satfuncset_[0] : satfuncset_[cell_to_func_[cell]]; + } + + + +} // namespace Opm + +#endif // OPM_SATURATIONPROPSFROMDECK_IMPL_HEADER_INCLUDED diff --git a/opm/core/fluid/SaturationPropsInterface.hpp b/opm/core/fluid/SaturationPropsInterface.hpp new file mode 100644 index 000000000..e55995677 --- /dev/null +++ b/opm/core/fluid/SaturationPropsInterface.hpp @@ -0,0 +1,85 @@ +/* + Copyright 2012 SINTEF ICT, Applied Mathematics. + + This file is part of the Open Porous Media project (OPM). + + OPM is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OPM is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OPM. If not, see . +*/ + +#ifndef OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED +#define OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED + +#include + + +namespace Opm +{ + + class SaturationPropsInterface : public BlackoilPhases + { + public: + /// Virtual destructor. + virtual ~SaturationPropsInterface() {}; + + /// \return P, the number of phases. + virtual int numPhases() const = 0; + + /// Relative permeability. + /// \param[in] n Number of data points. + /// \param[in] s Array of nP saturation values. + /// \param[out] kr Array of nP relperm values, array must be valid before calling. + /// \param[out] dkrds If non-null: array of nP^2 relperm derivative values, + /// array must be valid before calling. + /// The P^2 derivative matrix is + /// m_{ij} = \frac{dkr_i}{ds^j}, + /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) + virtual void relperm(const int n, + const double* s, + const int* cells, + double* kr, + double* dkrds) const = 0; + + /// Capillary pressure. + /// \param[in] n Number of data points. + /// \param[in] s Array of nP saturation values. + /// \param[out] pc Array of nP capillary pressure values, array must be valid before calling. + /// \param[out] dpcds If non-null: array of nP^2 derivative values, + /// array must be valid before calling. + /// The P^2 derivative matrix is + /// m_{ij} = \frac{dpc_i}{ds^j}, + /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) + virtual void capPress(const int n, + const double* s, + const int* cells, + double* pc, + double* dpcds) const = 0; + + /// Obtain the range of allowable saturation values. + /// \param[in] n Number of data points. + /// \param[out] smin Array of nP minimum s values, array must be valid before calling. + /// \param[out] smax Array of nP maximum s values, array must be valid before calling. + virtual void satRange(const int n, + const int* cells, + double* smin, + double* smax) const = 0; + + }; + + + +} // namespace Opm + + + +#endif // OPM_SATURATIONPROPSINTERFACE_HEADER_INCLUDED From 9aa349b1e50040c20d9a6373e369888026441d62 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Tue, 28 Aug 2012 13:12:54 +0200 Subject: [PATCH 41/58] Corrected comment. --- .../transport/reorder/TransportModelCompressibleTwophase.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp index 697f94a57..01882053b 100644 --- a/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp +++ b/opm/core/transport/reorder/TransportModelCompressibleTwophase.cpp @@ -124,7 +124,7 @@ namespace Opm // // [[ incompressible was: r(s) = s - s0 + dt/pv*( influx + outflux*f(s) ) ]] // - // r(s) = s - B*z0 + dt/pv*( influx + outflux*f(s) ) + // r(s) = s - B*z0 + s*(poro - poro0)/poro0 + dt/pv*( influx + outflux*f(s) ) // // @@@ What about the source term // From 94c04f343d5187701bc1461fa90825af69ca9849 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Tue, 28 Aug 2012 14:27:14 +0200 Subject: [PATCH 42/58] Added param initializer on fluids with param to addjust table length. Moved internal class SatFunc to SatFuncStone2. --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 16 ++++++++- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 7 ++-- opm/core/fluid/SaturationPropsFromDeck.hpp | 33 +++++-------------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index 004e6f88f..ae6a61306 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -18,7 +18,7 @@ */ #include - +#include namespace Opm { @@ -34,6 +34,20 @@ namespace Opm } } + BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck, + const UnstructuredGrid& grid, + const parameter::ParameterGroup& param) + { + rock_.init(deck, grid); + pvt_.init(deck); + satprops_.init(deck, grid, param); + + if (pvt_.numPhases() != satprops_.numPhases()) { + THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + } + } + BlackoilPropertiesFromDeck::~BlackoilPropertiesFromDeck() { } diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index a2a6c3de9..1d0a0d380 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -26,6 +26,7 @@ #include #include #include +#include struct UnstructuredGrid; @@ -43,8 +44,10 @@ namespace Opm /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid); - + const UnstructuredGrid& grid); + BlackoilPropertiesFromDeck(const EclipseGridParser& deck, + const UnstructuredGrid& grid, + const parameter::ParameterGroup& param); /// Destructor. virtual ~BlackoilPropertiesFromDeck(); diff --git a/opm/core/fluid/SaturationPropsFromDeck.hpp b/opm/core/fluid/SaturationPropsFromDeck.hpp index b83a12711..2c6a89a06 100644 --- a/opm/core/fluid/SaturationPropsFromDeck.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck.hpp @@ -19,10 +19,11 @@ #ifndef OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED #define OPM_SATURATIONPROPSFROMDECK_HEADER_INCLUDED - +#include #include #include #include +#include #include struct UnstructuredGrid; @@ -44,6 +45,10 @@ namespace Opm void init(const EclipseGridParser& deck, const UnstructuredGrid& grid); + void init(const EclipseGridParser& deck, + const UnstructuredGrid& grid, + const parameter::ParameterGroup& param); + /// \return P, the number of phases. int numPhases() const; @@ -87,31 +92,11 @@ namespace Opm double* smax) const; private: - PhaseUsage phase_usage_; - class SatFuncSet - { - public: - void init(const EclipseGridParser& deck, const int table_num, PhaseUsage phase_usg); - void evalKr(const double* s, double* kr) const; - void evalKrDeriv(const double* s, double* kr, double* dkrds) const; - void evalPc(const double* s, double* pc) const; - void evalPcDeriv(const double* s, double* pc, double* dpcds) const; - double smin_[PhaseUsage::MaxNumPhases]; - double smax_[PhaseUsage::MaxNumPhases]; - private: - PhaseUsage phase_usage; // A copy of the outer class' phase_usage_. - UniformTableLinear krw_; - UniformTableLinear krow_; - UniformTableLinear pcow_; - UniformTableLinear krg_; - UniformTableLinear krog_; - UniformTableLinear pcog_; - double krocw_; // = krow_(s_wc) - }; - std::vector satfuncset_; + PhaseUsage phase_usage_; + std::vector satfuncset_; std::vector cell_to_func_; // = SATNUM - 1 - const SatFuncSet& funcForCell(const int cell) const; + const SatFuncStone2& funcForCell(const int cell) const; }; From 6852be422c458f6deb43ef6fc22eba7b561a02e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Tue, 28 Aug 2012 16:41:06 +0200 Subject: [PATCH 43/58] Added new SatFuncSimple fluid. Introduced a simple fluid which has no problem with strange black oil behavior. Intended for testing, but for now it is used in SaturationPropsFromDeck. --- opm/core/fluid/SaturationPropsFromDeck.hpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/opm/core/fluid/SaturationPropsFromDeck.hpp b/opm/core/fluid/SaturationPropsFromDeck.hpp index 2c6a89a06..bd70d8029 100644 --- a/opm/core/fluid/SaturationPropsFromDeck.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck.hpp @@ -24,6 +24,7 @@ #include #include #include +#include #include struct UnstructuredGrid; @@ -92,11 +93,12 @@ namespace Opm double* smax) const; private: - PhaseUsage phase_usage_; - std::vector satfuncset_; + PhaseUsage phase_usage_; + typedef SatFuncSimple satfunc_t; + std::vector satfuncset_; std::vector cell_to_func_; // = SATNUM - 1 - const SatFuncStone2& funcForCell(const int cell) const; + const satfunc_t& funcForCell(const int cell) const; }; From b4a4e297a884632a8992a162239c85f62c72a7f8 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Wed, 29 Aug 2012 10:54:21 +0200 Subject: [PATCH 44/58] Added functionality to compute porosity for compressible fluid. --- opm/core/utility/miscUtilities.cpp | 19 +++++++++++++++++++ opm/core/utility/miscUtilities.hpp | 11 +++++++++++ 2 files changed, 30 insertions(+) diff --git a/opm/core/utility/miscUtilities.cpp b/opm/core/utility/miscUtilities.cpp index 16c59b17e..ac9552dc3 100644 --- a/opm/core/utility/miscUtilities.cpp +++ b/opm/core/utility/miscUtilities.cpp @@ -70,6 +70,25 @@ namespace Opm } } + /// @brief Computes porosity of all cells in a grid, with rock compressibility effects. + /// @param[in] grid a grid + /// @param[in] porosity_standard array of grid.number_of_cells porosity values (at standard conditions) + /// @param[in] rock_comp rock compressibility properties + /// @param[in] pressure pressure by cell + /// @param[out] porosity porosity (at reservoir condition) + void computePorosity(const UnstructuredGrid& grid, + const double* porosity_standard, + const RockCompressibility& rock_comp, + const std::vector& pressure, + std::vector& porosity) + { + int num_cells = grid.number_of_cells; + porosity.resize(num_cells); + for (int i = 0; i < num_cells; ++i) { + porosity[i] = porosity_standard[i]*rock_comp.poroMult(pressure[i]); + } + } + /// @brief Computes total saturated volumes over all grid cells. /// @param[in] pv the pore volume by cell. diff --git a/opm/core/utility/miscUtilities.hpp b/opm/core/utility/miscUtilities.hpp index 37b252bc2..de452fbac 100644 --- a/opm/core/utility/miscUtilities.hpp +++ b/opm/core/utility/miscUtilities.hpp @@ -54,6 +54,17 @@ namespace Opm const std::vector& pressure, std::vector& porevol); + /// @brief Computes porosity of all cells in a grid, with rock compressibility effects. + /// @param[in] grid a grid + /// @param[in] porosity_standard array of grid.number_of_cells porosity values (at standard conditions) + /// @param[in] rock_comp rock compressibility properties + /// @param[in] pressure pressure by cell + /// @param[out] porosity porosity (at reservoir condition) + void computePorosity(const UnstructuredGrid& grid, + const double* porosity_standard, + const RockCompressibility& rock_comp, + const std::vector& pressure, + std::vector& porosity); /// @brief Computes total saturated volumes over all grid cells. /// @param[in] pv the pore volume by cell. From 2dede29f20824b5c2f089b91950c7fe6d474c7b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halvor=20M=C3=B8ll=20Nilsen?= Date: Fri, 31 Aug 2012 17:01:07 +0200 Subject: [PATCH 45/58] Introduced posibility to change number of sample points for pvt. Did change the PVTW calculation so derivatives are exact. Extended the test functions for pvt and relperm --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 3 ++- opm/core/fluid/blackoil/BlackoilPvtProperties.hpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index ae6a61306..67943fc76 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -39,7 +39,8 @@ namespace Opm const parameter::ParameterGroup& param) { rock_.init(deck, grid); - pvt_.init(deck); + int samples = param.getDefault("dead_tab_size", 1025); + pvt_.init(deck, samples); satprops_.init(deck, grid, param); if (pvt_.numPhases() != satprops_.numPhases()) { diff --git a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp index 627f266b7..99fd5b8f4 100644 --- a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp +++ b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp @@ -47,7 +47,7 @@ namespace Opm BlackoilPvtProperties(); /// Initialize from deck. - void init(const EclipseGridParser& deck); + void init(const EclipseGridParser& deck,const int samples = 16); /// Number of active phases. int numPhases() const; From 0701daa4dc2f8f2bb6a748ab2565e04591840c4b Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Mon, 3 Sep 2012 11:29:48 +0200 Subject: [PATCH 46/58] Improve documentation. --- opm/core/utility/miscUtilities.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/utility/miscUtilities.hpp b/opm/core/utility/miscUtilities.hpp index de452fbac..74cdc6748 100644 --- a/opm/core/utility/miscUtilities.hpp +++ b/opm/core/utility/miscUtilities.hpp @@ -44,7 +44,7 @@ namespace Opm /// @brief Computes pore volume of all cells in a grid, with rock compressibility effects. /// @param[in] grid a grid - /// @param[in] porosity array of grid.number_of_cells porosity values + /// @param[in] porosity array of grid.number_of_cells porosity values (at reference pressure) /// @param[in] rock_comp rock compressibility properties /// @param[in] pressure pressure by cell /// @param[out] porevol the pore volume by cell. From a8cb519d4eb194189d9a9bf9b7fc1cbf25468143 Mon Sep 17 00:00:00 2001 From: Xavier Raynaud Date: Mon, 3 Sep 2012 12:26:22 +0200 Subject: [PATCH 47/58] Fixed comment. --- opm/core/utility/miscUtilities.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/utility/miscUtilities.hpp b/opm/core/utility/miscUtilities.hpp index 74cdc6748..2def319a9 100644 --- a/opm/core/utility/miscUtilities.hpp +++ b/opm/core/utility/miscUtilities.hpp @@ -56,7 +56,7 @@ namespace Opm /// @brief Computes porosity of all cells in a grid, with rock compressibility effects. /// @param[in] grid a grid - /// @param[in] porosity_standard array of grid.number_of_cells porosity values (at standard conditions) + /// @param[in] porosity_standard array of grid.number_of_cells porosity values (at reference presure) /// @param[in] rock_comp rock compressibility properties /// @param[in] pressure pressure by cell /// @param[out] porosity porosity (at reservoir condition) From 913054c47369279b1d074d71f08757fa48ee9536 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Sep 2012 13:54:50 +0200 Subject: [PATCH 48/58] Added more checks in 3-phase init code. --- opm/core/utility/initState_impl.hpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/opm/core/utility/initState_impl.hpp b/opm/core/utility/initState_impl.hpp index f66704348..9a635e93f 100644 --- a/opm/core/utility/initState_impl.hpp +++ b/opm/core/utility/initState_impl.hpp @@ -512,11 +512,10 @@ namespace Opm State& state) { const int num_phases = props.numPhases(); - state.init(grid, num_phases); if (deck.hasField("EQUIL")) { if (num_phases != 2) { - THROW("initStateFromDeck(): currently handling only two-phase scenarios."); + THROW("initStateFromDeck(): EQUIL-based init currently handling only two-phase scenarios."); } // Set saturations depending on oil-water contact. const EQUIL& equil= deck.getEQUIL(); @@ -536,22 +535,27 @@ namespace Opm const std::vector& sw_deck = deck.getFloatingPointValue("SWAT"); const std::vector& p_deck = deck.getFloatingPointValue("PRESSURE"); const int num_cells = grid.number_of_cells; - if(num_phases == 2){ + if (num_phases == 2) { for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; s[2*c] = sw_deck[c_deck]; s[2*c + 1] = 1.0 - s[2*c]; p[c] = p_deck[c_deck]; } - }else{ + } else if (num_phases == 3) { + if (!deck.hasField("SGAS")) { + THROW("initStateFromDeck(): missing SGAS keyword in 3-phase init (only SWAT and PRESSURE found)."); + } const std::vector& sg_deck = deck.getFloatingPointValue("SGAS"); - for (int c = 0; c < num_cells; ++c) { + for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; s[2*c] = sw_deck[c_deck]; s[2*c + 1] = 1.0 - (sw_deck[c_deck] + sg_deck[c_deck]); s[2*c + 2] = sg_deck[c_deck]; p[c] = p_deck[c_deck]; } + } else { + THROW("initStateFromDeck(): init with SWAT etc. only available with 2 or 3 phases."); } } else { THROW("initStateFromDeck(): we must either have EQUIL, or both SWAT and PRESSURE."); From c2d41a6639c0f24663ccdf0c3a6ed38c92853d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Sep 2012 14:04:52 +0200 Subject: [PATCH 49/58] Whitespace cleanup and adding a check for #phases <= 3. --- opm/core/utility/miscUtilities.cpp | 340 ++++++++++++++--------------- 1 file changed, 170 insertions(+), 170 deletions(-) diff --git a/opm/core/utility/miscUtilities.cpp b/opm/core/utility/miscUtilities.cpp index 0b8d20103..e1658b83a 100644 --- a/opm/core/utility/miscUtilities.cpp +++ b/opm/core/utility/miscUtilities.cpp @@ -40,14 +40,14 @@ namespace Opm /// @param[out] porevol the pore volume by cell. void computePorevolume(const UnstructuredGrid& grid, const double* porosity, - std::vector& porevol) + std::vector& porevol) { - int num_cells = grid.number_of_cells; - porevol.resize(num_cells); - std::transform(porosity, porosity + num_cells, - grid.cell_volumes, - porevol.begin(), - std::multiplies()); + int num_cells = grid.number_of_cells; + porevol.resize(num_cells); + std::transform(porosity, porosity + num_cells, + grid.cell_volumes, + porevol.begin(), + std::multiplies()); } @@ -98,20 +98,20 @@ namespace Opm /// For each phase p, we compute /// sat_vol_p = sum_i s_p_i pv_i void computeSaturatedVol(const std::vector& pv, - const std::vector& s, - double* sat_vol) + const std::vector& s, + double* sat_vol) { - const int num_cells = pv.size(); - const int np = s.size()/pv.size(); - if (int(s.size()) != num_cells*np) { - THROW("Sizes of s and pv vectors do not match."); - } - std::fill(sat_vol, sat_vol + np, 0.0); - for (int c = 0; c < num_cells; ++c) { - for (int p = 0; p < np; ++p) { - sat_vol[p] += pv[c]*s[np*c + p]; - } - } + const int num_cells = pv.size(); + const int np = s.size()/pv.size(); + if (int(s.size()) != num_cells*np) { + THROW("Sizes of s and pv vectors do not match."); + } + std::fill(sat_vol, sat_vol + np, 0.0); + for (int c = 0; c < num_cells; ++c) { + for (int p = 0; p < np; ++p) { + sat_vol[p] += pv[c]*s[np*c + p]; + } + } } @@ -123,28 +123,28 @@ namespace Opm /// For each phase p, we compute /// aver_sat_p = (sum_i s_p_i pv_i) / (sum_i pv_i). void computeAverageSat(const std::vector& pv, - const std::vector& s, - double* aver_sat) + const std::vector& s, + double* aver_sat) { - const int num_cells = pv.size(); - const int np = s.size()/pv.size(); - if (int(s.size()) != num_cells*np) { - THROW("Sizes of s and pv vectors do not match."); - } - double tot_pv = 0.0; - // Note that we abuse the output array to accumulate the - // saturated pore volumes. - std::fill(aver_sat, aver_sat + np, 0.0); - for (int c = 0; c < num_cells; ++c) { - tot_pv += pv[c]; - for (int p = 0; p < np; ++p) { - aver_sat[p] += pv[c]*s[np*c + p]; - } - } - // Must divide by pore volumes to get saturations. - for (int p = 0; p < np; ++p) { - aver_sat[p] /= tot_pv; - } + const int num_cells = pv.size(); + const int np = s.size()/pv.size(); + if (int(s.size()) != num_cells*np) { + THROW("Sizes of s and pv vectors do not match."); + } + double tot_pv = 0.0; + // Note that we abuse the output array to accumulate the + // saturated pore volumes. + std::fill(aver_sat, aver_sat + np, 0.0); + for (int c = 0; c < num_cells; ++c) { + tot_pv += pv[c]; + for (int p = 0; p < np; ++p) { + aver_sat[p] += pv[c]*s[np*c + p]; + } + } + // Must divide by pore volumes to get saturations. + for (int p = 0; p < np; ++p) { + aver_sat[p] /= tot_pv; + } } @@ -161,38 +161,38 @@ namespace Opm /// where P = s.size()/src.size(). /// @param[out] produced must also point to a valid array with P elements. void computeInjectedProduced(const IncompPropertiesInterface& props, - const std::vector& s, - const std::vector& src, - const double dt, - double* injected, - double* produced) + const std::vector& s, + const std::vector& src, + const double dt, + double* injected, + double* produced) { - const int num_cells = src.size(); - const int np = s.size()/src.size(); - if (int(s.size()) != num_cells*np) { - THROW("Sizes of s and src vectors do not match."); - } - std::fill(injected, injected + np, 0.0); - std::fill(produced, produced + np, 0.0); - const double* visc = props.viscosity(); - std::vector mob(np); - for (int c = 0; c < num_cells; ++c) { - if (src[c] > 0.0) { - injected[0] += src[c]*dt; - } else if (src[c] < 0.0) { - const double flux = -src[c]*dt; - const double* sat = &s[np*c]; - props.relperm(1, sat, &c, &mob[0], 0); - double totmob = 0.0; - for (int p = 0; p < np; ++p) { - mob[p] /= visc[p]; - totmob += mob[p]; - } - for (int p = 0; p < np; ++p) { - produced[p] += (mob[p]/totmob)*flux; - } - } - } + const int num_cells = src.size(); + const int np = s.size()/src.size(); + if (int(s.size()) != num_cells*np) { + THROW("Sizes of s and src vectors do not match."); + } + std::fill(injected, injected + np, 0.0); + std::fill(produced, produced + np, 0.0); + const double* visc = props.viscosity(); + std::vector mob(np); + for (int c = 0; c < num_cells; ++c) { + if (src[c] > 0.0) { + injected[0] += src[c]*dt; + } else if (src[c] < 0.0) { + const double flux = -src[c]*dt; + const double* sat = &s[np*c]; + props.relperm(1, sat, &c, &mob[0], 0); + double totmob = 0.0; + for (int p = 0; p < np; ++p) { + mob[p] /= visc[p]; + totmob += mob[p]; + } + for (int p = 0; p < np; ++p) { + produced[p] += (mob[p]/totmob)*flux; + } + } + } } @@ -203,9 +203,9 @@ namespace Opm /// @param[in] s saturation values (for all phases) /// @param[out] totmob total mobilities. void computeTotalMobility(const Opm::IncompPropertiesInterface& props, - const std::vector& cells, - const std::vector& s, - std::vector& totmob) + const std::vector& cells, + const std::vector& s, + std::vector& totmob) { std::vector pmobc; @@ -231,10 +231,10 @@ namespace Opm /// @param[out] totmob total mobility /// @param[out] omega fractional-flow weighted fluid densities. void computeTotalMobilityOmega(const Opm::IncompPropertiesInterface& props, - const std::vector& cells, - const std::vector& s, - std::vector& totmob, - std::vector& omega) + const std::vector& cells, + const std::vector& s, + std::vector& totmob, + std::vector& omega) { std::vector pmobc; @@ -331,33 +331,33 @@ namespace Opm /// (+) positive inflow of first phase (water) /// (-) negative total outflow of both phases void computeTransportSource(const UnstructuredGrid& grid, - const std::vector& src, - const std::vector& faceflux, - const double inflow_frac, + const std::vector& src, + const std::vector& faceflux, + const double inflow_frac, const Wells* wells, const std::vector& well_perfrates, - std::vector& transport_src) + std::vector& transport_src) { - int nc = grid.number_of_cells; - transport_src.resize(nc); + int nc = grid.number_of_cells; + transport_src.resize(nc); // Source term and boundary contributions. - for (int c = 0; c < nc; ++c) { - transport_src[c] = 0.0; - transport_src[c] += src[c] > 0.0 ? inflow_frac*src[c] : src[c]; - for (int hf = grid.cell_facepos[c]; hf < grid.cell_facepos[c + 1]; ++hf) { - int f = grid.cell_faces[hf]; - const int* f2c = &grid.face_cells[2*f]; - double bdy_influx = 0.0; - if (f2c[0] == c && f2c[1] == -1) { - bdy_influx = -faceflux[f]; - } else if (f2c[0] == -1 && f2c[1] == c) { - bdy_influx = faceflux[f]; - } - if (bdy_influx != 0.0) { - transport_src[c] += bdy_influx > 0.0 ? inflow_frac*bdy_influx : bdy_influx; - } - } - } + for (int c = 0; c < nc; ++c) { + transport_src[c] = 0.0; + transport_src[c] += src[c] > 0.0 ? inflow_frac*src[c] : src[c]; + for (int hf = grid.cell_facepos[c]; hf < grid.cell_facepos[c + 1]; ++hf) { + int f = grid.cell_faces[hf]; + const int* f2c = &grid.face_cells[2*f]; + double bdy_influx = 0.0; + if (f2c[0] == c && f2c[1] == -1) { + bdy_influx = -faceflux[f]; + } else if (f2c[0] == -1 && f2c[1] == c) { + bdy_influx = faceflux[f]; + } + if (bdy_influx != 0.0) { + transport_src[c] += bdy_influx > 0.0 ? inflow_frac*bdy_influx : bdy_influx; + } + } + } // Well contributions. if (wells) { @@ -392,52 +392,52 @@ namespace Opm /// @param[in] face_flux signed per-face fluxes /// @param[out] cell_velocity the estimated velocities. void estimateCellVelocity(const UnstructuredGrid& grid, - const std::vector& face_flux, - std::vector& cell_velocity) + const std::vector& face_flux, + std::vector& cell_velocity) { - const int dim = grid.dimensions; - cell_velocity.clear(); - cell_velocity.resize(grid.number_of_cells*dim, 0.0); - for (int face = 0; face < grid.number_of_faces; ++face) { - int c[2] = { grid.face_cells[2*face], grid.face_cells[2*face + 1] }; - const double* fc = &grid.face_centroids[face*dim]; - double flux = face_flux[face]; - for (int i = 0; i < 2; ++i) { - if (c[i] >= 0) { - const double* cc = &grid.cell_centroids[c[i]*dim]; - for (int d = 0; d < dim; ++d) { - double v_contrib = fc[d] - cc[d]; - v_contrib *= flux/grid.cell_volumes[c[i]]; - cell_velocity[c[i]*dim + d] += (i == 0) ? v_contrib : -v_contrib; - } - } - } - } + const int dim = grid.dimensions; + cell_velocity.clear(); + cell_velocity.resize(grid.number_of_cells*dim, 0.0); + for (int face = 0; face < grid.number_of_faces; ++face) { + int c[2] = { grid.face_cells[2*face], grid.face_cells[2*face + 1] }; + const double* fc = &grid.face_centroids[face*dim]; + double flux = face_flux[face]; + for (int i = 0; i < 2; ++i) { + if (c[i] >= 0) { + const double* cc = &grid.cell_centroids[c[i]*dim]; + for (int d = 0; d < dim; ++d) { + double v_contrib = fc[d] - cc[d]; + v_contrib *= flux/grid.cell_volumes[c[i]]; + cell_velocity[c[i]*dim + d] += (i == 0) ? v_contrib : -v_contrib; + } + } + } + } } /// Extract a vector of water saturations from a vector of /// interleaved water and oil saturations. void toWaterSat(const std::vector& sboth, - std::vector& sw) + std::vector& sw) { - int num = sboth.size()/2; - sw.resize(num); - for (int i = 0; i < num; ++i) { - sw[i] = sboth[2*i]; - } + int num = sboth.size()/2; + sw.resize(num); + for (int i = 0; i < num; ++i) { + sw[i] = sboth[2*i]; + } } /// Make a a vector of interleaved water and oil saturations from /// a vector of water saturations. void toBothSat(const std::vector& sw, - std::vector& sboth) + std::vector& sboth) { - int num = sw.size(); - sboth.resize(2*num); - for (int i = 0; i < num; ++i) { - sboth[2*i] = sw[i]; - sboth[2*i + 1] = 1.0 - sw[i]; - } + int num = sw.size(); + sboth.resize(2*num); + for (int i = 0; i < num; ++i) { + sboth[2*i] = sw[i]; + sboth[2*i + 1] = 1.0 - sw[i]; + } } @@ -450,30 +450,30 @@ namespace Opm if (np != 2) { THROW("wellsToSrc() requires a 2 phase case."); } - src.resize(num_cells); - for (int w = 0; w < wells.number_of_wells; ++w) { + src.resize(num_cells); + for (int w = 0; w < wells.number_of_wells; ++w) { const int cur = wells.ctrls[w]->current; - if (wells.ctrls[w]->num != 1) { - MESSAGE("In wellsToSrc(): well has more than one control, all but current control will be ignored."); - } - if (wells.ctrls[w]->type[cur] != RESERVOIR_RATE) { - THROW("In wellsToSrc(): well is something other than RESERVOIR_RATE."); - } - if (wells.well_connpos[w+1] - wells.well_connpos[w] != 1) { - THROW("In wellsToSrc(): well has multiple perforations."); - } + if (wells.ctrls[w]->num != 1) { + MESSAGE("In wellsToSrc(): well has more than one control, all but current control will be ignored."); + } + if (wells.ctrls[w]->type[cur] != RESERVOIR_RATE) { + THROW("In wellsToSrc(): well is something other than RESERVOIR_RATE."); + } + if (wells.well_connpos[w+1] - wells.well_connpos[w] != 1) { + THROW("In wellsToSrc(): well has multiple perforations."); + } for (int p = 0; p < np; ++p) { if (wells.ctrls[w]->distr[np*cur + p] != 1.0) { THROW("In wellsToSrc(): well not controlled on total rate."); } } - double flow = wells.ctrls[w]->target[cur]; + double flow = wells.ctrls[w]->target[cur]; if (wells.type[w] == INJECTOR) { flow *= wells.comp_frac[np*w + 0]; // Obtaining water rate for inflow source. } - const double cell = wells.well_cells[wells.well_connpos[w]]; - src[cell] = flow; - } + const double cell = wells.well_cells[wells.well_connpos[w]]; + src[cell] = flow; + } } @@ -594,9 +594,10 @@ namespace Opm int nw = well_bhp.size(); ASSERT(nw == wells.number_of_wells); int np = props.numPhases(); - //if (props.numPhases() != 2) { - // THROW("WellReport for now assumes two phase flow."); - //} + const int max_np = 3; + if (np > max_np) { + THROW("WellReport for now assumes #phases <= " << max_np); + } const double* visc = props.viscosity(); std::vector data_now; data_now.reserve(1 + 3*nw); @@ -606,8 +607,8 @@ namespace Opm double well_rate_total = 0.0; double well_rate_water = 0.0; for (int perf = wells.well_connpos[w]; perf < wells.well_connpos[w + 1]; ++perf) { - const double perf_rate = unit::convert::to(well_perfrates[perf], - unit::cubic(unit::meter)/unit::day); + const double perf_rate = unit::convert::to(well_perfrates[perf], + unit::cubic(unit::meter)/unit::day); well_rate_total += perf_rate; if (perf_rate > 0.0) { // Injection. @@ -615,13 +616,13 @@ namespace Opm } else { // Production. const int cell = wells.well_cells[perf]; - double mob[np]; + double mob[max_np]; props.relperm(1, &saturation[2*cell], &cell, mob, 0); - double tmob=0; - for(int i=0; i < np; ++i){ + double tmob = 0; + for(int i = 0; i < np; ++i) { mob[i] /= visc[i]; tmob += mob[i]; - } + } const double fracflow = mob[0]/tmob; well_rate_water += perf_rate*fracflow; } @@ -652,9 +653,10 @@ namespace Opm int nw = well_bhp.size(); ASSERT(nw == wells.number_of_wells); int np = props.numPhases(); - //if (props.numPhases() != 2) { - // THROW("WellReport for now assumes two phase flow."); - //} + const int max_np = 3; + if (np > max_np) { + THROW("WellReport for now assumes #phases <= " << max_np); + } std::vector data_now; data_now.reserve(1 + 3*nw); data_now.push_back(time/unit::day); @@ -665,25 +667,23 @@ namespace Opm for (int perf = wells.well_connpos[w]; perf < wells.well_connpos[w + 1]; ++perf) { const double perf_rate = well_perfrates[perf]*(unit::day/unit::second); well_rate_total += perf_rate; - if (perf_rate > 0.0) { + if (perf_rate > 0.0) { // Injection. well_rate_water += perf_rate*wells.comp_frac[0]; } else { // Production. const int cell = wells.well_cells[perf]; - double mob[np]; + double mob[max_np]; props.relperm(1, &s[2*cell], &cell, mob, 0); - double visc[np]; + double visc[max_np]; props.viscosity(1, &p[cell], &z[2*cell], &cell, visc, 0); - double tmob=0; - for(int i=0; i < np; ++i){ + double tmob = 0; + for(int i = 0; i < np; ++i) { mob[i] /= visc[i]; tmob += mob[i]; - } + } const double fracflow = mob[0]/(tmob); well_rate_water += perf_rate*fracflow; - //const double fracflow = mob[0]/(tmob); - //well_rate_water += perf_rate*fracflow; } } data_now.push_back(well_rate_total); From 489501b49b3669548a3e6657e51de156692f87a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Sep 2012 14:16:54 +0200 Subject: [PATCH 50/58] Documented new constructor. Fixed layout. --- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index 1d0a0d380..e6b9c5b41 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -45,9 +45,18 @@ namespace Opm /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, const UnstructuredGrid& grid); + + /// Initialize from deck, grid and parameters. + /// \param deck Deck input parser + /// \param grid Grid to which property object applies, needed for the + /// mapping from cell indices (typically from a processed grid) + /// to logical cartesian indices consistent with the deck. + /// \param param Parameters. Accepted parameters include: + /// tab_size (200) number of uniform sample points for saturation tables. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, const UnstructuredGrid& grid, const parameter::ParameterGroup& param); + /// Destructor. virtual ~BlackoilPropertiesFromDeck(); From 4e1647bb6272fa98ba57936d6761b8b39578f90b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Sep 2012 15:07:03 +0200 Subject: [PATCH 51/58] Formatting fixes. --- opm/core/fluid/blackoil/BlackoilPvtProperties.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp index 99fd5b8f4..191c6fa89 100644 --- a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp +++ b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp @@ -47,7 +47,7 @@ namespace Opm BlackoilPvtProperties(); /// Initialize from deck. - void init(const EclipseGridParser& deck,const int samples = 16); + void init(const EclipseGridParser& deck, const int samples = 16); /// Number of active phases. int numPhases() const; From e9c4c2499cc362facef490fae23178c2b72fe6b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 3 Sep 2012 15:09:55 +0200 Subject: [PATCH 52/58] Documented parameters. --- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index e6b9c5b41..b63c0af88 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -52,7 +52,8 @@ namespace Opm /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. /// \param param Parameters. Accepted parameters include: - /// tab_size (200) number of uniform sample points for saturation tables. + /// dead_tab_size (1025) number of uniform sample points for dead-oil pvt tables. + /// tab_size_kr (200) number of uniform sample points for saturation tables. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, const UnstructuredGrid& grid, const parameter::ParameterGroup& param); From 0101e1f575b0ce50222a5b1d61bcb84d875d4196 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Sep 2012 11:49:05 +0200 Subject: [PATCH 53/58] Updated doc to match new parameter names. New parameters are (default): pvt_tab_size (200) sat_tab_size (200) threephase_model ("simple") [also accepts "stone2"]. --- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index 97a29d0af..80a8d8192 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -53,8 +53,9 @@ namespace Opm /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. /// \param[in] param Parameters. Accepted parameters include: - /// dead_tab_size (1025) number of uniform sample points for dead-oil pvt tables. - /// tab_size_kr (200) number of uniform sample points for saturation tables. + /// pvt_tab_size (200) number of uniform sample points for dead-oil pvt tables. + /// sat_tab_size (200) number of uniform sample points for saturation tables. + /// threephase_model("simple") three-phase relperm model (accepts "simple" and "stone2"). /// For both parameters, a 0 or negative value indicates that no spline fitting is to /// be done, and the input fluid data used directly for linear interpolation. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, From 7c7609698f617a4ce640720f6cb09421365474ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Sep 2012 12:52:17 +0200 Subject: [PATCH 54/58] Added proper Doxygen tags. --- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index b63c0af88..13f5799d8 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -39,19 +39,19 @@ namespace Opm { public: /// Initialize from deck and grid. - /// \param deck Deck input parser - /// \param grid Grid to which property object applies, needed for the + /// \param[in] deck Deck input parser + /// \param[in] grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, const UnstructuredGrid& grid); /// Initialize from deck, grid and parameters. - /// \param deck Deck input parser - /// \param grid Grid to which property object applies, needed for the + /// \param[in] deck Deck input parser + /// \param[in] grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. - /// \param param Parameters. Accepted parameters include: + /// \param[in] param Parameters. Accepted parameters include: /// dead_tab_size (1025) number of uniform sample points for dead-oil pvt tables. /// tab_size_kr (200) number of uniform sample points for saturation tables. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, From 14aab769f2f9d90875d2568596a2924b0eb421bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Sep 2012 13:06:13 +0200 Subject: [PATCH 55/58] Fix stride bug in SGAS/SWAT init. --- opm/core/utility/initState_impl.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/opm/core/utility/initState_impl.hpp b/opm/core/utility/initState_impl.hpp index 9a635e93f..7d01ade0e 100644 --- a/opm/core/utility/initState_impl.hpp +++ b/opm/core/utility/initState_impl.hpp @@ -549,9 +549,9 @@ namespace Opm const std::vector& sg_deck = deck.getFloatingPointValue("SGAS"); for (int c = 0; c < num_cells; ++c) { int c_deck = (grid.global_cell == NULL) ? c : grid.global_cell[c]; - s[2*c] = sw_deck[c_deck]; - s[2*c + 1] = 1.0 - (sw_deck[c_deck] + sg_deck[c_deck]); - s[2*c + 2] = sg_deck[c_deck]; + s[3*c] = sw_deck[c_deck]; + s[3*c + 1] = 1.0 - (sw_deck[c_deck] + sg_deck[c_deck]); + s[3*c + 2] = sg_deck[c_deck]; p[c] = p_deck[c_deck]; } } else { From 0f9d572f9a4a148c4feb1cb38731faf27a7c0b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Sep 2012 13:12:06 +0200 Subject: [PATCH 56/58] Fix stride bug in WellReport::push(). Use convert::to(). --- opm/core/utility/miscUtilities.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/opm/core/utility/miscUtilities.cpp b/opm/core/utility/miscUtilities.cpp index e1658b83a..aeafbfca7 100644 --- a/opm/core/utility/miscUtilities.cpp +++ b/opm/core/utility/miscUtilities.cpp @@ -665,7 +665,8 @@ namespace Opm double well_rate_total = 0.0; double well_rate_water = 0.0; for (int perf = wells.well_connpos[w]; perf < wells.well_connpos[w + 1]; ++perf) { - const double perf_rate = well_perfrates[perf]*(unit::day/unit::second); + const double perf_rate = unit::convert::to(well_perfrates[perf], + unit::cubic(unit::meter)/unit::day); well_rate_total += perf_rate; if (perf_rate > 0.0) { // Injection. @@ -674,9 +675,9 @@ namespace Opm // Production. const int cell = wells.well_cells[perf]; double mob[max_np]; - props.relperm(1, &s[2*cell], &cell, mob, 0); + props.relperm(1, &s[np*cell], &cell, mob, 0); double visc[max_np]; - props.viscosity(1, &p[cell], &z[2*cell], &cell, visc, 0); + props.viscosity(1, &p[cell], &z[np*cell], &cell, visc, 0); double tmob = 0; for(int i = 0; i < np; ++i) { mob[i] /= visc[i]; From 23ae62f8dc6339eff646cdb1e85f12ac9c76be72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 4 Sep 2012 13:15:26 +0200 Subject: [PATCH 57/58] Constified some local variables. --- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index 67943fc76..5c834fe8c 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -39,7 +39,7 @@ namespace Opm const parameter::ParameterGroup& param) { rock_.init(deck, grid); - int samples = param.getDefault("dead_tab_size", 1025); + const int samples = param.getDefault("dead_tab_size", 1025); pvt_.init(deck, samples); satprops_.init(deck, grid, param); From 0f91bc6a349a83fdcd3966e8a03eb62950f54085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Wed, 5 Sep 2012 11:28:54 +0200 Subject: [PATCH 58/58] Massive whitespace cleanup: entire fluid subdir. --- opm/core/fluid/BlackoilPropertiesBasic.cpp | 72 +++---- opm/core/fluid/BlackoilPropertiesBasic.hpp | 20 +- opm/core/fluid/BlackoilPropertiesFromDeck.cpp | 10 +- opm/core/fluid/BlackoilPropertiesFromDeck.hpp | 12 +- .../fluid/BlackoilPropertiesInterface.hpp | 6 +- opm/core/fluid/IncompPropertiesBasic.cpp | 70 +++--- opm/core/fluid/IncompPropertiesBasic.hpp | 34 +-- opm/core/fluid/IncompPropertiesFromDeck.cpp | 42 ++-- opm/core/fluid/IncompPropertiesFromDeck.hpp | 14 +- opm/core/fluid/IncompPropertiesInterface.hpp | 6 +- opm/core/fluid/PvtPropertiesBasic.cpp | 112 +++++----- opm/core/fluid/PvtPropertiesBasic.hpp | 18 +- .../fluid/PvtPropertiesIncompFromDeck.cpp | 70 +++--- .../fluid/PvtPropertiesIncompFromDeck.hpp | 12 +- opm/core/fluid/RockBasic.hpp | 8 +- opm/core/fluid/RockCompressibility.cpp | 6 +- opm/core/fluid/RockFromDeck.cpp | 2 +- opm/core/fluid/RockFromDeck.hpp | 2 +- opm/core/fluid/SaturationPropsBasic.cpp | 204 +++++++++--------- opm/core/fluid/SaturationPropsBasic.hpp | 22 +- opm/core/fluid/SaturationPropsFromDeck.hpp | 10 +- .../fluid/SaturationPropsFromDeck_impl.hpp | 20 +- opm/core/fluid/SaturationPropsInterface.hpp | 4 +- .../fluid/blackoil/BlackoilPvtProperties.hpp | 6 +- 24 files changed, 391 insertions(+), 391 deletions(-) diff --git a/opm/core/fluid/BlackoilPropertiesBasic.cpp b/opm/core/fluid/BlackoilPropertiesBasic.cpp index be8211c15..2496d98ef 100644 --- a/opm/core/fluid/BlackoilPropertiesBasic.cpp +++ b/opm/core/fluid/BlackoilPropertiesBasic.cpp @@ -26,20 +26,20 @@ namespace Opm { BlackoilPropertiesBasic::BlackoilPropertiesBasic(const parameter::ParameterGroup& param, - const int dim, - const int num_cells) + const int dim, + const int num_cells) { - double poro = param.getDefault("porosity", 1.0); - using namespace Opm::unit; - using namespace Opm::prefix; - double perm = param.getDefault("permeability", 100.0)*milli*darcy; + double poro = param.getDefault("porosity", 1.0); + using namespace Opm::unit; + using namespace Opm::prefix; + double perm = param.getDefault("permeability", 100.0)*milli*darcy; rock_.init(dim, num_cells, poro, perm); - pvt_.init(param); + pvt_.init(param); satprops_.init(param); - if (pvt_.numPhases() != satprops_.numPhases()) { - THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); - } + if (pvt_.numPhases() != satprops_.numPhases()) { + THROW("BlackoilPropertiesBasic::BlackoilPropertiesBasic() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + } } BlackoilPropertiesBasic::~BlackoilPropertiesBasic() @@ -90,11 +90,11 @@ namespace Opm /// \param[out] dmudp If non-null: array of nP viscosity derivative values, /// array must be valid before calling. void BlackoilPropertiesBasic::viscosity(const int n, - const double* p, - const double* z, - const int* /*cells*/, - double* mu, - double* dmudp) const + const double* p, + const double* z, + const int* /*cells*/, + double* mu, + double* dmudp) const { if (dmudp) { THROW("BlackoilPropertiesBasic::viscosity() -- derivatives of viscosity not yet implemented."); @@ -114,16 +114,16 @@ namespace Opm /// array must be valid before calling. The matrices are output /// in Fortran order. void BlackoilPropertiesBasic::matrix(const int n, - const double* /*p*/, - const double* /*z*/, - const int* /*cells*/, - double* A, - double* dAdp) const + const double* /*p*/, + const double* /*z*/, + const int* /*cells*/, + double* A, + double* dAdp) const { - const int np = numPhases(); - ASSERT(np <= 2); - double B[2]; // Must be enough since component classes do not handle more than 2. - pvt_.B(1, 0, 0, B); + const int np = numPhases(); + ASSERT(np <= 2); + double B[2]; // Must be enough since component classes do not handle more than 2. + pvt_.B(1, 0, 0, B); // Compute A matrix // #pragma omp parallel for for (int i = 0; i < n; ++i) { @@ -152,8 +152,8 @@ namespace Opm /// of a call to the method matrix(). /// \param[out] rho Array of nP density values, array must be valid before calling. void BlackoilPropertiesBasic::density(const int n, - const double* A, - double* rho) const + const double* A, + double* rho) const { const int np = numPhases(); const double* sdens = pvt_.surfaceDensities(); @@ -186,10 +186,10 @@ namespace Opm /// m_{ij} = \frac{dkr_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) void BlackoilPropertiesBasic::relperm(const int n, - const double* s, - const int* /*cells*/, - double* kr, - double* dkrds) const + const double* s, + const int* /*cells*/, + double* kr, + double* dkrds) const { satprops_.relperm(n, s, kr, dkrds); } @@ -205,10 +205,10 @@ namespace Opm /// m_{ij} = \frac{dpc_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) void BlackoilPropertiesBasic::capPress(const int n, - const double* s, - const int* /*cells*/, - double* pc, - double* dpcds) const + const double* s, + const int* /*cells*/, + double* pc, + double* dpcds) const { satprops_.capPress(n, s, pc, dpcds); } @@ -226,7 +226,7 @@ namespace Opm double* smin, double* smax) const { - satprops_.satRange(n, smin, smax); + satprops_.satRange(n, smin, smax); } diff --git a/opm/core/fluid/BlackoilPropertiesBasic.hpp b/opm/core/fluid/BlackoilPropertiesBasic.hpp index d879036ef..44a76013b 100644 --- a/opm/core/fluid/BlackoilPropertiesBasic.hpp +++ b/opm/core/fluid/BlackoilPropertiesBasic.hpp @@ -35,16 +35,16 @@ namespace Opm { public: /// Construct from parameters. - /// The following parameters are accepted (defaults): - /// num_phases (2) Must be 1 or 2. - /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". - /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 - /// mu1 [mu2, mu3] (1.0) Viscosity in cP - /// porosity (1.0) Porosity - /// permeability (100.0) Permeability in mD + /// The following parameters are accepted (defaults): + /// num_phases (2) Must be 1 or 2. + /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". + /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 + /// mu1 [mu2, mu3] (1.0) Viscosity in cP + /// porosity (1.0) Porosity + /// permeability (100.0) Permeability in mD BlackoilPropertiesBasic(const parameter::ParameterGroup& param, - const int dim, - const int num_cells); + const int dim, + const int num_cells); /// Destructor. virtual ~BlackoilPropertiesBasic(); @@ -151,7 +151,7 @@ namespace Opm double* dpcds) const; - /// Obtain the range of allowable saturation values. +/// Obtain the range of allowable saturation values. /// In cell cells[i], saturation of phase p is allowed to be /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp index 7cdae4ae2..e2457f39b 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.cpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.cpp @@ -33,10 +33,10 @@ namespace Opm satprops_.reset(ptr); ptr->init(deck, grid, 200); - if (pvt_.numPhases() != satprops_->numPhases()) { - THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ")."); - } + if (pvt_.numPhases() != satprops_->numPhases()) { + THROW("BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_->numPhases() << ")."); + } } BlackoilPropertiesFromDeck::BlackoilPropertiesFromDeck(const EclipseGridParser& deck, @@ -319,7 +319,7 @@ namespace Opm double* smin, double* smax) const { - satprops_->satRange(n, cells, smin, smax); + satprops_->satRange(n, cells, smin, smax); } diff --git a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp index aceb534b8..eb8b947b4 100644 --- a/opm/core/fluid/BlackoilPropertiesFromDeck.hpp +++ b/opm/core/fluid/BlackoilPropertiesFromDeck.hpp @@ -41,15 +41,15 @@ namespace Opm public: /// Initialize from deck and grid. /// \param[in] deck Deck input parser - /// \param[in] grid Grid to which property object applies, needed for the + /// \param[in] grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. BlackoilPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid); + const UnstructuredGrid& grid); /// Initialize from deck, grid and parameters. /// \param[in] deck Deck input parser - /// \param[in] grid Grid to which property object applies, needed for the + /// \param[in] grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. /// \param[in] param Parameters. Accepted parameters include: @@ -167,9 +167,9 @@ namespace Opm double* dpcds) const; - /// Obtain the range of allowable saturation values. - /// In cell cells[i], saturation of phase p is allowed to be - /// in the interval [smin[i*P + p], smax[i*P + p]]. + /// Obtain the range of allowable saturation values. + /// In cell cells[i], saturation of phase p is allowed to be + /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. /// \param[in] cells Array of n cell indices. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. diff --git a/opm/core/fluid/BlackoilPropertiesInterface.hpp b/opm/core/fluid/BlackoilPropertiesInterface.hpp index dd8a857fb..501c8a406 100644 --- a/opm/core/fluid/BlackoilPropertiesInterface.hpp +++ b/opm/core/fluid/BlackoilPropertiesInterface.hpp @@ -138,9 +138,9 @@ namespace Opm double* dpcds) const = 0; - /// Obtain the range of allowable saturation values. - /// In cell cells[i], saturation of phase p is allowed to be - /// in the interval [smin[i*P + p], smax[i*P + p]]. + /// Obtain the range of allowable saturation values. + /// In cell cells[i], saturation of phase p is allowed to be + /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. /// \param[in] cells Array of n cell indices. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. diff --git a/opm/core/fluid/IncompPropertiesBasic.cpp b/opm/core/fluid/IncompPropertiesBasic.cpp index 0ce3c88aa..ab68017c1 100644 --- a/opm/core/fluid/IncompPropertiesBasic.cpp +++ b/opm/core/fluid/IncompPropertiesBasic.cpp @@ -28,22 +28,22 @@ namespace Opm { IncompPropertiesBasic::IncompPropertiesBasic(const parameter::ParameterGroup& param, - const int dim, - const int num_cells) + const int dim, + const int num_cells) { - double poro = param.getDefault("porosity", 1.0); - using namespace Opm::unit; - using namespace Opm::prefix; - double perm = param.getDefault("permeability", 100.0)*milli*darcy; + double poro = param.getDefault("porosity", 1.0); + using namespace Opm::unit; + using namespace Opm::prefix; + double perm = param.getDefault("permeability", 100.0)*milli*darcy; rock_.init(dim, num_cells, poro, perm); - pvt_.init(param); + pvt_.init(param); satprops_.init(param); - if (pvt_.numPhases() != satprops_.numPhases()) { - THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); - } - viscosity_.resize(pvt_.numPhases()); - pvt_.mu(1, 0, 0, &viscosity_[0]); + if (pvt_.numPhases() != satprops_.numPhases()) { + THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + } + viscosity_.resize(pvt_.numPhases()); + pvt_.mu(1, 0, 0, &viscosity_[0]); } IncompPropertiesBasic::IncompPropertiesBasic(const int num_phases, @@ -56,14 +56,14 @@ namespace Opm const int num_cells) { rock_.init(dim, num_cells, por, perm); - pvt_.init(num_phases, rho, mu); + pvt_.init(num_phases, rho, mu); satprops_.init(num_phases, relpermfunc); - if (pvt_.numPhases() != satprops_.numPhases()) { - THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); - } - viscosity_.resize(pvt_.numPhases()); - pvt_.mu(1, 0, 0, &viscosity_[0]); + if (pvt_.numPhases() != satprops_.numPhases()) { + THROW("IncompPropertiesBasic::IncompPropertiesBasic() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + } + viscosity_.resize(pvt_.numPhases()); + pvt_.mu(1, 0, 0, &viscosity_[0]); } IncompPropertiesBasic::~IncompPropertiesBasic() @@ -109,7 +109,7 @@ namespace Opm /// \return Array of P viscosity values. const double* IncompPropertiesBasic::viscosity() const { - return &viscosity_[0]; + return &viscosity_[0]; } /// \return Array of P density values. @@ -117,7 +117,7 @@ namespace Opm { // No difference between reservoir and surface densities // modelled by this class. - return pvt_.surfaceDensities(); + return pvt_.surfaceDensities(); } /// \return Array of P density values. @@ -125,7 +125,7 @@ namespace Opm { // No difference between reservoir and surface densities // modelled by this class. - return pvt_.surfaceDensities(); + return pvt_.surfaceDensities(); } /// \param[in] n Number of data points. @@ -138,10 +138,10 @@ namespace Opm /// m_{ij} = \frac{dkr_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m_01 ...) void IncompPropertiesBasic::relperm(const int n, - const double* s, - const int* /*cells*/, - double* kr, - double* dkrds) const + const double* s, + const int* /*cells*/, + double* kr, + double* dkrds) const { satprops_.relperm(n, s, kr, dkrds); } @@ -157,10 +157,10 @@ namespace Opm /// m_{ij} = \frac{dpc_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m_01 ...) void IncompPropertiesBasic::capPress(const int n, - const double* s, - const int* /*cells*/, - double* pc, - double* dpcds) const + const double* s, + const int* /*cells*/, + double* pc, + double* dpcds) const { satprops_.capPress(n, s, pc, dpcds); } @@ -174,11 +174,11 @@ namespace Opm /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. void IncompPropertiesBasic::satRange(const int n, - const int* /*cells*/, - double* smin, - double* smax) const + const int* /*cells*/, + double* smin, + double* smax) const { - satprops_.satRange(n, smin, smax); + satprops_.satRange(n, smin, smax); } } // namespace Opm diff --git a/opm/core/fluid/IncompPropertiesBasic.hpp b/opm/core/fluid/IncompPropertiesBasic.hpp index b90b0876f..72c39b1b0 100644 --- a/opm/core/fluid/IncompPropertiesBasic.hpp +++ b/opm/core/fluid/IncompPropertiesBasic.hpp @@ -42,29 +42,29 @@ namespace Opm { public: /// Construct from parameters. - /// The following parameters are accepted (defaults): - /// num_phases (2) Must be 1 or 2. - /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". - /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 - /// mu1 [mu2, mu3] (1.0) Viscosity in cP - /// porosity (1.0) Porosity - /// permeability (100.0) Permeability in mD + /// The following parameters are accepted (defaults): + /// num_phases (2) Must be 1 or 2. + /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". + /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 + /// mu1 [mu2, mu3] (1.0) Viscosity in cP + /// porosity (1.0) Porosity + /// permeability (100.0) Permeability in mD IncompPropertiesBasic(const parameter::ParameterGroup& param, - const int dim, - const int num_cells); + const int dim, + const int num_cells); /// Construct from arguments a basic two phase fluid. IncompPropertiesBasic(const int num_phases, const SaturationPropsBasic::RelPermFunc& relpermfunc, const std::vector& rho, - const std::vector& mu, + const std::vector& mu, const double porosity, const double permeability, const int dim, - const int num_cells); + const int num_cells); - /// Destructor. + /// Destructor. virtual ~IncompPropertiesBasic(); // ---- Rock interface ---- @@ -132,9 +132,9 @@ namespace Opm double* dpcds) const; - /// Obtain the range of allowable saturation values. - /// In cell cells[i], saturation of phase p is allowed to be - /// in the interval [smin[i*P + p], smax[i*P + p]]. + /// Obtain the range of allowable saturation values. + /// In cell cells[i], saturation of phase p is allowed to be + /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. /// \param[in] cells Array of n cell indices. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. @@ -145,9 +145,9 @@ namespace Opm double* smax) const; private: RockBasic rock_; - PvtPropertiesBasic pvt_; + PvtPropertiesBasic pvt_; SaturationPropsBasic satprops_; - std::vector viscosity_; + std::vector viscosity_; }; diff --git a/opm/core/fluid/IncompPropertiesFromDeck.cpp b/opm/core/fluid/IncompPropertiesFromDeck.cpp index 45e49791f..9aa690980 100644 --- a/opm/core/fluid/IncompPropertiesFromDeck.cpp +++ b/opm/core/fluid/IncompPropertiesFromDeck.cpp @@ -27,15 +27,15 @@ namespace Opm { IncompPropertiesFromDeck::IncompPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid) + const UnstructuredGrid& grid) { rock_.init(deck, grid); - pvt_.init(deck); + pvt_.init(deck); satprops_.init(deck, grid, 200); - if (pvt_.numPhases() != satprops_.numPhases()) { - THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data (" - << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); - } + if (pvt_.numPhases() != satprops_.numPhases()) { + THROW("IncompPropertiesFromDeck::IncompPropertiesFromDeck() - Inconsistent number of phases in pvt data (" + << pvt_.numPhases() << ") and saturation-dependent function data (" << satprops_.numPhases() << ")."); + } } IncompPropertiesFromDeck::~IncompPropertiesFromDeck() @@ -81,19 +81,19 @@ namespace Opm /// \return Array of P viscosity values. const double* IncompPropertiesFromDeck::viscosity() const { - return pvt_.viscosity(); + return pvt_.viscosity(); } /// \return Array of P density values. const double* IncompPropertiesFromDeck::density() const { - return pvt_.reservoirDensities(); + return pvt_.reservoirDensities(); } /// \return Array of P density values. const double* IncompPropertiesFromDeck::surfaceDensity() const { - return pvt_.surfaceDensities(); + return pvt_.surfaceDensities(); } /// \param[in] n Number of data points. @@ -106,10 +106,10 @@ namespace Opm /// m_{ij} = \frac{dkr_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m_01 ...) void IncompPropertiesFromDeck::relperm(const int n, - const double* s, - const int* cells, - double* kr, - double* dkrds) const + const double* s, + const int* cells, + double* kr, + double* dkrds) const { satprops_.relperm(n, s, cells, kr, dkrds); } @@ -125,10 +125,10 @@ namespace Opm /// m_{ij} = \frac{dpc_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m_01 ...) void IncompPropertiesFromDeck::capPress(const int n, - const double* s, - const int* cells, - double* pc, - double* dpcds) const + const double* s, + const int* cells, + double* pc, + double* dpcds) const { satprops_.capPress(n, s, cells, pc, dpcds); } @@ -142,11 +142,11 @@ namespace Opm /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. void IncompPropertiesFromDeck::satRange(const int n, - const int* cells, - double* smin, - double* smax) const + const int* cells, + double* smin, + double* smax) const { - satprops_.satRange(n, cells, smin, smax); + satprops_.satRange(n, cells, smin, smax); } } // namespace Opm diff --git a/opm/core/fluid/IncompPropertiesFromDeck.hpp b/opm/core/fluid/IncompPropertiesFromDeck.hpp index 8f917d3b9..6680eaa49 100644 --- a/opm/core/fluid/IncompPropertiesFromDeck.hpp +++ b/opm/core/fluid/IncompPropertiesFromDeck.hpp @@ -47,13 +47,13 @@ namespace Opm public: /// Initialize from deck and grid. /// \param deck Deck input parser - /// \param grid Grid to which property object applies, needed for the + /// \param grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. IncompPropertiesFromDeck(const EclipseGridParser& deck, - const UnstructuredGrid& grid); + const UnstructuredGrid& grid); - /// Destructor. + /// Destructor. virtual ~IncompPropertiesFromDeck(); // ---- Rock interface ---- @@ -121,9 +121,9 @@ namespace Opm double* dpcds) const; - /// Obtain the range of allowable saturation values. - /// In cell cells[i], saturation of phase p is allowed to be - /// in the interval [smin[i*P + p], smax[i*P + p]]. + /// Obtain the range of allowable saturation values. + /// In cell cells[i], saturation of phase p is allowed to be + /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. /// \param[in] cells Array of n cell indices. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. @@ -134,7 +134,7 @@ namespace Opm double* smax) const; private: RockFromDeck rock_; - PvtPropertiesIncompFromDeck pvt_; + PvtPropertiesIncompFromDeck pvt_; SaturationPropsFromDeck satprops_; }; diff --git a/opm/core/fluid/IncompPropertiesInterface.hpp b/opm/core/fluid/IncompPropertiesInterface.hpp index a5025e8a1..4f8bfb516 100644 --- a/opm/core/fluid/IncompPropertiesInterface.hpp +++ b/opm/core/fluid/IncompPropertiesInterface.hpp @@ -109,9 +109,9 @@ namespace Opm double* pc, double* dpcds) const = 0; - /// Obtain the range of allowable saturation values. - /// In cell cells[i], saturation of phase p is allowed to be - /// in the interval [smin[i*P + p], smax[i*P + p]]. + /// Obtain the range of allowable saturation values. + /// In cell cells[i], saturation of phase p is allowed to be + /// in the interval [smin[i*P + p], smax[i*P + p]]. /// \param[in] n Number of data points. /// \param[in] cells Array of n cell indices. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. diff --git a/opm/core/fluid/PvtPropertiesBasic.cpp b/opm/core/fluid/PvtPropertiesBasic.cpp index 3d7d7bb2d..5220502ad 100644 --- a/opm/core/fluid/PvtPropertiesBasic.cpp +++ b/opm/core/fluid/PvtPropertiesBasic.cpp @@ -34,41 +34,41 @@ namespace Opm void PvtPropertiesBasic::init(const parameter::ParameterGroup& param) { - int num_phases = param.getDefault("num_phases", 2); - if (num_phases > 3 || num_phases < 1) { - THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases); - } - density_.resize(num_phases); - viscosity_.resize(num_phases); - // We currently do not allow the user to set B. - formation_volume_factor_.clear(); - formation_volume_factor_.resize(num_phases, 1.0); + int num_phases = param.getDefault("num_phases", 2); + if (num_phases > 3 || num_phases < 1) { + THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases); + } + density_.resize(num_phases); + viscosity_.resize(num_phases); + // We currently do not allow the user to set B. + formation_volume_factor_.clear(); + formation_volume_factor_.resize(num_phases, 1.0); - // Setting mu and rho from parameters - using namespace Opm::prefix; - using namespace Opm::unit; - const double kgpm3 = kilogram/cubic(meter); - const double cP = centi*Poise; - std::string rname[3] = { "rho1", "rho2", "rho3" }; - double rdefault[3] = { 1.0e3, 1.0e3, 1.0e3 }; - std::string vname[3] = { "mu1", "mu2", "mu3" }; - double vdefault[3] = { 1.0, 1.0, 1.0 }; - for (int phase = 0; phase < num_phases; ++phase) { - density_[phase] = kgpm3*param.getDefault(rname[phase], rdefault[phase]); - viscosity_[phase] = cP*param.getDefault(vname[phase], vdefault[phase]); - } + // Setting mu and rho from parameters + using namespace Opm::prefix; + using namespace Opm::unit; + const double kgpm3 = kilogram/cubic(meter); + const double cP = centi*Poise; + std::string rname[3] = { "rho1", "rho2", "rho3" }; + double rdefault[3] = { 1.0e3, 1.0e3, 1.0e3 }; + std::string vname[3] = { "mu1", "mu2", "mu3" }; + double vdefault[3] = { 1.0, 1.0, 1.0 }; + for (int phase = 0; phase < num_phases; ++phase) { + density_[phase] = kgpm3*param.getDefault(rname[phase], rdefault[phase]); + viscosity_[phase] = cP*param.getDefault(vname[phase], vdefault[phase]); + } } void PvtPropertiesBasic::init(const int num_phases, const std::vector& rho, const std::vector& visc) { - if (num_phases > 3 || num_phases < 1) { - THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases); - } - // We currently do not allow the user to set B. - formation_volume_factor_.clear(); - formation_volume_factor_.resize(num_phases, 1.0); + if (num_phases > 3 || num_phases < 1) { + THROW("PvtPropertiesBasic::init() illegal num_phases: " << num_phases); + } + // We currently do not allow the user to set B. + formation_volume_factor_.clear(); + formation_volume_factor_.resize(num_phases, 1.0); density_ = rho; viscosity_ = visc; } @@ -87,69 +87,69 @@ namespace Opm void PvtPropertiesBasic::mu(const int n, - const double* /*p*/, - const double* /*z*/, - double* output_mu) const + const double* /*p*/, + const double* /*z*/, + double* output_mu) const { - const int np = numPhases(); + const int np = numPhases(); for (int phase = 0; phase < np; ++phase) { // #pragma omp parallel for for (int i = 0; i < n; ++i) { output_mu[np*i + phase] = viscosity_[phase]; } - } + } } void PvtPropertiesBasic::B(const int n, - const double* /*p*/, - const double* /*z*/, - double* output_B) const + const double* /*p*/, + const double* /*z*/, + double* output_B) const { - const int np = numPhases(); + const int np = numPhases(); for (int phase = 0; phase < np; ++phase) { // #pragma omp parallel for for (int i = 0; i < n; ++i) { output_B[np*i + phase] = formation_volume_factor_[phase]; } - } + } } void PvtPropertiesBasic::dBdp(const int n, - const double* /*p*/, - const double* /*z*/, - double* output_B, - double* output_dBdp) const + const double* /*p*/, + const double* /*z*/, + double* output_B, + double* output_dBdp) const { - const int np = numPhases(); + const int np = numPhases(); for (int phase = 0; phase < np; ++phase) { // #pragma omp parallel for for (int i = 0; i < n; ++i) { output_B[np*i + phase] = formation_volume_factor_[phase]; output_dBdp[np*i + phase] = 0.0; } - } + } } void PvtPropertiesBasic::R(const int n, - const double* /*p*/, - const double* /*z*/, - double* output_R) const + const double* /*p*/, + const double* /*z*/, + double* output_R) const { - const int np = numPhases(); - std::fill(output_R, output_R + n*np, 0.0); + const int np = numPhases(); + std::fill(output_R, output_R + n*np, 0.0); } void PvtPropertiesBasic::dRdp(const int n, - const double* /*p*/, - const double* /*z*/, - double* output_R, - double* output_dRdp) const + const double* /*p*/, + const double* /*z*/, + double* output_R, + double* output_dRdp) const { - const int np = numPhases(); - std::fill(output_R, output_R + n*np, 0.0); - std::fill(output_dRdp, output_dRdp + n*np, 0.0); + const int np = numPhases(); + std::fill(output_R, output_R + n*np, 0.0); + std::fill(output_dRdp, output_dRdp + n*np, 0.0); } } // namespace Opm diff --git a/opm/core/fluid/PvtPropertiesBasic.hpp b/opm/core/fluid/PvtPropertiesBasic.hpp index d1a3e9f3d..3e30e807c 100644 --- a/opm/core/fluid/PvtPropertiesBasic.hpp +++ b/opm/core/fluid/PvtPropertiesBasic.hpp @@ -38,11 +38,11 @@ namespace Opm PvtPropertiesBasic(); /// Initialize from parameters. - /// The following parameters are accepted (defaults): - /// num_phases (2) Must be 1, 2 or 3. - /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 - /// mu1 [mu2, mu3] (1.0) Viscosity in cP - void init(const parameter::ParameterGroup& param); + /// The following parameters are accepted (defaults): + /// num_phases (2) Must be 1, 2 or 3. + /// rho1 [rho2, rho3] (1.0e3) Density in kg/m^3 + /// mu1 [mu2, mu3] (1.0) Viscosity in cP + void init(const parameter::ParameterGroup& param); /// Initialize from arguments. /// Basic multi phase fluid pvt properties. @@ -55,7 +55,7 @@ namespace Opm /// Densities of stock components at surface conditions. /// \return Array of size numPhases(). - const double* surfaceDensities() const; + const double* surfaceDensities() const; /// Viscosity as a function of p and z. void mu(const int n, @@ -90,9 +90,9 @@ namespace Opm double* output_dRdp) const; private: - std::vector density_; - std::vector viscosity_; - std::vector formation_volume_factor_; + std::vector density_; + std::vector viscosity_; + std::vector formation_volume_factor_; }; } diff --git a/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp b/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp index 62cc1b231..34a4ba002 100644 --- a/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp +++ b/opm/core/fluid/PvtPropertiesIncompFromDeck.cpp @@ -38,54 +38,54 @@ namespace Opm { typedef std::vector > > table_t; // If we need multiple regions, this class and the SinglePvt* classes must change. - int region_number = 0; + int region_number = 0; PhaseUsage phase_usage = phaseUsageFromDeck(deck); - if (phase_usage.phase_used[PhaseUsage::Vapour] || - !phase_usage.phase_used[PhaseUsage::Aqua] || - !phase_usage.phase_used[PhaseUsage::Liquid]) { - THROW("PvtPropertiesIncompFromDeck::init() -- must have gas and oil phases (only) in deck input.\n"); - } + if (phase_usage.phase_used[PhaseUsage::Vapour] || + !phase_usage.phase_used[PhaseUsage::Aqua] || + !phase_usage.phase_used[PhaseUsage::Liquid]) { + THROW("PvtPropertiesIncompFromDeck::init() -- must have gas and oil phases (only) in deck input.\n"); + } - // Surface densities. Accounting for different orders in eclipse and our code. - if (deck.hasField("DENSITY")) { - const std::vector& d = deck.getDENSITY().densities_[region_number]; - enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 }; - surface_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] = d[ECL_water]; - surface_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] = d[ECL_oil]; - } else { - THROW("Input is missing DENSITY\n"); - } + // Surface densities. Accounting for different orders in eclipse and our code. + if (deck.hasField("DENSITY")) { + const std::vector& d = deck.getDENSITY().densities_[region_number]; + enum { ECL_oil = 0, ECL_water = 1, ECL_gas = 2 }; + surface_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] = d[ECL_water]; + surface_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] = d[ECL_oil]; + } else { + THROW("Input is missing DENSITY\n"); + } // Make reservoir densities the same as surface densities initially. // We will modify them with formation volume factors if found. reservoir_density_ = surface_density_; // Water viscosity. - if (deck.hasField("PVTW")) { - const std::vector& pvtw = deck.getPVTW().pvtw_[region_number]; - if (pvtw[2] != 0.0 || pvtw[4] != 0.0) { - MESSAGE("Compressibility effects in PVTW are ignored."); - } + if (deck.hasField("PVTW")) { + const std::vector& pvtw = deck.getPVTW().pvtw_[region_number]; + if (pvtw[2] != 0.0 || pvtw[4] != 0.0) { + MESSAGE("Compressibility effects in PVTW are ignored."); + } reservoir_density_[phase_usage.phase_pos[PhaseUsage::Aqua]] /= pvtw[1]; - viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = pvtw[3]; - } else { - // Eclipse 100 default. - // viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = 0.5*Opm::prefix::centi*Opm::unit::Poise; - THROW("Input is missing PVTW\n"); - } + viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = pvtw[3]; + } else { + // Eclipse 100 default. + // viscosity_[phase_usage.phase_pos[PhaseUsage::Aqua]] = 0.5*Opm::prefix::centi*Opm::unit::Poise; + THROW("Input is missing PVTW\n"); + } // Oil viscosity. - if (deck.hasField("PVCDO")) { - const std::vector& pvcdo = deck.getPVCDO().pvcdo_[region_number]; - if (pvcdo[2] != 0.0 || pvcdo[4] != 0.0) { - MESSAGE("Compressibility effects in PVCDO are ignored."); - } + if (deck.hasField("PVCDO")) { + const std::vector& pvcdo = deck.getPVCDO().pvcdo_[region_number]; + if (pvcdo[2] != 0.0 || pvcdo[4] != 0.0) { + MESSAGE("Compressibility effects in PVCDO are ignored."); + } reservoir_density_[phase_usage.phase_pos[PhaseUsage::Liquid]] /= pvcdo[1]; - viscosity_[phase_usage.phase_pos[PhaseUsage::Liquid]] = pvcdo[3]; - } else { - THROW("Input is missing PVCDO\n"); - } + viscosity_[phase_usage.phase_pos[PhaseUsage::Liquid]] = pvcdo[3]; + } else { + THROW("Input is missing PVCDO\n"); + } } const double* PvtPropertiesIncompFromDeck::surfaceDensities() const diff --git a/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp b/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp index acbabaa49..01bbeed1d 100644 --- a/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp +++ b/opm/core/fluid/PvtPropertiesIncompFromDeck.hpp @@ -39,14 +39,14 @@ namespace Opm PvtPropertiesIncompFromDeck(); /// Initialize from deck. - void init(const EclipseGridParser& deck); + void init(const EclipseGridParser& deck); /// Number of active phases. int numPhases() const; /// Densities of stock components at surface conditions. /// \return Array of size numPhases(). - const double* surfaceDensities() const; + const double* surfaceDensities() const; /// Densities of stock components at reservoir conditions. /// Note: a reasonable question to ask is why there can be @@ -58,15 +58,15 @@ namespace Opm /// reporting and using data given in terms of surface values, /// we need to handle this difference. /// \return Array of size numPhases(). - const double* reservoirDensities() const; + const double* reservoirDensities() const; /// Viscosities. const double* viscosity() const; private: - std::tr1::array surface_density_; - std::tr1::array reservoir_density_; - std::tr1::array viscosity_; + std::tr1::array surface_density_; + std::tr1::array reservoir_density_; + std::tr1::array viscosity_; }; } diff --git a/opm/core/fluid/RockBasic.hpp b/opm/core/fluid/RockBasic.hpp index 965637807..2adc3ffd6 100644 --- a/opm/core/fluid/RockBasic.hpp +++ b/opm/core/fluid/RockBasic.hpp @@ -35,9 +35,9 @@ namespace Opm /// Initialize with homogenous porosity and permeability. void init(const int dimensions, - const int num_cells, - const double poro, - const double perm); + const int num_cells, + const double poro, + const double perm); /// \return D, the number of spatial dimensions. int numDimensions() const @@ -66,7 +66,7 @@ namespace Opm } private: - int dimensions_; + int dimensions_; std::vector porosity_; std::vector permeability_; }; diff --git a/opm/core/fluid/RockCompressibility.cpp b/opm/core/fluid/RockCompressibility.cpp index 104861013..af65d852b 100644 --- a/opm/core/fluid/RockCompressibility.cpp +++ b/opm/core/fluid/RockCompressibility.cpp @@ -69,8 +69,8 @@ namespace Opm const double cpnorm = rock_comp_*(pressure - pref_); return (1.0 + cpnorm + 0.5*cpnorm*cpnorm); } else { - // return Opm::linearInterpolation(p_, poromult_, pressure); - return Opm::linearInterpolationExtrap(p_, poromult_, pressure); + // return Opm::linearInterpolation(p_, poromult_, pressure); + return Opm::linearInterpolationExtrap(p_, poromult_, pressure); } } @@ -81,7 +81,7 @@ namespace Opm } else { //const double poromult = Opm::linearInterpolation(p_, poromult_, pressure); //const double dporomultdp = Opm::linearInterpolationDerivative(p_, poromult_, pressure); - const double poromult = Opm::linearInterpolationExtrap(p_, poromult_, pressure); + const double poromult = Opm::linearInterpolationExtrap(p_, poromult_, pressure); const double dporomultdp = Opm::linearInterpolationDerivativeExtrap(p_, poromult_, pressure); return dporomultdp/poromult; diff --git a/opm/core/fluid/RockFromDeck.cpp b/opm/core/fluid/RockFromDeck.cpp index 7ba8903fd..ec7db9a6a 100644 --- a/opm/core/fluid/RockFromDeck.cpp +++ b/opm/core/fluid/RockFromDeck.cpp @@ -51,7 +51,7 @@ namespace Opm /// Initialize from deck and cell mapping. /// \param deck Deck input parser - /// \param grid grid to which property object applies, needed for the + /// \param grid grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. void RockFromDeck::init(const EclipseGridParser& deck, diff --git a/opm/core/fluid/RockFromDeck.hpp b/opm/core/fluid/RockFromDeck.hpp index 65027e425..63e71a6e4 100644 --- a/opm/core/fluid/RockFromDeck.hpp +++ b/opm/core/fluid/RockFromDeck.hpp @@ -37,7 +37,7 @@ namespace Opm /// Initialize from deck and grid. /// \param deck Deck input parser - /// \param grid Grid to which property object applies, needed for the + /// \param grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. void init(const EclipseGridParser& deck, diff --git a/opm/core/fluid/SaturationPropsBasic.cpp b/opm/core/fluid/SaturationPropsBasic.cpp index 760f934d4..10ddf23dd 100644 --- a/opm/core/fluid/SaturationPropsBasic.cpp +++ b/opm/core/fluid/SaturationPropsBasic.cpp @@ -29,64 +29,64 @@ namespace Opm namespace { - struct KrFunConstant - { - double kr(double) - { - return 1.0; - } - double dkrds(double) - { - return 0.0; - } - }; + struct KrFunConstant + { + double kr(double) + { + return 1.0; + } + double dkrds(double) + { + return 0.0; + } + }; - struct KrFunLinear - { - double kr(double s) - { - return s; - } - double dkrds(double) - { - return 1.0; - } - }; + struct KrFunLinear + { + double kr(double s) + { + return s; + } + double dkrds(double) + { + return 1.0; + } + }; - struct KrFunQuadratic - { - double kr(double s) - { - return s*s; - } - double dkrds(double s) - { - return 2.0*s; - } - }; + struct KrFunQuadratic + { + double kr(double s) + { + return s*s; + } + double dkrds(double s) + { + return 2.0*s; + } + }; - template - static inline void evalAllKrDeriv(const int n, const int np, - const double* s, double* kr, double* dkrds, Fun fun) - { - if (dkrds == 0) { + template + static inline void evalAllKrDeriv(const int n, const int np, + const double* s, double* kr, double* dkrds, Fun fun) + { + if (dkrds == 0) { // #pragma omp parallel for - for (int i = 0; i < n*np; ++i) { - kr[i] = fun.kr(s[i]); - } - return; - } + for (int i = 0; i < n*np; ++i) { + kr[i] = fun.kr(s[i]); + } + return; + } // #pragma omp parallel for - for (int i = 0; i < n; ++i) { - std::fill(dkrds + i*np*np, dkrds + (i+1)*np*np, 0.0); - for (int phase = 0; phase < np; ++phase) { - kr[i*np + phase] = fun.kr(s[i*np + phase]); - // Only diagonal elements in derivative. - dkrds[i*np*np + phase*np + phase] = fun.dkrds(s[i*np + phase]); - } - } - } + for (int i = 0; i < n; ++i) { + std::fill(dkrds + i*np*np, dkrds + (i+1)*np*np, 0.0); + for (int phase = 0; phase < np; ++phase) { + kr[i*np + phase] = fun.kr(s[i*np + phase]); + // Only diagonal elements in derivative. + dkrds[i*np*np + phase*np + phase] = fun.dkrds(s[i*np + phase]); + } + } + } } // anon namespace @@ -109,25 +109,25 @@ namespace Opm /// Initialize from parameters. void SaturationPropsBasic::init(const parameter::ParameterGroup& param) { - int num_phases = param.getDefault("num_phases", 2); - if (num_phases > 2 || num_phases < 1) { - THROW("SaturationPropsBasic::init() illegal num_phases: " << num_phases); - } + int num_phases = param.getDefault("num_phases", 2); + if (num_phases > 2 || num_phases < 1) { + THROW("SaturationPropsBasic::init() illegal num_phases: " << num_phases); + } num_phases_ = num_phases; - //std::string rpf = param.getDefault("relperm_func", std::string("Unset")); - std::string rpf = param.getDefault("relperm_func", std::string("Linear")); - if (rpf == "Constant") { - relperm_func_ = Constant; - if(num_phases!=1){ - THROW("Constant relperm with more than one phase???"); - } - } else if (rpf == "Linear") { - relperm_func_ = Linear; - } else if (rpf == "Quadratic") { - relperm_func_ = Quadratic; - } else { - THROW("SaturationPropsBasic::init() illegal relperm_func: " << rpf); - } + //std::string rpf = param.getDefault("relperm_func", std::string("Unset")); + std::string rpf = param.getDefault("relperm_func", std::string("Linear")); + if (rpf == "Constant") { + relperm_func_ = Constant; + if(num_phases!=1){ + THROW("Constant relperm with more than one phase???"); + } + } else if (rpf == "Linear") { + relperm_func_ = Linear; + } else if (rpf == "Quadratic") { + relperm_func_ = Quadratic; + } else { + THROW("SaturationPropsBasic::init() illegal relperm_func: " << rpf); + } } @@ -136,7 +136,7 @@ namespace Opm /// \return P, the number of phases. int SaturationPropsBasic::numPhases() const { - return num_phases_; + return num_phases_; } @@ -152,29 +152,29 @@ namespace Opm /// m_{ij} = \frac{dkr_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) void SaturationPropsBasic::relperm(const int n, - const double* s, - double* kr, - double* dkrds) const + const double* s, + double* kr, + double* dkrds) const { - switch (relperm_func_) { - case Constant: - { - evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunConstant()); - break; - } - case Linear: - { - evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunLinear()); - break; - } - case Quadratic: - { - evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunQuadratic()); - break; - } - default: - THROW("SaturationPropsBasic::relperm() unhandled relperm func type: " << relperm_func_); - } + switch (relperm_func_) { + case Constant: + { + evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunConstant()); + break; + } + case Linear: + { + evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunLinear()); + break; + } + case Quadratic: + { + evalAllKrDeriv(n, num_phases_, s, kr, dkrds, KrFunQuadratic()); + break; + } + default: + THROW("SaturationPropsBasic::relperm() unhandled relperm func type: " << relperm_func_); + } } @@ -190,13 +190,13 @@ namespace Opm /// m_{ij} = \frac{dpc_i}{ds^j}, /// and is output in Fortran order (m_00 m_10 m_20 m01 ...) void SaturationPropsBasic::capPress(const int n, - const double* /*s*/, - double* pc, - double* dpcds) const + const double* /*s*/, + double* pc, + double* dpcds) const { - std::fill(pc, pc + num_phases_*n, 0.0); + std::fill(pc, pc + num_phases_*n, 0.0); if (dpcds) { - std::fill(dpcds, dpcds + num_phases_*num_phases_*n, 0.0); + std::fill(dpcds, dpcds + num_phases_*num_phases_*n, 0.0); } } @@ -207,11 +207,11 @@ namespace Opm /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. void SaturationPropsBasic::satRange(const int n, - double* smin, - double* smax) const + double* smin, + double* smax) const { - std::fill(smin, smin + num_phases_*n, 0.0); - std::fill(smax, smax + num_phases_*n, 1.0); + std::fill(smin, smin + num_phases_*n, 0.0); + std::fill(smax, smax + num_phases_*n, 1.0); } diff --git a/opm/core/fluid/SaturationPropsBasic.hpp b/opm/core/fluid/SaturationPropsBasic.hpp index 789e0a351..2f90672d8 100644 --- a/opm/core/fluid/SaturationPropsBasic.hpp +++ b/opm/core/fluid/SaturationPropsBasic.hpp @@ -40,16 +40,16 @@ namespace Opm SaturationPropsBasic(); /// Initialize from parameters. - /// The following parameters are accepted (defaults): - /// num_phases (2) Must be 1 or 2. - /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". + /// The following parameters are accepted (defaults): + /// num_phases (2) Must be 1 or 2. + /// relperm_func ("Linear") Must be "Constant", "Linear" or "Quadratic". void init(const parameter::ParameterGroup& param); - enum RelPermFunc { Constant, Linear, Quadratic }; + enum RelPermFunc { Constant, Linear, Quadratic }; /// Initialize from arguments a basic Saturation property. void init(const int num_phases, - const RelPermFunc& relperm_func) + const RelPermFunc& relperm_func) { num_phases_ = num_phases; relperm_func_ = relperm_func; @@ -86,18 +86,18 @@ namespace Opm double* pc, double* dpcds) const; - /// Obtain the range of allowable saturation values. + /// Obtain the range of allowable saturation values. /// \param[in] n Number of data points. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. - void satRange(const int n, - double* smin, - double* smax) const; + void satRange(const int n, + double* smin, + double* smax) const; private: - int num_phases_; - RelPermFunc relperm_func_; + int num_phases_; + RelPermFunc relperm_func_; }; diff --git a/opm/core/fluid/SaturationPropsFromDeck.hpp b/opm/core/fluid/SaturationPropsFromDeck.hpp index 42461985c..0a0599ec8 100644 --- a/opm/core/fluid/SaturationPropsFromDeck.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck.hpp @@ -50,7 +50,7 @@ namespace Opm /// Initialize from deck and grid. /// \param[in] deck Deck input parser - /// \param[in] grid Grid to which property object applies, needed for the + /// \param[in] grid Grid to which property object applies, needed for the /// mapping from cell indices (typically from a processed grid) /// to logical cartesian indices consistent with the deck. /// \param[in] samples Number of uniform sample points for saturation tables. @@ -92,14 +92,14 @@ namespace Opm double* pc, double* dpcds) const; - /// Obtain the range of allowable saturation values. + /// Obtain the range of allowable saturation values. /// \param[in] n Number of data points. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. - void satRange(const int n, + void satRange(const int n, const int* cells, - double* smin, - double* smax) const; + double* smin, + double* smax) const; private: PhaseUsage phase_usage_; diff --git a/opm/core/fluid/SaturationPropsFromDeck_impl.hpp b/opm/core/fluid/SaturationPropsFromDeck_impl.hpp index a4df7f425..f7a80b453 100644 --- a/opm/core/fluid/SaturationPropsFromDeck_impl.hpp +++ b/opm/core/fluid/SaturationPropsFromDeck_impl.hpp @@ -105,7 +105,7 @@ namespace Opm template int SaturationPropsFromDeck::numPhases() const { - return phase_usage_.num_phases; + return phase_usage_.num_phases; } @@ -191,18 +191,18 @@ namespace Opm template void SaturationPropsFromDeck::satRange(const int n, const int* cells, - double* smin, - double* smax) const + double* smin, + double* smax) const { ASSERT (cells != 0); - const int np = phase_usage_.num_phases; - for (int i = 0; i < n; ++i) { - for (int p = 0; p < np; ++p) { - smin[np*i + p] = funcForCell(cells[i]).smin_[p]; - smax[np*i + p] = funcForCell(cells[i]).smax_[p]; - } - } + const int np = phase_usage_.num_phases; + for (int i = 0; i < n; ++i) { + for (int p = 0; p < np; ++p) { + smin[np*i + p] = funcForCell(cells[i]).smin_[p]; + smax[np*i + p] = funcForCell(cells[i]).smax_[p]; + } + } } diff --git a/opm/core/fluid/SaturationPropsInterface.hpp b/opm/core/fluid/SaturationPropsInterface.hpp index e55995677..30f277cc1 100644 --- a/opm/core/fluid/SaturationPropsInterface.hpp +++ b/opm/core/fluid/SaturationPropsInterface.hpp @@ -65,11 +65,11 @@ namespace Opm double* pc, double* dpcds) const = 0; - /// Obtain the range of allowable saturation values. + /// Obtain the range of allowable saturation values. /// \param[in] n Number of data points. /// \param[out] smin Array of nP minimum s values, array must be valid before calling. /// \param[out] smax Array of nP maximum s values, array must be valid before calling. - virtual void satRange(const int n, + virtual void satRange(const int n, const int* cells, double* smin, double* smax) const = 0; diff --git a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp index d3a42e321..8633fd9ee 100644 --- a/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp +++ b/opm/core/fluid/blackoil/BlackoilPvtProperties.hpp @@ -70,7 +70,7 @@ namespace Opm /// Densities of stock components at surface conditions. /// \return Array of size numPhases(). - const double* surfaceDensities() const; + const double* surfaceDensities() const; /// Viscosity as a function of p and z. void mu(const int n, @@ -111,11 +111,11 @@ namespace Opm PhaseUsage phase_usage_; - int region_number_; + int region_number_; std::vector > props_; - double densities_[MaxNumPhases]; + double densities_[MaxNumPhases]; mutable std::vector data1_; mutable std::vector data2_; };