From 5d5ab267d2aec15d72645c5d4c3921579c7b7ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 10 Mar 2015 10:34:21 +0100 Subject: [PATCH 1/8] Use std::move() in variableState(). --- .../FullyImplicitBlackoilSolver_impl.hpp | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp index d0625ee32..726d2e28d 100644 --- a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp +++ b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp @@ -542,21 +542,20 @@ namespace detail { // Pressure. int nextvar = 0; - state.pressure = vars[ nextvar++ ]; + state.pressure = std::move(vars[ nextvar++ ]); // temperature const V temp = Eigen::Map(& x.temperature()[0], x.temperature().size()); state.temperature = ADB::constant(temp); // Saturations - const std::vector& bpat = vars[0].blockPattern(); { - ADB so = ADB::constant(V::Ones(nc, 1), bpat); + ADB so = ADB::constant(V::Ones(nc, 1)); if (active_[ Water ]) { - ADB& sw = vars[ nextvar++ ]; - state.saturation[pu.phase_pos[ Water ]] = sw; + state.saturation[pu.phase_pos[ Water ]] = std::move(vars[ nextvar++ ]); + const ADB& sw = state.saturation[pu.phase_pos[ Water ]]; so -= sw; } @@ -572,7 +571,7 @@ namespace detail { // RS and RV is only defined if both oil and gas phase are active. const ADB& sw = (active_[ Water ] ? state.saturation[ pu.phase_pos[ Water ] ] - : ADB::constant(V::Zero(nc, 1), bpat)); + : ADB::constant(V::Zero(nc, 1))); state.canonical_phase_pressures = computePressures(state.pressure, sw, so, sg); const ADB rsSat = fluidRsSat(state.canonical_phase_pressures[ Oil ], so , cells_); if (has_disgas_) { @@ -591,15 +590,15 @@ namespace detail { if (active_[ Oil ]) { // Note that so is never a primary variable. - state.saturation[pu.phase_pos[ Oil ]] = so; + state.saturation[pu.phase_pos[ Oil ]] = std::move(so); } } // Qs. - state.qs = vars[ nextvar++ ]; + state.qs = std::move(vars[ nextvar++ ]); // Bhp. - state.bhp = vars[ nextvar++ ]; + state.bhp = std::move(vars[ nextvar++ ]); assert(nextvar == int(vars.size())); From 635f3db8146079b22678df2024655317c526e098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 10 Mar 2015 10:34:58 +0100 Subject: [PATCH 2/8] Use references in computeRelperm(). --- .../FullyImplicitBlackoilSolver_impl.hpp | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp index 726d2e28d..42da494d6 100644 --- a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp +++ b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp @@ -1606,22 +1606,21 @@ namespace detail { { using namespace Opm::AutoDiffGrid; const int nc = numCells(grid_); - const std::vector& bpat = state.pressure.blockPattern(); - const ADB null = ADB::constant(V::Zero(nc, 1), bpat); + const ADB zero = ADB::constant(V::Zero(nc)); const Opm::PhaseUsage& pu = fluid_.phaseUsage(); - const ADB sw = (active_[ Water ] - ? state.saturation[ pu.phase_pos[ Water ] ] - : null); + const ADB& sw = (active_[ Water ] + ? state.saturation[ pu.phase_pos[ Water ] ] + : zero); - const ADB so = (active_[ Oil ] - ? state.saturation[ pu.phase_pos[ Oil ] ] - : null); + const ADB& so = (active_[ Oil ] + ? state.saturation[ pu.phase_pos[ Oil ] ] + : zero); - const ADB sg = (active_[ Gas ] - ? state.saturation[ pu.phase_pos[ Gas ] ] - : null); + const ADB& sg = (active_[ Gas ] + ? state.saturation[ pu.phase_pos[ Gas ] ] + : zero); return fluid_.relperm(sw, so, sg, cells_); } From 04b255a03f0c24851b0c3f1024925e2dac7c3717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 10 Mar 2015 12:36:14 +0100 Subject: [PATCH 3/8] Make more use of move semantics in AD code. This makes some API changes to AutoDiffBlock. - Add overload for the constant() constructor taking rvalue ref. - Add overload for the variable() constructor taking rvalue ref. - Make the function() constructor *require* rvalue refs. - Add a swap() function. The remaining changes in this commit are follow-ups especially to the third change (adding std::move in many places), and some removal of unnecessary block pattern arguments from calls to the constant() static method. --- examples/sim_simple.cpp | 4 +- opm/autodiff/AutoDiffBlock.hpp | 66 ++++++++++++++----- opm/autodiff/AutoDiffHelpers.hpp | 3 +- opm/autodiff/BlackoilPropsAdFromDeck.cpp | 26 ++++---- .../FullyImplicitBlackoilSolver_impl.hpp | 38 ++++++----- opm/autodiff/ImpesTPFAAD.cpp | 11 ++-- opm/autodiff/NewtonIterationBlackoilCPR.cpp | 5 +- opm/autodiff/TransportSolverTwophaseAd.cpp | 4 +- tests/test_block.cpp | 7 +- 9 files changed, 100 insertions(+), 64 deletions(-) diff --git a/examples/sim_simple.cpp b/examples/sim_simple.cpp index b8403b7ef..caa824ee3 100644 --- a/examples/sim_simple.cpp +++ b/examples/sim_simple.cpp @@ -90,8 +90,8 @@ phaseMobility(const Opm::IncompPropertiesInterface& props, std::vector dmw = { krwjac/mu[0] }; std::vector dmo = { krojac/mu[1] }; - std::vector pmobc = { ADB::function(krw / mu[0], dmw) , - ADB::function(kro / mu[1], dmo) }; + std::vector pmobc = { ADB::function(krw / mu[0], std::move(dmw)) , + ADB::function(kro / mu[1], std::move(dmo)) }; return pmobc; } diff --git a/opm/autodiff/AutoDiffBlock.hpp b/opm/autodiff/AutoDiffBlock.hpp index aaf9789d6..7ab3008ef 100644 --- a/opm/autodiff/AutoDiffBlock.hpp +++ b/opm/autodiff/AutoDiffBlock.hpp @@ -98,9 +98,14 @@ namespace Opm /// Construct an empty AutoDiffBlock. static AutoDiffBlock null() { - V val; - std::vector jac; - return AutoDiffBlock(val, jac); + return AutoDiffBlock(V(), {}); + } + + /// Create an AutoDiffBlock representing a constant. + /// \param[in] val values + static AutoDiffBlock constant(V&& val) + { + return AutoDiffBlock(std::move(val)); } /// Create an AutoDiffBlock representing a constant. @@ -126,7 +131,8 @@ namespace Opm for (int i = 0; i < num_blocks; ++i) { jac[i] = M(num_elem, blocksizes[i]); } - return AutoDiffBlock(val, jac); + V val_copy(val); + return AutoDiffBlock(std::move(val_copy), std::move(jac)); } /// Create an AutoDiffBlock representing a single variable block. @@ -136,7 +142,7 @@ namespace Opm /// The resulting object will have size() equal to block_pattern[index]. /// Its jacobians will all be zero, except for derivative()[index], which /// will be an identity matrix. - static AutoDiffBlock variable(const int index, const V& val, const std::vector& blocksizes) + static AutoDiffBlock variable(const int index, V&& val, const std::vector& blocksizes) { std::vector jac; const int num_elem = val.size(); @@ -164,15 +170,28 @@ namespace Opm assert(jac[i].size()==0); } } - return AutoDiffBlock(val, jac); + return AutoDiffBlock(std::move(val), std::move(jac)); + } + + /// Create an AutoDiffBlock representing a single variable block. + /// \param[in] index index of the variable you are constructing + /// \param[in] val values + /// \param[in] blocksizes block pattern + /// The resulting object will have size() equal to block_pattern[index]. + /// Its jacobians will all be zero, except for derivative()[index], which + /// will be an identity matrix. + static AutoDiffBlock variable(const int index, const V& val, const std::vector& blocksizes) + { + V value = val; + return variable(index, std::move(value), blocksizes); } /// Create an AutoDiffBlock by directly specifying values and jacobians. /// \param[in] val values /// \param[in] jac vector of jacobians - static AutoDiffBlock function(const V& val, const std::vector& jac) + static AutoDiffBlock function(V&& val, std::vector&& jac) { - return AutoDiffBlock(val, jac); + return AutoDiffBlock(std::move(val), std::move(jac)); } /// Construct a set of primary variables, each initialized to @@ -259,7 +278,7 @@ namespace Opm assert(jac[block].cols() == rhs.jac_[block].cols()); jac[block] += rhs.jac_[block]; } - return function(val_ + rhs.val_, jac); + return function(val_ + rhs.val_, std::move(jac)); } /// Elementwise operator - @@ -282,7 +301,7 @@ namespace Opm assert(jac[block].cols() == rhs.jac_[block].cols()); jac[block] -= rhs.jac_[block]; } - return function(val_ - rhs.val_, jac); + return function(val_ - rhs.val_, std::move(jac)); } /// Elementwise operator * @@ -318,7 +337,7 @@ namespace Opm jac[block] = D2*jac_[block] + D1*rhs.jac_[block]; } } - return function(val_ * rhs.val_, jac); + return function(val_ * rhs.val_, std::move(jac)); } /// Elementwise operator / @@ -358,7 +377,7 @@ namespace Opm jac[block] = D3 * (D2*jac_[block] - D1*rhs.jac_[block]); } } - return function(val_ / rhs.val_, jac); + return function(val_ / rhs.val_, std::move(jac)); } /// I/O. @@ -374,6 +393,13 @@ namespace Opm return os; } + /// Efficient swap function. + void swap(AutoDiffBlock& other) + { + val_.swap(other.val_); + jac_.swap(other.jac_); + } + /// Number of elements int size() const { @@ -411,13 +437,17 @@ namespace Opm private: AutoDiffBlock(const V& val) - : val_(val) + : val_(val) { } - AutoDiffBlock(const V& val, - const std::vector& jac) - : val_(val), jac_(jac) + AutoDiffBlock(V&& val) + : val_(std::move(val)) + { + } + + AutoDiffBlock(V&& val, std::vector&& jac) + : val_(std::move(val)), jac_(std::move(jac)) { #ifndef NDEBUG const int num_elem = val_.size(); @@ -457,7 +487,7 @@ namespace Opm fastSparseProduct(lhs, rhs.derivative()[block], jac[block]); } typename AutoDiffBlock::V val = lhs*rhs.value().matrix(); - return AutoDiffBlock::function(val, jac); + return AutoDiffBlock::function(std::move(val), std::move(jac)); } @@ -549,7 +579,7 @@ namespace Opm for (int block=0; block::function( lhs.value() * rhs, jac ); + return AutoDiffBlock::function( lhs.value() * rhs, std::move(jac) ); } diff --git a/opm/autodiff/AutoDiffHelpers.hpp b/opm/autodiff/AutoDiffHelpers.hpp index 8036582d9..c49c6c65a 100644 --- a/opm/autodiff/AutoDiffHelpers.hpp +++ b/opm/autodiff/AutoDiffHelpers.hpp @@ -403,7 +403,8 @@ collapseJacs(const AutoDiffBlock& x) // Build final jacobian. std::vector jacs(1); collapseJacs( x, jacs[ 0 ] ); - return ADB::function(x.value(), jacs); + ADB::V val = x.value(); + return ADB::function(std::move(val), std::move(jacs)); } diff --git a/opm/autodiff/BlackoilPropsAdFromDeck.cpp b/opm/autodiff/BlackoilPropsAdFromDeck.cpp index 9d328ce88..2f1075aab 100644 --- a/opm/autodiff/BlackoilPropsAdFromDeck.cpp +++ b/opm/autodiff/BlackoilPropsAdFromDeck.cpp @@ -335,7 +335,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& props_[phase_usage_.phase_pos[Water]]->mu(n, pvt_region_.data(), pw.value().data(), T.value().data(), rs, mu.data(), dmudp.data(), dmudr.data()); if (pw.derivative().empty()) { - return ADB::constant(mu); + return ADB::constant(std::move(mu)); } else { ADB::M dmudp_diag = spdiag(dmudp); const int num_blocks = pw.numBlocks(); @@ -343,7 +343,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(dmudp_diag, pw.derivative()[block], jacs[block]); } - return ADB::function(mu, jacs); + return ADB::function(std::move(mu), std::move(jacs)); } } @@ -383,7 +383,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& fastSparseProduct(dmudr_diag, rs.derivative()[block], temp); jacs[block] += temp; } - return ADB::function(mu, jacs); + return ADB::function(std::move(mu), std::move(jacs)); } /// Gas viscosity. @@ -422,7 +422,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& fastSparseProduct(dmudr_diag, rv.derivative()[block], temp); jacs[block] += temp; } - return ADB::function(mu, jacs); + return ADB::function(std::move(mu), std::move(jacs)); } @@ -459,7 +459,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(dbdp_diag, pw.derivative()[block], jacs[block]); } - return ADB::function(b, jacs); + return ADB::function(std::move(b), std::move(jacs)); } /// Oil formation volume factor. @@ -499,7 +499,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& fastSparseProduct(dbdr_diag, rs.derivative()[block], temp); jacs[block] += temp; } - return ADB::function(b, jacs); + return ADB::function(std::move(b), std::move(jacs)); } /// Gas formation volume factor. @@ -539,7 +539,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& fastSparseProduct(dbdr_diag, rv.derivative()[block], temp); jacs[block] += temp; } - return ADB::function(b, jacs); + return ADB::function(std::move(b), std::move(jacs)); } @@ -568,7 +568,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(drbubdp_diag, po.derivative()[block], jacs[block]); } - return ADB::function(rbub, jacs); + return ADB::function(std::move(rbub), std::move(jacs)); } /// Bubble point curve for Rs as function of oil pressure. @@ -609,7 +609,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(drvdp_diag, po.derivative()[block], jacs[block]); } - return ADB::function(rv, jacs); + return ADB::function(std::move(rv), std::move(jacs)); } /// Condensation curve for Rv as function of oil pressure. @@ -686,7 +686,8 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& jacs[block] += temp; } } - relperms.emplace_back(ADB::function(kr.col(phase1_pos), jacs)); + ADB::V val = kr.col(phase1_pos); + relperms.emplace_back(ADB::function(std::move(val), std::move(jacs))); } else { relperms.emplace_back(ADB::null()); } @@ -746,7 +747,8 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& jacs[block] += temp; } } - adbCapPressures.emplace_back(ADB::function(pc.col(phase1_pos), jacs)); + ADB::V val = pc.col(phase1_pos); + adbCapPressures.emplace_back(ADB::function(std::move(val), std::move(jacs))); } else { adbCapPressures.emplace_back(ADB::null()); } @@ -849,7 +851,7 @@ BlackoilPropsAdFromDeck::BlackoilPropsAdFromDeck(const BlackoilPropsAdFromDeck& for (int block = 0; block < num_blocks; ++block) { jacs[block] = dfactor_dso_diag * so.derivative()[block]; } - r = ADB::function(factor, jacs)*r; + r = ADB::function(std::move(factor), std::move(jacs))*r; } } diff --git a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp index 42da494d6..163fc1e08 100644 --- a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp +++ b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp @@ -945,7 +945,7 @@ namespace detail { } // total rates at std - ADB qt_s = ADB::constant(V::Zero(nw), state.bhp.blockPattern()); + ADB qt_s = ADB::constant(V::Zero(nw)); for (int phase = 0; phase < np; ++phase) { qt_s += subset(state.qs, Span(nw, 1, phase*nw)); } @@ -953,7 +953,7 @@ namespace detail { // compute avg. and total wellbore phase volumetric rates at std. conds const DataBlock compi = Eigen::Map(wells().comp_frac, nw, np); std::vector wbq(np, ADB::null()); - ADB wbqt = ADB::constant(V::Zero(nw), state.pressure.blockPattern()); + ADB wbqt = ADB::constant(V::Zero(nw)); for (int phase = 0; phase < np; ++phase) { const int pos = pu.phase_pos[phase]; wbq[phase] = (isInj * compi.col(pos)) * qt_s - q_ps[phase]; @@ -994,7 +994,7 @@ namespace detail { ADB cqt_i = -(isInjInx * Tw) * (mt * drawdown); // compute volume ratio between connection at standard conditions - ADB volRat = ADB::constant(V::Zero(nperf), state.pressure.blockPattern()); + ADB volRat = ADB::constant(V::Zero(nperf)); std::vector cmix_s(np, ADB::null()); for (int phase = 0; phase < np; ++phase) { cmix_s[phase] = wops_.w2p * mix_s[phase]; @@ -1222,16 +1222,22 @@ namespace detail { // Update primary variables, if necessary. if (bhp_changed) { + // We will set the bhp primary variable to the new ones, + // but we do not change the derivatives here. ADB::V new_bhp = Eigen::Map(xw.bhp().data(), nw); - bhp = ADB::function(new_bhp, bhp.derivative()); + // Avoiding the copy below would require a value setter method + // in AutoDiffBlock. + std::vector old_derivs = bhp.derivative(); + bhp = ADB::function(std::move(new_bhp), std::move(old_derivs)); } if (rates_changed) { // Need to reshuffle well rates, from phase running fastest // to wells running fastest. // The transpose() below switches the ordering. const DataBlock wrates = Eigen::Map(xw.wellRates().data(), nw, np).transpose(); - const ADB::V new_qs = Eigen::Map(wrates.data(), nw*np); - well_phase_flow_rate = ADB::function(new_qs, well_phase_flow_rate.derivative()); + ADB::V new_qs = Eigen::Map(wrates.data(), nw*np); + std::vector old_derivs = well_phase_flow_rate.derivative(); + well_phase_flow_rate = ADB::function(std::move(new_qs), std::move(old_derivs)); } } @@ -1635,9 +1641,8 @@ namespace detail { { using namespace Opm::AutoDiffGrid; const int nc = numCells(grid_); - const std::vector& bpat = state.pressure.blockPattern(); - const ADB null = ADB::constant(V::Zero(nc, 1), bpat); + const ADB null = ADB::constant(V::Zero(nc)); const Opm::PhaseUsage& pu = fluid_.phaseUsage(); const ADB& sw = (active_[ Water ] @@ -1724,21 +1729,20 @@ namespace detail { { const int nw = wells().number_of_wells; const int nperf = wells().well_connpos[nw]; - const std::vector& bpat = state.pressure.blockPattern(); - const ADB null = ADB::constant(V::Zero(nperf), bpat); + const ADB null = ADB::constant(V::Zero(nperf)); const Opm::PhaseUsage& pu = fluid_.phaseUsage(); const ADB sw = (active_[ Water ] - ? ADB::constant(well_s.col(pu.phase_pos[ Water ]), bpat) + ? ADB::constant(well_s.col(pu.phase_pos[ Water ])) : null); const ADB so = (active_[ Oil ] - ? ADB::constant(well_s.col(pu.phase_pos[ Oil ]), bpat) + ? ADB::constant(well_s.col(pu.phase_pos[ Oil ])) : null); const ADB sg = (active_[ Gas ] - ? ADB::constant(well_s.col(pu.phase_pos[ Gas ]), bpat) + ? ADB::constant(well_s.col(pu.phase_pos[ Gas ])) : null); return fluid_.relperm(sw, so, sg, well_cells); @@ -2261,9 +2265,9 @@ namespace detail { for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(dpm_diag, p.derivative()[block], jacs[block]); } - return ADB::function(pm, jacs); + return ADB::function(std::move(pm), std::move(jacs)); } else { - return ADB::constant(V::Constant(n, 1.0), p.blockPattern()); + return ADB::constant(V::Constant(n, 1.0)); } } @@ -2289,9 +2293,9 @@ namespace detail { for (int block = 0; block < num_blocks; ++block) { fastSparseProduct(dtm_diag, p.derivative()[block], jacs[block]); } - return ADB::function(tm, jacs); + return ADB::function(std::move(tm), std::move(jacs)); } else { - return ADB::constant(V::Constant(n, 1.0), p.blockPattern()); + return ADB::constant(V::Constant(n, 1.0)); } } diff --git a/opm/autodiff/ImpesTPFAAD.cpp b/opm/autodiff/ImpesTPFAAD.cpp index 90fcaa3d3..e1ffaeae8 100644 --- a/opm/autodiff/ImpesTPFAAD.cpp +++ b/opm/autodiff/ImpesTPFAAD.cpp @@ -326,7 +326,6 @@ namespace { const ADB& p = vars[0]; const ADB T = ADB::constant(T0); const ADB& bhp = vars[1]; - std::vector bpat = p.blockPattern(); // Compute T_ij * (p_i - p_j). const ADB nkgradp = transi * (ops_.ngrad * p); @@ -351,10 +350,10 @@ namespace { const ADB nkgradp_well = transw * (p_perfcell - p_perfwell); const Selector cell_to_well_selector(nkgradp_well.value()); - cell_residual_ = ADB::constant(pv, bpat); - well_residual_ = ADB::constant(V::Zero(nw,1), bpat); - ADB divcontrib_sum = ADB::constant(V::Zero(nc,1), bpat); - qs_ = ADB::constant(V::Zero(nw*np, 1), bpat); + cell_residual_ = ADB::constant(pv); + well_residual_ = ADB::constant(V::Zero(nw,1)); + ADB divcontrib_sum = ADB::constant(V::Zero(nc,1)); + qs_ = ADB::constant(V::Zero(nw*np, 1)); for (int phase = 0; phase < np; ++phase) { const ADB cell_b = fluidFvf(phase, p, T, cells); const ADB cell_rho = fluidRho(phase, p, T, cells); @@ -381,7 +380,7 @@ namespace { const ADB well_contrib = superset(perf_flux*perf_b, well_cells, nc); const ADB divcontrib = delta_t * (ops_.div * (flux * face_b) + well_contrib); const V qcontrib = delta_t * q; - const ADB pvcontrib = ADB::constant(pv*z0, bpat); + const ADB pvcontrib = ADB::constant(pv*z0); const ADB component_contrib = pvcontrib + qcontrib; divcontrib_sum = divcontrib_sum - divcontrib/cell_b; cell_residual_ = cell_residual_ - (component_contrib/cell_b); diff --git a/opm/autodiff/NewtonIterationBlackoilCPR.cpp b/opm/autodiff/NewtonIterationBlackoilCPR.cpp index 1df51a984..7b9126a23 100644 --- a/opm/autodiff/NewtonIterationBlackoilCPR.cpp +++ b/opm/autodiff/NewtonIterationBlackoilCPR.cpp @@ -314,7 +314,7 @@ namespace Opm if (eq == n) { continue; } - retval.push_back(ADB::function(vals[eq], jacs[eq])); + retval.push_back(ADB::function(std::move(vals[eq]), std::move(jacs[eq]))); } return retval; } @@ -338,7 +338,8 @@ namespace Opm // Build C. std::vector C_jacs = equation.derivative(); C_jacs.erase(C_jacs.begin() + n); - ADB eq_coll = collapseJacs(ADB::function(equation.value(), C_jacs)); + V equation_value = equation.value(); + ADB eq_coll = collapseJacs(ADB::function(std::move(equation_value), std::move(C_jacs))); const M& C = eq_coll.derivative()[0]; // Use sparse LU to solve the block submatrices diff --git a/opm/autodiff/TransportSolverTwophaseAd.cpp b/opm/autodiff/TransportSolverTwophaseAd.cpp index 9ac7402ca..117ca51a7 100644 --- a/opm/autodiff/TransportSolverTwophaseAd.cpp +++ b/opm/autodiff/TransportSolverTwophaseAd.cpp @@ -129,8 +129,8 @@ namespace Opm std::vector dmw = { krwjac/mu[0] }; std::vector dmo = { krojac/mu[1] }; - std::vector pmobc = { ADB::function(krw / mu[0], dmw) , - ADB::function(kro / mu[1], dmo) }; + std::vector pmobc = { ADB::function(krw / mu[0], std::move(dmw)) , + ADB::function(kro / mu[1], std::move(dmo)) }; return pmobc; } diff --git a/tests/test_block.cpp b/tests/test_block.cpp index 102237924..538140ae1 100644 --- a/tests/test_block.cpp +++ b/tests/test_block.cpp @@ -77,12 +77,10 @@ BOOST_AUTO_TEST_CASE(ConstantInitialisation) { typedef AutoDiffBlock ADB; - std::vector blocksizes = { 3, 1, 2 }; - ADB::V v(3); v << 0.2, 1.2, 13.4; - ADB a = ADB::constant(v, blocksizes); + ADB a = ADB::constant(v); BOOST_REQUIRE(a.value().matrix() == v.matrix()); const std::vector& J = a.derivative(); @@ -137,7 +135,8 @@ BOOST_AUTO_TEST_CASE(FunctionInitialisation) jacs[j].insert(0,0) = -1.0; } - ADB f = ADB::function(v, jacs); + ADB::V v_copy(v); + ADB f = ADB::function(std::move(v_copy), std::move(jacs)); BOOST_REQUIRE(f.value().matrix() == v.matrix()); From a4a3505faefe1d41e3074e8019505ea2e9016fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 10 Mar 2015 12:46:03 +0100 Subject: [PATCH 4/8] Remove unused method computeRelPermWells(). --- opm/autodiff/FullyImplicitBlackoilSolver.hpp | 5 --- .../FullyImplicitBlackoilSolver_impl.hpp | 31 ------------------- 2 files changed, 36 deletions(-) diff --git a/opm/autodiff/FullyImplicitBlackoilSolver.hpp b/opm/autodiff/FullyImplicitBlackoilSolver.hpp index 71d6d90a8..6ed224c6c 100644 --- a/opm/autodiff/FullyImplicitBlackoilSolver.hpp +++ b/opm/autodiff/FullyImplicitBlackoilSolver.hpp @@ -281,11 +281,6 @@ namespace Opm { std::vector computeRelPerm(const SolutionState& state) const; - std::vector - computeRelPermWells(const SolutionState& state, - const DataBlock& well_s, - const std::vector& well_cells) const; - void computeMassFlux(const int actph , const V& transi, diff --git a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp index 163fc1e08..5d7e63e09 100644 --- a/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp +++ b/opm/autodiff/FullyImplicitBlackoilSolver_impl.hpp @@ -1721,37 +1721,6 @@ namespace detail { - template - std::vector - FullyImplicitBlackoilSolver::computeRelPermWells(const SolutionState& state, - const DataBlock& well_s, - const std::vector& well_cells) const - { - const int nw = wells().number_of_wells; - const int nperf = wells().well_connpos[nw]; - - const ADB null = ADB::constant(V::Zero(nperf)); - - const Opm::PhaseUsage& pu = fluid_.phaseUsage(); - const ADB sw = (active_[ Water ] - ? ADB::constant(well_s.col(pu.phase_pos[ Water ])) - : null); - - const ADB so = (active_[ Oil ] - ? ADB::constant(well_s.col(pu.phase_pos[ Oil ])) - : null); - - const ADB sg = (active_[ Gas ] - ? ADB::constant(well_s.col(pu.phase_pos[ Gas ])) - : null); - - return fluid_.relperm(sw, so, sg, well_cells); - } - - - - - template void FullyImplicitBlackoilSolver::computeMassFlux(const int actph , From 5ff65b40e12dc6abc6566afcb3ed4c3966695cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 10 Mar 2015 12:53:22 +0100 Subject: [PATCH 5/8] Fix bug added when adapting to new API. Avoid using invalidated 'jacs', make copy. --- tests/test_block.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_block.cpp b/tests/test_block.cpp index 538140ae1..51da5f0dd 100644 --- a/tests/test_block.cpp +++ b/tests/test_block.cpp @@ -136,7 +136,8 @@ BOOST_AUTO_TEST_CASE(FunctionInitialisation) } ADB::V v_copy(v); - ADB f = ADB::function(std::move(v_copy), std::move(jacs)); + std::vector jacs_copy(jacs); + ADB f = ADB::function(std::move(v_copy), std::move(jacs_copy)); BOOST_REQUIRE(f.value().matrix() == v.matrix()); From f0ba4a5797fa1bfdb02da6afbc5ff0a1cbdf52bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Mon, 16 Mar 2015 12:43:05 +0100 Subject: [PATCH 6/8] Use swap() and move() to reduce copying in formEllipticSystem(). --- opm/autodiff/NewtonIterationBlackoilCPR.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opm/autodiff/NewtonIterationBlackoilCPR.cpp b/opm/autodiff/NewtonIterationBlackoilCPR.cpp index 7b9126a23..0a014c5f6 100644 --- a/opm/autodiff/NewtonIterationBlackoilCPR.cpp +++ b/opm/autodiff/NewtonIterationBlackoilCPR.cpp @@ -396,7 +396,7 @@ namespace Opm // A concession to MRST, to obtain more similar behaviour: // swap the first two equations, so that oil is first, then water. auto eqs = eqs_in; - std::swap(eqs[0], eqs[1]); + eqs[0].swap(eqs[1]); // Characterize the material balance equations. const int n = eqs[0].size(); @@ -463,7 +463,7 @@ namespace Opm L.setFromTriplets(t.begin(), t.end()); // Combine in single block. - ADB total_residual = eqs[0]; + ADB total_residual = std::move(eqs[0]); for (int phase = 1; phase < num_phases; ++phase) { total_residual = vertcat(total_residual, eqs[phase]); } From 0a76af1b1415e62b5cbe054e56b754ab2435bc55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Tue, 17 Mar 2015 09:46:15 +0100 Subject: [PATCH 7/8] Include for std::move(). --- opm/autodiff/AutoDiffBlock.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/opm/autodiff/AutoDiffBlock.hpp b/opm/autodiff/AutoDiffBlock.hpp index 7ab3008ef..e6feeed14 100644 --- a/opm/autodiff/AutoDiffBlock.hpp +++ b/opm/autodiff/AutoDiffBlock.hpp @@ -28,6 +28,7 @@ #include +#include #include #include #include From ad3da1d946ea28f7c5eb86dc890c89e69979a8fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Atgeirr=20Fl=C3=B8=20Rasmussen?= Date: Thu, 19 Mar 2015 11:25:47 +0100 Subject: [PATCH 8/8] Re-add copying overload of AutoDiffBlock::function(). --- opm/autodiff/AutoDiffBlock.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/opm/autodiff/AutoDiffBlock.hpp b/opm/autodiff/AutoDiffBlock.hpp index e6feeed14..5ba57b32f 100644 --- a/opm/autodiff/AutoDiffBlock.hpp +++ b/opm/autodiff/AutoDiffBlock.hpp @@ -188,6 +188,8 @@ namespace Opm } /// Create an AutoDiffBlock by directly specifying values and jacobians. + /// This version of function() moves its arguments and is therefore + /// quite efficient, but leaves the argument variables empty (but valid). /// \param[in] val values /// \param[in] jac vector of jacobians static AutoDiffBlock function(V&& val, std::vector&& jac) @@ -195,6 +197,18 @@ namespace Opm return AutoDiffBlock(std::move(val), std::move(jac)); } + /// Create an AutoDiffBlock by directly specifying values and jacobians. + /// This version of function() copies its arguments and is therefore + /// less efficient than the other (moving) overload. + /// \param[in] val values + /// \param[in] jac vector of jacobians + static AutoDiffBlock function(const V& val, const std::vector& jac) + { + V val_copy(val); + std::vector jac_copy(jac); + return AutoDiffBlock(std::move(val_copy), std::move(jac_copy)); + } + /// Construct a set of primary variables, each initialized to /// a given vector. static std::vector variables(const std::vector& initial_values)