mirror of
https://github.com/OPM/opm-simulators.git
synced 2025-02-25 18:55:30 -06:00
and give warning messages when they happen, since they can be the culprits of the termination of simulation later. For ADB related, I did not find a good way to do the detection, so there is no warning message given.
239 lines
6.3 KiB
C++
239 lines
6.3 KiB
C++
/*
|
|
Copyright 2015 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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
|
|
#ifndef OPM_AUTODIFF_VFPHELPERSLEGACY_HPP_
|
|
#define OPM_AUTODIFF_VFPHELPERSLEGACY_HPP_
|
|
|
|
|
|
#include <opm/parser/eclipse/EclipseState/Schedule/VFPProdTable.hpp>
|
|
#include <opm/parser/eclipse/EclipseState/Schedule/VFPInjTable.hpp>
|
|
#include <opm/autodiff/AutoDiffHelpers.hpp>
|
|
|
|
/**
|
|
* This file contains a set of helper functions used by VFPProd / VFPInj.
|
|
*/
|
|
namespace Opm {
|
|
namespace detail {
|
|
|
|
|
|
typedef AutoDiffBlock<double> ADB;
|
|
|
|
|
|
/**
|
|
* * Returns zero for every entry in the ADB which is NaN or INF
|
|
* */
|
|
inline ADB zeroIfNanInf(const ADB& values) {
|
|
Selector<ADB::V::Scalar> not_nan_inf_selector(values.value(), Selector<ADB::V::Scalar>::NotNaNInf);
|
|
|
|
const ADB::V z = ADB::V::Zero(values.size());
|
|
const ADB zero = ADB::constant(z, values.blockPattern());
|
|
|
|
ADB retval = not_nan_inf_selector.select(values, zero);
|
|
return retval;
|
|
}
|
|
|
|
|
|
/**
|
|
* Sets block_pattern to be the "union of x.blockPattern() and block_pattern".
|
|
*/
|
|
inline void extendBlockPattern(const ADB& x, std::vector<int>& block_pattern) {
|
|
std::vector<int> x_block_pattern = x.blockPattern();
|
|
|
|
if (x_block_pattern.empty()) {
|
|
return;
|
|
}
|
|
else {
|
|
if (block_pattern.empty()) {
|
|
block_pattern = x_block_pattern;
|
|
return;
|
|
}
|
|
else {
|
|
if (x_block_pattern != block_pattern) {
|
|
OPM_THROW(std::logic_error, "Block patterns do not match");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
#include "VFPHelpers.hpp"
|
|
|
|
|
|
namespace Opm {
|
|
namespace detail {
|
|
|
|
/**
|
|
* Finds the common block pattern for all inputs
|
|
*/
|
|
inline std::vector<int> commonBlockPattern(
|
|
const ADB& x1,
|
|
const ADB& x2,
|
|
const ADB& x3,
|
|
const ADB& x4) {
|
|
std::vector<int> block_pattern;
|
|
|
|
extendBlockPattern(x1, block_pattern);
|
|
extendBlockPattern(x2, block_pattern);
|
|
extendBlockPattern(x3, block_pattern);
|
|
extendBlockPattern(x4, block_pattern);
|
|
|
|
return block_pattern;
|
|
}
|
|
|
|
inline std::vector<int> commonBlockPattern(
|
|
const ADB& x1,
|
|
const ADB& x2,
|
|
const ADB& x3,
|
|
const ADB& x4,
|
|
const ADB& x5) {
|
|
std::vector<int> block_pattern = commonBlockPattern(x1, x2, x3, x4);
|
|
extendBlockPattern(x5, block_pattern);
|
|
|
|
return block_pattern;
|
|
}
|
|
|
|
|
|
/**
|
|
* Returns the actual ADB for the type of FLO/GFR/WFR type
|
|
*/
|
|
template <typename TYPE>
|
|
ADB getValue(
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour, TYPE type);
|
|
|
|
template <>
|
|
inline
|
|
ADB getValue(
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour,
|
|
VFPProdTable::FLO_TYPE type) {
|
|
return detail::getFlo(aqua, liquid, vapour, type);
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
ADB getValue(
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour,
|
|
VFPProdTable::WFR_TYPE type) {
|
|
return detail::getWFR(aqua, liquid, vapour, type);
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
ADB getValue(
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour,
|
|
VFPProdTable::GFR_TYPE type) {
|
|
return detail::getGFR(aqua, liquid, vapour, type);
|
|
}
|
|
|
|
template <>
|
|
inline
|
|
ADB getValue(
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour,
|
|
VFPInjTable::FLO_TYPE type) {
|
|
return detail::getFlo(aqua, liquid, vapour, type);
|
|
}
|
|
|
|
/**
|
|
* Given m wells and n types of VFP variables (e.g., FLO = {FLO_OIL, FLO_LIQ}
|
|
* this function combines the n types of ADB objects, so that each of the
|
|
* m wells gets the right ADB.
|
|
* @param TYPE Type of variable to return, e.g., FLO_TYPE, WFR_TYPE, GFR_TYPE
|
|
* @param TABLE Type of table to use, e.g., VFPInjTable, VFPProdTable.
|
|
*/
|
|
template <typename TYPE, typename TABLE>
|
|
ADB combineADBVars(const std::vector<const TABLE*>& well_tables,
|
|
const ADB& aqua,
|
|
const ADB& liquid,
|
|
const ADB& vapour) {
|
|
|
|
const int num_wells = static_cast<int>(well_tables.size());
|
|
assert(aqua.size() == num_wells);
|
|
assert(liquid.size() == num_wells);
|
|
assert(vapour.size() == num_wells);
|
|
|
|
//Caching variable for flo/wfr/gfr
|
|
std::map<TYPE, ADB> map;
|
|
|
|
//Indexing variable used when combining the different ADB types
|
|
std::map<TYPE, std::vector<int> > elems;
|
|
|
|
//Compute all of the different ADB types,
|
|
//and record which wells use which types
|
|
for (int i=0; i<num_wells; ++i) {
|
|
const TABLE* table = well_tables[i];
|
|
|
|
//Only do something if this well is under THP control
|
|
if (table != NULL) {
|
|
TYPE type = getType<TYPE>(table);
|
|
|
|
//"Caching" of flo_type etc: Only calculate used types
|
|
//Create type if it does not exist
|
|
if (map.find(type) == map.end()) {
|
|
map.insert(std::pair<TYPE, ADB>(
|
|
type,
|
|
detail::getValue<TYPE>(aqua, liquid, vapour, type)
|
|
));
|
|
}
|
|
|
|
//Add the index for assembly later in gather_vars
|
|
elems[type].push_back(i);
|
|
}
|
|
}
|
|
|
|
//Loop over all types of ADB variables, and combine them
|
|
//so that each well gets the proper variable
|
|
ADB retval = ADB::constant(ADB::V::Zero(num_wells));
|
|
for (const auto& entry : elems) {
|
|
const auto& key = entry.first;
|
|
const auto& value = entry.second;
|
|
|
|
//Get the ADB for this type of variable
|
|
assert(map.find(key) != map.end());
|
|
const ADB& values = map.find(key)->second;
|
|
|
|
//Get indices to all elements that should use this ADB
|
|
const std::vector<int>& current = value;
|
|
|
|
//Add these elements to retval
|
|
retval = retval + superset(subset(values, current), current, values.size());
|
|
}
|
|
|
|
return retval;
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
#endif /* OPM_AUTODIFF_VFPHELPERSLEGACY_HPP_ */
|