Loading...
Searching...
No Matches
BlackoilWellModelNldd_impl.hpp
/*
Copyright 2016 - 2019 SINTEF Digital, Mathematics & Cybernetics.
Copyright 2016 - 2018 Equinor ASA.
Copyright 2017 Dr. Blatt - HPC-Simulation-Software & Services
Copyright 2016 - 2018 Norce AS
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 <http://www.gnu.org/licenses/>.
*/
#ifndef OPM_BLACKOILWELLMODEL_NLDD_IMPL_HEADER_INCLUDED
#define OPM_BLACKOILWELLMODEL_NLDD_IMPL_HEADER_INCLUDED
// Improve IDE experience
#ifndef OPM_BLACKOILWELLMODEL_NLDD_HEADER_INCLUDED
#include <config.h>
#include <opm/simulators/wells/BlackoilWellModelNldd.hpp>
#endif
#include <algorithm>
namespace Opm {
template<typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
assemble(const int /*iterationIdx*/,
const double dt,
const Domain& domain)
{
OPM_TIMEBLOCK(assemble);
// We assume that calculateExplicitQuantities() and
// prepareTimeStep() have been called already for the entire
// well model, so we do not need to do it here (when
// iterationIdx is 0).
DeferredLogger local_deferredLogger;
this->updateWellControls(local_deferredLogger, domain);
this->assembleWellEq(dt, domain, local_deferredLogger);
}
template<typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
assembleWellEq(const double dt,
const Domain& domain,
DeferredLogger& deferred_logger)
{
OPM_TIMEBLOCK(assembleWellEq);
for (const auto& well : wellModel_.localNonshutWells()) {
if (this->well_domain().at(well->name()) == domain.index) {
well->assembleWellEq(wellModel_.simulator(),
dt,
wellModel_.wellState(),
wellModel_.groupState(),
deferred_logger);
}
}
}
template<typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
addWellPressureEquations(PressureMatrix& /*jacobian*/,
const BVector& /*weights*/,
const bool /*use_well_weights*/,
const int /*domainIndex*/) const
{
throw std::logic_error("CPRW is not yet implemented for NLDD subdomains");
// To fix this function, rdofs should be the size of the domain, and the nw should be the number of wells in the domain
// int nw = this->numLocalWellsEnd(); // should number of wells in the domain
// int rdofs = local_num_cells_; // should be the size of the domain
// for ( int i = 0; i < nw; i++ ) {
// int wdof = rdofs + i;
// jacobian[wdof][wdof] = 1.0;// better scaling ?
// }
// for ( const auto& well : well_container_ ) {
// if (well_domain_.at(well->name()) == domainIndex) {
// weights should be the size of the domain
// well->addWellPressureEquations(jacobian, weights, pressureVarIndex, use_well_weights, this->wellState());
// }
// }
}
template<typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
recoverWellSolutionAndUpdateWellState(const BVector& x,
const int domainIdx)
{
// Note: no point in trying to do a parallel gathering
// try/catch here, as this function is not called in
// parallel but for each individual domain of each rank.
DeferredLogger local_deferredLogger;
for (const auto& well : wellModel_.localNonshutWells()) {
if (this->well_domain().at(well->name()) == domainIdx) {
const auto& cells = well->cells();
x_local_.resize(cells.size());
for (size_t i = 0; i < cells.size(); ++i) {
x_local_[i] = x[cells[i]];
}
well->recoverWellSolutionAndUpdateWellState(wellModel_.simulator(),
x_local_,
wellModel_.wellState(),
local_deferredLogger);
}
}
// TODO: avoid losing the logging information that could
// be stored in the local_deferredlogger in a parallel case.
if (wellModel_.terminalOutput()) {
local_deferredLogger.logMessages();
}
}
template<typename TypeTag>
ConvergenceReport
BlackoilWellModelNldd<TypeTag>::
getWellConvergence(const Domain& domain,
const std::vector<Scalar>& B_avg,
DeferredLogger& local_deferredLogger) const
{
const int iterationIdx = wellModel_.simulator().model().newtonMethod().numIterations();
const bool relax_tolerance = iterationIdx > wellModel_.numStrictIterations();
ConvergenceReport report;
for (const auto& well : wellModel_.localNonshutWells()) {
if ((this->well_domain().at(well->name()) == domain.index)) {
if (well->isOperableAndSolvable() || well->wellIsStopped()) {
report += well->getWellConvergence(wellModel_.simulator(),
wellModel_.wellState(),
B_avg,
local_deferredLogger,
relax_tolerance);
} else {
ConvergenceReport xreport;
using CR = ConvergenceReport;
xreport.setWellFailed({CR::WellFailure::Type::Unsolvable,
CR::Severity::Normal, -1, well->name()});
report += xreport;
}
}
}
// Log debug messages for NaN or too large residuals.
if (wellModel_.terminalOutput()) {
for (const auto& f : report.wellFailures()) {
if (f.severity() == ConvergenceReport::Severity::NotANumber) {
local_deferredLogger.debug("NaN residual found with phase " +
std::to_string(f.phase()) +
" for well " + f.wellName());
} else if (f.severity() == ConvergenceReport::Severity::TooLarge) {
local_deferredLogger.debug("Too large residual found with phase " +
std::to_string(f.phase()) +
" for well " + f.wellName());
}
}
}
return report;
}
template<typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
updateWellControls(DeferredLogger& deferred_logger,
const Domain& domain)
{
OPM_TIMEBLOCK(updateWellControls);
if (!wellModel_.wellsActive()) {
return;
}
// TODO: decide on and implement an approach to handling of
// group controls, network and similar for domain solves.
// Check only individual well constraints and communicate.
for (const auto& well : wellModel_.localNonshutWells()) {
if (this->well_domain().at(well->name()) == domain.index) {
constexpr auto mode = WellInterface<TypeTag>::IndividualOrGroup::Individual;
well->updateWellControl(wellModel_.simulator(),
mode,
wellModel_.wellState(),
wellModel_.groupState(),
deferred_logger);
}
}
}
template <typename TypeTag>
void
BlackoilWellModelNldd<TypeTag>::
setupDomains(const std::vector<Domain>& domains)
{
std::vector<const SubDomainIndices*> genDomains;
std::transform(domains.begin(), domains.end(),
std::back_inserter(genDomains),
[](const auto& domain)
{ return static_cast<const SubDomainIndices*>(&domain); });
this->calcDomains(genDomains);
}
} // namespace Opm
#endif
Opm::BlackoilWellModelNldd
Class for handling the blackoil well model in a NLDD solver.
Definition BlackoilWellModelNldd.hpp:80
Opm::ConvergenceReport
Represents the convergence status of the whole simulator, to make it possible to query and store the ...
Definition ConvergenceReport.hpp:38
Opm::DeferredLogger
Definition DeferredLogger.hpp:57
Opm
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition blackoilbioeffectsmodules.hh:43