mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
changed: do all assembleTracerEquations_() in one call
by looping over the tracer batches. this trades memory for runtime efficiency as we cannot reuse one matrix but rather need to have one matrix for each phase
This commit is contained in:
parent
2b2b0b085c
commit
83b7aec1f1
@ -214,7 +214,7 @@ doInit(bool rst, size_t numGridDof,
|
|||||||
tracerResidual_.resize(numGridDof);
|
tracerResidual_.resize(numGridDof);
|
||||||
|
|
||||||
// allocate matrix for storing the Jacobian of the tracer residual
|
// allocate matrix for storing the Jacobian of the tracer residual
|
||||||
tracerMatrix_ = new TracerMatrix(numGridDof, numGridDof, TracerMatrix::random);
|
tracerMatrix_ = std::make_unique<TracerMatrix>(numGridDof, numGridDof, TracerMatrix::random);
|
||||||
|
|
||||||
// find the sparsity pattern of the tracer matrix
|
// find the sparsity pattern of the tracer matrix
|
||||||
using NeighborSet = std::set<unsigned>;
|
using NeighborSet = std::set<unsigned>;
|
||||||
|
@ -103,7 +103,7 @@ protected:
|
|||||||
|
|
||||||
std::vector<int> tracerPhaseIdx_;
|
std::vector<int> tracerPhaseIdx_;
|
||||||
std::vector<Dune::BlockVector<Dune::FieldVector<Scalar, 1>>> tracerConcentration_;
|
std::vector<Dune::BlockVector<Dune::FieldVector<Scalar, 1>>> tracerConcentration_;
|
||||||
TracerMatrix *tracerMatrix_;
|
std::unique_ptr<TracerMatrix> tracerMatrix_;
|
||||||
TracerVector tracerResidual_;
|
TracerVector tracerResidual_;
|
||||||
std::vector<int> cartToGlobal_;
|
std::vector<int> cartToGlobal_;
|
||||||
std::vector<Dune::BlockVector<Dune::FieldVector<Scalar, 1>>> storageOfTimeIndex1_;
|
std::vector<Dune::BlockVector<Dune::FieldVector<Scalar, 1>>> storageOfTimeIndex1_;
|
||||||
|
@ -76,6 +76,7 @@ class EclTracerModel : public EclGenericTracerModel<GetPropType<TypeTag, Propert
|
|||||||
|
|
||||||
using TracerEvaluation = DenseAd::Evaluation<Scalar,1>;
|
using TracerEvaluation = DenseAd::Evaluation<Scalar,1>;
|
||||||
|
|
||||||
|
using TracerMatrix = typename BaseType::TracerMatrix;
|
||||||
using TracerVector = typename BaseType::TracerVector;
|
using TracerVector = typename BaseType::TracerVector;
|
||||||
|
|
||||||
enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
|
enum { numEq = getPropValue<TypeTag, Properties::NumEq>() };
|
||||||
@ -154,11 +155,22 @@ public:
|
|||||||
gas_.addTracer(tracerIdx, this->tracerConcentration_[tracerIdx]);
|
gas_.addTracer(tracerIdx, this->tracerConcentration_[tracerIdx]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// will be valid after we move out of tracerMatrix_
|
||||||
|
TracerMatrix* base = this->tracerMatrix_.get();
|
||||||
|
for (auto& tr : this->tbatch) {
|
||||||
|
if (tr.numTracer() != 0) {
|
||||||
|
if (this->tracerMatrix_)
|
||||||
|
tr.mat = std::move(this->tracerMatrix_);
|
||||||
|
else
|
||||||
|
tr.mat = std::make_unique<TracerMatrix>(*base);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void beginTimeStep()
|
void beginTimeStep()
|
||||||
{
|
{
|
||||||
if (this->numTracers()==0)
|
if (this->numTracers() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
updateStorageCache();
|
updateStorageCache();
|
||||||
@ -169,7 +181,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void endTimeStep()
|
void endTimeStep()
|
||||||
{
|
{
|
||||||
if (this->numTracers()==0)
|
if (this->numTracers() == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
advanceTracerFields();
|
advanceTracerFields();
|
||||||
@ -287,7 +299,7 @@ protected:
|
|||||||
Scalar localStorage = (storageOfTimeIndex0 - storageOfTimeIndex1[tIdx]) * scvVolume/dt;
|
Scalar localStorage = (storageOfTimeIndex0 - storageOfTimeIndex1[tIdx]) * scvVolume/dt;
|
||||||
tr.residual_[tIdx][I][0] += localStorage; //residual + flux
|
tr.residual_[tIdx][I][0] += localStorage; //residual + flux
|
||||||
}
|
}
|
||||||
(*this->tracerMatrix_)[I][I][0][0] += fVolume.derivative(0) * scvVolume/dt;
|
(*tr.mat)[I][I][0][0] += fVolume.derivative(0) * scvVolume/dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TrRe>
|
template<class TrRe>
|
||||||
@ -297,6 +309,9 @@ protected:
|
|||||||
unsigned I,
|
unsigned I,
|
||||||
unsigned J)
|
unsigned J)
|
||||||
{
|
{
|
||||||
|
if (tr.numTracer() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
TracerEvaluation flux;
|
TracerEvaluation flux;
|
||||||
bool isUpF;
|
bool isUpF;
|
||||||
computeFlux_(flux, isUpF, tr.phaseIdx_, elemCtx, scvfIdx, 0);
|
computeFlux_(flux, isUpF, tr.phaseIdx_, elemCtx, scvfIdx, 0);
|
||||||
@ -305,8 +320,8 @@ protected:
|
|||||||
tr.residual_[tIdx][I][0] += flux.value()*tr.concentration_[tIdx][globalUpIdx]; //residual + flux
|
tr.residual_[tIdx][I][0] += flux.value()*tr.concentration_[tIdx][globalUpIdx]; //residual + flux
|
||||||
}
|
}
|
||||||
if (isUpF) {
|
if (isUpF) {
|
||||||
(*this->tracerMatrix_)[J][I][0][0] = -flux.derivative(0);
|
(*tr.mat)[J][I][0][0] = -flux.derivative(0);
|
||||||
(*this->tracerMatrix_)[I][I][0][0] += flux.derivative(0);
|
(*tr.mat)[I][I][0][0] += flux.derivative(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -314,6 +329,9 @@ protected:
|
|||||||
void assembleTracerEquationWell(TrRe& tr,
|
void assembleTracerEquationWell(TrRe& tr,
|
||||||
const Well& well)
|
const Well& well)
|
||||||
{
|
{
|
||||||
|
if (tr.numTracer() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
const auto& eclWell = well.wellEcl();
|
const auto& eclWell = well.wellEcl();
|
||||||
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
|
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
|
||||||
this->wellTracerRate_[std::make_pair(eclWell.name(), this->name(tr.idx_[tIdx]))] = 0.0;
|
this->wellTracerRate_[std::make_pair(eclWell.name(), this->name(tr.idx_[tIdx]))] = 0.0;
|
||||||
@ -338,37 +356,40 @@ protected:
|
|||||||
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
|
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx) {
|
||||||
tr.residual_[tIdx][I][0] -= rate*tr.concentration_[tIdx][I];
|
tr.residual_[tIdx][I][0] -= rate*tr.concentration_[tIdx][I];
|
||||||
}
|
}
|
||||||
(*this->tracerMatrix_)[I][I][0][0] -= rate*variable<TracerEvaluation>(1.0, 0).derivative(0);
|
(*tr.mat)[I][I][0][0] -= rate*variable<TracerEvaluation>(1.0, 0).derivative(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class TrRe>
|
void assembleTracerEquations_()
|
||||||
void assembleTracerEquations_(TrRe & tr)
|
|
||||||
{
|
{
|
||||||
if (tr.numTracer() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Note that we formulate the equations in terms of a concentration update
|
// Note that we formulate the equations in terms of a concentration update
|
||||||
// (compared to previous time step) and not absolute concentration.
|
// (compared to previous time step) and not absolute concentration.
|
||||||
// This implies that current concentration (tr.concentration_[][]) contributes
|
// This implies that current concentration (tr.concentration_[][]) contributes
|
||||||
// to the rhs both through storrage and flux terms.
|
// to the rhs both through storrage and flux terms.
|
||||||
// Compare also advanceTracerFields(...) below.
|
// Compare also advanceTracerFields(...) below.
|
||||||
|
|
||||||
(*this->tracerMatrix_) = 0.0;
|
for (auto& tr : tbatch) {
|
||||||
for (int tIdx =0; tIdx < tr.numTracer(); ++tIdx)
|
if (tr.numTracer() != 0) {
|
||||||
|
(*tr.mat) = 0.0;
|
||||||
|
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx)
|
||||||
tr.residual_[tIdx] = 0.0;
|
tr.residual_[tIdx] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ElementContext elemCtx(simulator_);
|
ElementContext elemCtx(simulator_);
|
||||||
for (const auto& elem : elements(simulator_.gridView())) {
|
for (const auto& elem : elements(simulator_.gridView())) {
|
||||||
elemCtx.updateStencil(elem);
|
elemCtx.updateStencil(elem);
|
||||||
|
|
||||||
size_t I = elemCtx.globalSpaceIndex(/*dofIdx=*/ 0, /*timIdx=*/0);
|
size_t I = elemCtx.globalSpaceIndex(/*dofIdx=*/ 0, /*timeIdx=*/0);
|
||||||
|
|
||||||
if (elem.partitionType() != Dune::InteriorEntity)
|
if (elem.partitionType() != Dune::InteriorEntity)
|
||||||
{
|
{
|
||||||
// Dirichlet boundary conditions needed for the parallel matrix
|
// Dirichlet boundary conditions needed for the parallel matrix
|
||||||
(*this->tracerMatrix_)[I][I][0][0] = 1.;
|
for (auto& tr : tbatch) {
|
||||||
|
if (tr.numTracer() != 0)
|
||||||
|
(*tr.mat)[I][I][0][0] = 1.;
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
elemCtx.updateAllIntensiveQuantities();
|
elemCtx.updateAllIntensiveQuantities();
|
||||||
@ -384,31 +405,41 @@ protected:
|
|||||||
* extrusionFactor;
|
* extrusionFactor;
|
||||||
Scalar dt = elemCtx.simulator().timeStepSize();
|
Scalar dt = elemCtx.simulator().timeStepSize();
|
||||||
|
|
||||||
size_t I1 = elemCtx.globalSpaceIndex(/*dofIdx=*/ 0, /*timIdx=*/1);
|
size_t I1 = elemCtx.globalSpaceIndex(/*dofIdx=*/ 0, /*timeIdx=*/1);
|
||||||
|
|
||||||
|
for (auto& tr : tbatch) {
|
||||||
this->assembleTracerEquationVolume(tr, elemCtx, scvVolume, dt, I, I1);
|
this->assembleTracerEquationVolume(tr, elemCtx, scvVolume, dt, I, I1);
|
||||||
|
}
|
||||||
|
|
||||||
size_t numInteriorFaces = elemCtx.numInteriorFaces(/*timIdx=*/0);
|
size_t numInteriorFaces = elemCtx.numInteriorFaces(/*timIdx=*/0);
|
||||||
for (unsigned scvfIdx = 0; scvfIdx < numInteriorFaces; scvfIdx++) {
|
for (unsigned scvfIdx = 0; scvfIdx < numInteriorFaces; scvfIdx++) {
|
||||||
const auto& face = elemCtx.stencil(0).interiorFace(scvfIdx);
|
const auto& face = elemCtx.stencil(0).interiorFace(scvfIdx);
|
||||||
unsigned j = face.exteriorIndex();
|
unsigned j = face.exteriorIndex();
|
||||||
unsigned J = elemCtx.globalSpaceIndex(/*dofIdx=*/ j, /*timIdx=*/0);
|
unsigned J = elemCtx.globalSpaceIndex(/*dofIdx=*/ j, /*timIdx=*/0);
|
||||||
|
for (auto& tr : tbatch) {
|
||||||
this->assembleTracerEquationFlux(tr, elemCtx, scvfIdx, I, J);
|
this->assembleTracerEquationFlux(tr, elemCtx, scvfIdx, I, J);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Well terms
|
// Well terms
|
||||||
const auto& wellPtrs = simulator_.problem().wellModel().localNonshutWells();
|
const auto& wellPtrs = simulator_.problem().wellModel().localNonshutWells();
|
||||||
for (const auto& wellPtr : wellPtrs) {
|
for (const auto& wellPtr : wellPtrs) {
|
||||||
|
for (auto& tr : tbatch) {
|
||||||
this->assembleTracerEquationWell(tr, *wellPtr);
|
this->assembleTracerEquationWell(tr, *wellPtr);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Communicate overlap using grid Communication
|
// Communicate overlap using grid Communication
|
||||||
|
for (auto& tr : tbatch) {
|
||||||
|
if (tr.numTracer() == 0)
|
||||||
|
continue;
|
||||||
auto handle = VectorVectorDataHandle<GridView, std::vector<TracerVector>>(tr.residual_,
|
auto handle = VectorVectorDataHandle<GridView, std::vector<TracerVector>>(tr.residual_,
|
||||||
simulator_.gridView());
|
simulator_.gridView());
|
||||||
simulator_.gridView().communicate(handle, Dune::InteriorBorder_All_Interface,
|
simulator_.gridView().communicate(handle, Dune::InteriorBorder_All_Interface,
|
||||||
Dune::ForwardCommunication);
|
Dune::ForwardCommunication);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void updateStorageCache()
|
void updateStorageCache()
|
||||||
{
|
{
|
||||||
@ -436,6 +467,8 @@ protected:
|
|||||||
|
|
||||||
void advanceTracerFields()
|
void advanceTracerFields()
|
||||||
{
|
{
|
||||||
|
assembleTracerEquations_();
|
||||||
|
|
||||||
for (auto& tr : tbatch) {
|
for (auto& tr : tbatch) {
|
||||||
if (tr.numTracer() == 0)
|
if (tr.numTracer() == 0)
|
||||||
continue;
|
continue;
|
||||||
@ -446,9 +479,7 @@ protected:
|
|||||||
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx)
|
for (int tIdx = 0; tIdx < tr.numTracer(); ++tIdx)
|
||||||
dx[tIdx] = 0.0;
|
dx[tIdx] = 0.0;
|
||||||
|
|
||||||
assembleTracerEquations_(tr);
|
bool converged = this->linearSolveBatchwise_(*tr.mat, dx, tr.residual_);
|
||||||
|
|
||||||
bool converged = this->linearSolveBatchwise_(*this->tracerMatrix_, dx, tr.residual_);
|
|
||||||
if (!converged)
|
if (!converged)
|
||||||
std::cout << "### Tracer model: Warning, linear solver did not converge. ###" << std::endl;
|
std::cout << "### Tracer model: Warning, linear solver did not converge. ###" << std::endl;
|
||||||
|
|
||||||
@ -522,6 +553,7 @@ protected:
|
|||||||
std::vector<TV> concentration_;
|
std::vector<TV> concentration_;
|
||||||
std::vector<TV> storageOfTimeIndex1_;
|
std::vector<TV> storageOfTimeIndex1_;
|
||||||
std::vector<TV> residual_;
|
std::vector<TV> residual_;
|
||||||
|
std::unique_ptr<TracerMatrix> mat;
|
||||||
|
|
||||||
TracerBatch(int phaseIdx) : phaseIdx_(phaseIdx) {}
|
TracerBatch(int phaseIdx) : phaseIdx_(phaseIdx) {}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user