Add support for NNC in the simulator

1) NNC are added the grad, div and average operators
2) NNC are added the upwindSelector
3) NNC transmissibilities are added to the face transmissibilities
This commit is contained in:
Tor Harald Sandve 2015-06-10 09:25:45 +02:00
parent 85fe3d6ad2
commit 065b2f595c
5 changed files with 135 additions and 8 deletions

View File

@ -1,5 +1,6 @@
/*
Copyright 2013 SINTEF ICT, Applied Mathematics.
Copyright 2015 IRIS
This file is part of the Open Porous Media project (OPM).
@ -24,7 +25,8 @@
#include <opm/autodiff/GridHelpers.hpp>
#include <opm/core/grid.h>
#include <opm/core/utility/ErrorMacros.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <iostream>
#include <vector>
@ -58,6 +60,109 @@ struct HelperOps
/// Extract for each cell the sum of all its adjacent faces' (signed) values.
M fulldiv;
/// Non-neighboring connections
typedef Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor> TwoColInt;
TwoColInt nnc_cells;
/// The NNC transmissibilities
V nnc_trans;
/// Constructs all helper vectors and matrices.
template<class Grid>
HelperOps(const Grid& grid, Opm::EclipseStateConstPtr eclState)
{
using namespace AutoDiffGrid;
const int nc = numCells(grid);
const int nf = numFaces(grid);
// Define some neighbourhood-derived helper arrays.
TwoColInt nbi;
extractInternalFaces(grid, internal_faces, nbi);
int num_internal=internal_faces.size();
// num_connections may also include non-neighboring connections
int num_connections = num_internal;
int numNNC = 0;
// handle non-neighboring connections
std::shared_ptr<const NNC> nnc = eclState->getNNC();
if (nnc->hasNNC()) {
numNNC = nnc->numNNC();
num_connections += numNNC;
//std::cout << "Added " << numNNC << " NNC" <<std::endl;
nbi.resize(num_internal, 2);
// the nnc's acts on global indicies and must be mapped to cell indicies
size_t cartesianSize = eclState->getEclipseGrid()->getCartesianSize();
std::vector<int> global2localIdx(cartesianSize,0);
for (int i = 0; i< nc; ++i) {
global2localIdx[grid.global_cell[i]] = i;
}
const std::vector<size_t>& NNC1 = nnc->nnc1();
const std::vector<size_t>& NNC2 = nnc->nnc2();
nnc_cells.resize(numNNC,2);
for (int i = 0; i < numNNC; ++i) {
nnc_cells(i,0) = global2localIdx[NNC1[i]];
nnc_cells(i,1) = global2localIdx[NNC2[i]];
}
// store the nnc transmissibilities for later usage.
nnc_trans = Eigen::Map<const V>(nnc->trans().data(), numNNC);
} else {
nnc_trans.resize(0);
nnc_cells.resize(0,0);
}
// std::cout << "nbi = \n" << nbi << std::endl;
// Create matrices.
ngrad.resize(num_connections, nc);
caver.resize(num_connections, nc);
typedef Eigen::Triplet<double> Tri;
std::vector<Tri> ngrad_tri;
std::vector<Tri> caver_tri;
ngrad_tri.reserve(2*num_connections);
caver_tri.reserve(2*num_connections);
for (int i = 0; i < num_internal; ++i) {
ngrad_tri.emplace_back(i, nbi(i,0), 1.0);
ngrad_tri.emplace_back(i, nbi(i,1), -1.0);
caver_tri.emplace_back(i, nbi(i,0), 0.5);
caver_tri.emplace_back(i, nbi(i,1), 0.5);
}
// add contribution from NNC
if (nnc->hasNNC()) {
for (int i = 0; i < numNNC; ++i) {
ngrad_tri.emplace_back(i+num_internal, nnc_cells(i,0), 1.0);
ngrad_tri.emplace_back(i+num_internal, nnc_cells(i,1), -1.0);
caver_tri.emplace_back(i+num_internal, nnc_cells(i,0), 0.5);
caver_tri.emplace_back(i+num_internal, nnc_cells(i,1), 0.5);
}
}
ngrad.setFromTriplets(ngrad_tri.begin(), ngrad_tri.end());
caver.setFromTriplets(caver_tri.begin(), caver_tri.end());
grad = -ngrad;
div = ngrad.transpose();
std::vector<Tri> fullngrad_tri;
fullngrad_tri.reserve(2*(nf+numNNC));
typename ADFaceCellTraits<Grid>::Type nb=faceCellsToEigen(grid);
for (int i = 0; i < nf; ++i) {
if (nb(i,0) >= 0) {
fullngrad_tri.emplace_back(i, nb(i,0), 1.0);
}
if (nb(i,1) >= 0) {
fullngrad_tri.emplace_back(i, nb(i,1), -1.0);
}
}
// add contribution from NNC
if (nnc->hasNNC()) {
for (int i = 0; i < numNNC; ++i) {
fullngrad_tri.emplace_back(i+nf, nnc_cells(i,0), 1.0);
fullngrad_tri.emplace_back(i+nf, nnc_cells(i,1), -1.0);
}
}
fullngrad.resize(nf+numNNC, nc);
fullngrad.setFromTriplets(fullngrad_tri.begin(), fullngrad_tri.end());
fulldiv = fullngrad.transpose();
}
/// Constructs all helper vectors and matrices.
template<class Grid>
HelperOps(const Grid& grid)
@ -66,7 +171,7 @@ struct HelperOps
const int nc = numCells(grid);
const int nf = numFaces(grid);
// Define some neighbourhood-derived helper arrays.
typedef Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor> TwoColInt;
//typedef Eigen::Array<int, Eigen::Dynamic, 2, Eigen::RowMajor> TwoColInt;
TwoColInt nbi;
extractInternalFaces(grid, internal_faces, nbi);
int num_internal=internal_faces.size();
@ -127,11 +232,15 @@ struct HelperOps
const IFIndex nif = h.internal_faces.size();
typename ADFaceCellTraits<Grid>::Type
face_cells = faceCellsToEigen(g);
assert(nif == ifaceflux.size());
// num connections may possibly include NNCs
size_t num_nnc = h.nnc_trans.size();
size_t num_connections= nif + num_nnc;
assert(num_connections == ifaceflux.size());
// Define selector structure.
typedef typename Eigen::Triplet<Scalar> Triplet;
std::vector<Triplet> s; s.reserve(nif);
std::vector<Triplet> s; s.reserve(num_connections);
for (IFIndex iface = 0; iface < nif; ++iface) {
const int f = h.internal_faces[iface];
const int c1 = face_cells(f,0);
@ -144,9 +253,15 @@ struct HelperOps
s.push_back(Triplet(iface, c, Scalar(1)));
}
if (num_nnc>0) {
for (int i = 0; i<num_nnc; ++i) {
const int c = (ifaceflux[i+nif] >= 0) ? h.nnc_cells(i,0) : h.nnc_cells(i,1);
s.push_back(Triplet(i+nif,c,Scalar(1)));
}
}
// Assemble explicit selector operator.
select_.resize(nif, numCells(g));
select_.resize(num_connections, numCells(g));
select_.setFromTriplets(s.begin(), s.end());
}

View File

@ -55,6 +55,7 @@ namespace Opm {
/// \param[in] rock_comp_props if non-null, rock compressibility properties
/// \param[in] wells well structure
/// \param[in] linsolver linear solver
/// \param[in] eclState eclipse state
/// \param[in] has_disgas turn on dissolved gas
/// \param[in] has_vapoil turn on vaporized oil feature
/// \param[in] terminal_output request output to cout/cerr
@ -65,11 +66,12 @@ namespace Opm {
const RockCompressibility* rock_comp_props,
const Wells* wells,
const NewtonIterationBlackoilInterface& linsolver,
Opm::EclipseStateConstPtr eclState,
const bool has_disgas,
const bool has_vapoil,
const bool terminal_output)
: Base(param, grid, fluid, geo, rock_comp_props, wells, linsolver,
has_disgas, has_vapoil, terminal_output)
eclState, has_disgas, has_vapoil, terminal_output)
{
}
};

View File

@ -31,6 +31,7 @@
#include <opm/autodiff/LinearisedBlackoilResidual.hpp>
#include <opm/autodiff/NewtonIterationBlackoilInterface.hpp>
#include <opm/autodiff/BlackoilModelEnums.hpp>
#include <opm/parser/eclipse/EclipseState/Grid/NNC.hpp>
#include <array>
@ -117,6 +118,7 @@ namespace Opm {
/// \param[in] rock_comp_props if non-null, rock compressibility properties
/// \param[in] wells well structure
/// \param[in] linsolver linear solver
/// \param[in] eclState eclipse state
/// \param[in] has_disgas turn on dissolved gas
/// \param[in] has_vapoil turn on vaporized oil feature
/// \param[in] terminal_output request output to cout/cerr
@ -127,6 +129,7 @@ namespace Opm {
const RockCompressibility* rock_comp_props,
const Wells* wells,
const NewtonIterationBlackoilInterface& linsolver,
Opm::EclipseStateConstPtr eclState,
const bool has_disgas,
const bool has_vapoil,
const bool terminal_output);

View File

@ -42,6 +42,7 @@
#include <opm/core/utility/Units.hpp>
#include <opm/core/well_controls.h>
#include <opm/core/utility/parameters/ParameterGroup.hpp>
#include <opm/parser/eclipse/EclipseState/EclipseState.hpp>
#include <cassert>
#include <cmath>
@ -144,6 +145,7 @@ namespace detail {
const RockCompressibility* rock_comp_props,
const Wells* wells,
const NewtonIterationBlackoilInterface& linsolver,
Opm::EclipseStateConstPtr eclState,
const bool has_disgas,
const bool has_vapoil,
const bool terminal_output)
@ -156,7 +158,7 @@ namespace detail {
, active_(detail::activePhases(fluid.phaseUsage()))
, canph_ (detail::active2Canonical(fluid.phaseUsage()))
, cells_ (detail::buildAllCells(Opm::AutoDiffGrid::numCells(grid)))
, ops_ (grid)
, ops_ (grid, eclState)
, wops_ (wells_)
, has_disgas_(has_disgas)
, has_vapoil_(has_vapoil)
@ -837,9 +839,13 @@ namespace detail {
// Set up the common parts of the mass balance equations
// for each active phase.
const V transi = subset(geo_.transmissibility(), ops_.internal_faces);
const V trans_nnc = ops_.nnc_trans;
V trans_all(transi.size() + trans_nnc.size());
trans_all << transi, trans_nnc;
const std::vector<ADB> kr = computeRelPerm(state);
for (int phaseIdx = 0; phaseIdx < fluid_.numPhases(); ++phaseIdx) {
asImpl().computeMassFlux(phaseIdx, transi, kr[canph_[phaseIdx]], state.canonical_phase_pressures[canph_[phaseIdx]], state);
asImpl().computeMassFlux(phaseIdx, trans_all, kr[canph_[phaseIdx]], state.canonical_phase_pressures[canph_[phaseIdx]], state);
residual_.material_balance_eq[ phaseIdx ] =
pvdt_ * (rq_[phaseIdx].accum[1] - rq_[phaseIdx].accum[0])

View File

@ -341,6 +341,7 @@ namespace Opm
rock_comp_props_,
wells,
solver_,
eclipse_state_,
has_disgas_,
has_vapoil_,
terminal_output_));