changed: ewoms/common -> opm/models/utils

This commit is contained in:
Arne Morten Kvarving 2019-09-16 10:40:08 +02:00
parent e37cbe32d6
commit e01f712294
67 changed files with 5052 additions and 61 deletions

View File

@ -32,7 +32,7 @@
#include <opm/material/common/quad.hpp>
#endif
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/flash/flashmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionflash.hh"

View File

@ -29,7 +29,7 @@
#include "config.h"
#include <opm/material/common/quad.hpp>
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/flash/flashmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionflash.hh"

View File

@ -29,7 +29,7 @@
#include "config.h"
#include <opm/material/common/quad.hpp>
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/flash/flashmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/co2injectionflash.hh"

View File

@ -32,7 +32,7 @@
#include <opm/material/common/quad.hpp>
#endif
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/flash/flashmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/co2injectionflash.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/co2injectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/cuvetteproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/flash/flashmodel.hh>
#include "problems/diffusionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include "problems/diffusionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/diffusionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/fingerproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include "problems/fractureproblem.hh"
int main(int argc, char **argv)

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/groundwaterproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/infiltrationproblem.hh"

View File

@ -30,7 +30,7 @@
#include "lens_immiscible_ecfv_ad.hh"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
int main(int argc, char **argv)
{

View File

@ -82,7 +82,7 @@ public:
END_PROPERTIES
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
int main(int argc, char **argv)
{

View File

@ -36,7 +36,7 @@
#include "lens_immiscible_ecfv_ad.hh"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
// fake forward declaration to prevent esoteric compiler warning
int mainCU1(int argc, char **argv);

View File

@ -36,7 +36,7 @@
#include "lens_immiscible_ecfv_ad.hh"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
// fake forward declaration to prevent esoteric compiler warning
int mainCU2(int argc, char **argv);

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/lensproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/lensproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/richardslensproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/richardslensproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/obstacleproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include "problems/obstacleproblem.hh"

View File

@ -29,7 +29,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/obstacleproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/outflowproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/powerinjectionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/powerinjectionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/powerinjectionproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/immiscible/immisciblemodel.hh>
#include "problems/powerinjectionproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/blackoil/blackoilmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/reservoirproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/blackoil/blackoilmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/reservoirproblem.hh"

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/ecfv/ecfvdiscretization.hh>
#include "problems/reservoirproblem.hh"

View File

@ -28,7 +28,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/ncp/ncpmodel.hh>
#include <ewoms/disc/vcfv/vcfvdiscretization.hh>
#include "problems/reservoirproblem.hh"

View File

@ -27,7 +27,7 @@
* immisciblility.
*/
#include "config.h" /*@\label{tutorial1:include-begin}@*/
#include <ewoms/common/start.hh> /*@\label{tutorial1:include-end}@*/
#include <opm/models/utils/start.hh> /*@\label{tutorial1:include-end}@*/
#include "tutorial1problem.hh" /*@\label{tutorial1:include-problem-header}@*/
int main(int argc, char **argv)

View File

@ -27,7 +27,7 @@
*/
#include "config.h"
#include <ewoms/common/start.hh>
#include <opm/models/utils/start.hh>
#include <ewoms/models/pvs/pvsmodel.hh>
#include "problems/waterairproblem.hh"

View File

@ -31,8 +31,8 @@
#include <omp.h>
#endif
#include <ewoms/common/parametersystem.hh>
#include <ewoms/common/propertysystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/material/common/Exceptions.hpp>

View File

@ -0,0 +1,226 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \brief This is a stand-alone version of boost::alignment::aligned_allocator from Boost
* 1.58
*
* The file has been modified to assume a C++-2011 compatible compiler on a POSIX
* operating system to remove the boost dependencies which the original version
* contained. The original copyright notice for this file is:
*
<pre>
(c) 2014 Glen Joseph Fernandes
glenjofe at gmail dot com
Distributed under the Boost Software
License, Version 1.0.
http://boost.org/LICENSE_1_0.txt
</pre>
*/
#ifndef EWOMS_ALIGNED_ALLOCATOR_HH
#define EWOMS_ALIGNED_ALLOCATOR_HH
#include <utility>
#include <memory>
#include <type_traits>
#include <cassert>
namespace Opm {
namespace detail {
constexpr inline bool is_alignment(std::size_t value) noexcept
{
return (value > 0) && ((value & (value - 1)) == 0);
}
template<std::size_t N>
struct is_alignment_constant
: std::integral_constant<bool, (N > 0) && ((N & (N - 1)) == 0)>
{};
template<std::size_t A, std::size_t B>
struct min_size
: std::integral_constant<std::size_t, (A < B) ? A : B>
{ };
template<class T>
struct offset_object
{
char offset;
T object;
};
template<class T>
struct alignment_of
: min_size<sizeof(T), sizeof(offset_object<T>) - sizeof(T)>::type
{};
template<std::size_t A, std::size_t B>
struct max_align
: std::integral_constant<std::size_t,(A > B) ? A : B>
{};
template<class T>
struct max_count_of
: std::integral_constant<std::size_t, ~static_cast<std::size_t>(0) / sizeof(T)>
{};
using std::addressof;
}
inline void* aligned_alloc(std::size_t alignment,
std::size_t size) noexcept
{
assert(detail::is_alignment(alignment));
if (alignment < sizeof(void*)) {
alignment = sizeof(void*);
}
void* p;
if (::posix_memalign(&p, alignment, size) != 0) {
p = 0;
}
return p;
}
inline void aligned_free(void* ptr)
noexcept
{
::free(ptr);
}
template<class T, std::size_t Alignment>
class aligned_allocator {
static_assert(detail::is_alignment_constant<Alignment>::value, "Alignment must be powers of two!");
public:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef void* void_pointer;
typedef const void* const_void_pointer;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
typedef T& reference;
typedef const T& const_reference;
private:
typedef detail::max_align<Alignment, detail::alignment_of<value_type>::value> MaxAlign;
public:
template<class U>
struct rebind {
typedef aligned_allocator<U, Alignment> other;
};
aligned_allocator()
noexcept = default;
template<class U>
aligned_allocator(const aligned_allocator<U,
Alignment>&) noexcept {
}
pointer address(reference value) const
noexcept {
return detail::addressof(value);
}
const_pointer address(const_reference value) const
noexcept {
return detail::addressof(value);
}
pointer allocate(size_type size,
const_void_pointer = 0) {
void* p = aligned_alloc(MaxAlign::value,
sizeof(T) * size);
if (!p && size > 0) {
throw std::bad_alloc();
}
return static_cast<T*>(p);
}
void deallocate(pointer ptr, size_type) {
aligned_free(ptr);
}
constexpr size_type max_size() const
noexcept {
return detail::max_count_of<T>::value;
}
template<class U, class... Args>
void construct(U* ptr, Args&&... args) {
void* p = ptr;
::new(p) U(std::forward<Args>(args)...);
}
template<class U>
void construct(U* ptr) {
void* p = ptr;
::new(p) U();
}
template<class U>
void destroy(U* ptr) {
(void)ptr;
ptr->~U();
}
};
template<std::size_t Alignment>
class aligned_allocator<void, Alignment> {
static_assert(detail::is_alignment_constant<Alignment>::value,
"The specified alignment is not a power of two!");
public:
typedef void value_type;
typedef void* pointer;
typedef const void* const_pointer;
template<class U>
struct rebind {
typedef aligned_allocator<U, Alignment> other;
};
};
template<class T1, class T2, std::size_t Alignment>
inline bool operator==(const aligned_allocator<T1,
Alignment>&, const aligned_allocator<T2,
Alignment>&) noexcept
{
return true;
}
template<class T1, class T2, std::size_t Alignment>
inline bool operator!=(const aligned_allocator<T1,
Alignment>&, const aligned_allocator<T2,
Alignment>&) noexcept
{
return false;
}
}
#endif

View File

@ -0,0 +1,191 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \brief Defines a type tags and some fundamental properties all models.
*/
#ifndef EWOMS_BASIC_PROPERTIES_HH
#define EWOMS_BASIC_PROPERTIES_HH
#include <dune/common/parametertree.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <ewoms/io/dgfvanguard.hh>
#if HAVE_DUNE_FEM
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>
#endif
#include <string>
BEGIN_PROPERTIES
///////////////////////////////////
// Type tag definitions:
//
// NumericModel
// |
// +-> ImplicitModel
///////////////////////////////////
//! Type tag for all models.
NEW_TYPE_TAG(NumericModel, INHERITS_FROM(ParameterSystem));
//! Type tag for all fully coupled models.
NEW_TYPE_TAG(ImplicitModel, INHERITS_FROM(NumericModel));
///////////////////////////////////
// Property names which are always available:
//
// Scalar
///////////////////////////////////
//! Property to specify the type of scalar values.
NEW_PROP_TAG(Scalar);
//! Property which provides a Dune::ParameterTree.
NEW_PROP_TAG(ParameterTree);
//! Property which defines the group that is queried for parameters by default
NEW_PROP_TAG(ModelParameterGroup);
//! Property which provides a Vanguard (manages grids)
NEW_PROP_TAG(Vanguard);
NEW_PROP_TAG(GridView);
#if HAVE_DUNE_FEM
NEW_PROP_TAG(GridPart);
#endif
//! Property which tells the Vanguard how often the grid should be refined
//! after creation.
NEW_PROP_TAG(GridGlobalRefinements);
//! Property provides the name of the file from which the additional runtime
//! parameters should to be loaded from
NEW_PROP_TAG(ParameterFile);
/*!
* \brief Print all properties on startup?
*
* 0 means 'no', 1 means 'yes', 2 means 'print only to logfiles'. The
* default is 2.
*/
NEW_PROP_TAG(PrintProperties);
/*!
* \brief Print all parameters on startup?
*
* 0 means 'no', 1 means 'yes', 2 means 'print only to logfiles'. The
* default is 2.
*/
NEW_PROP_TAG(PrintParameters);
//! The default value for the simulation's end time
NEW_PROP_TAG(EndTime);
//! The default value for the simulation's initial time step size
NEW_PROP_TAG(InitialTimeStepSize);
//! The default value for the simulation's restart time
NEW_PROP_TAG(RestartTime);
//! The name of the file with a number of forced time step lengths
NEW_PROP_TAG(PredeterminedTimeStepsFile);
///////////////////////////////////
// Values for the properties
///////////////////////////////////
//! Set the default type of scalar values to double
SET_TYPE_PROP(NumericModel, Scalar, double);
//! Set the ParameterTree property
SET_PROP(NumericModel, ParameterTree)
{
typedef Dune::ParameterTree type;
static Dune::ParameterTree& tree()
{
static Dune::ParameterTree obj_;
return obj_;
}
};
//! use the global group as default for the model's parameter group
SET_STRING_PROP(NumericModel, ModelParameterGroup, "");
//! Use the DgfVanguard by default
SET_TYPE_PROP(NumericModel, Vanguard, Opm::DgfVanguard<TypeTag>);
//! Set a value for the GridFile property
SET_STRING_PROP(NumericModel, GridFile, "");
#if HAVE_DUNE_FEM
SET_PROP(NumericModel, GridPart)
{
typedef typename GET_PROP_TYPE(TypeTag, Grid) Grid;
typedef Dune::Fem::AdaptiveLeafGridPart<Grid> type;
};
SET_TYPE_PROP(NumericModel, GridView, typename GET_PROP_TYPE(TypeTag, GridPart)::GridViewType);
#else
//! Use the leaf grid view by default.
//!
//! Except for spatial refinement, there is rarly a reason to use
//! anything else...
SET_TYPE_PROP(NumericModel, GridView, typename GET_PROP_TYPE(TypeTag, Grid)::LeafGridView);
#endif
//! Set a value for the ParameterFile property
SET_STRING_PROP(NumericModel, ParameterFile, "");
//! Set the number of refinement levels of the grid to 0. This does not belong
//! here, strictly speaking.
SET_INT_PROP(NumericModel, GridGlobalRefinements, 0);
//! By default, print the properties on startup
SET_INT_PROP(NumericModel, PrintProperties, 2);
//! By default, print the values of the run-time parameters on startup
SET_INT_PROP(NumericModel, PrintParameters, 2);
//! The default value for the simulation's end time
SET_SCALAR_PROP(NumericModel, EndTime, -1e35);
//! The default value for the simulation's initial time step size
SET_SCALAR_PROP(NumericModel, InitialTimeStepSize, -1e35);
//! The default value for the simulation's restart time
SET_SCALAR_PROP(NumericModel, RestartTime, -1e35);
//! By default, do not force any time steps
SET_STRING_PROP(NumericModel, PredeterminedTimeStepsFile, "");
END_PROPERTIES
#endif

View File

@ -0,0 +1,93 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::GenericGuard
*/
#ifndef EWOMS_GENERIC_GUARD_HH
#define EWOMS_GENERIC_GUARD_HH
namespace Opm {
/*!
* \ingroup Common
*
* \brief A simple class which makes sure that a cleanup function is called once the
* object is destroyed.
*
* This class is particularly useful in conjunction with lambdas for code that might
* throw exceptions.
*/
template <class Callback>
class GenericGuard
{
public:
GenericGuard(Callback& callback)
: callback_(callback)
, isEnabled_(true)
{ }
// allow moves
GenericGuard(GenericGuard&& other)
: callback_(other.callback_)
, isEnabled_(other.isEnabled_)
{
other.isEnabled_ = false;
}
// disable copies
GenericGuard(const GenericGuard& other) = delete;
~GenericGuard()
{
if (isEnabled_)
callback_();
}
/*!
* \brief Specify whether the guard object is "on duty" or not.
*
* If the guard object is destroyed while it is "off-duty", the cleanup callback is
* not called. At construction, guards are on duty.
*/
void setEnabled(bool value)
{ isEnabled_ = value; }
/*!
* \brief Returns whether the guard object is "on duty" or not.
*/
bool enabled() const
{ return isEnabled_; }
private:
Callback& callback_;
bool isEnabled_;
};
template <class Callback>
GenericGuard<Callback> make_guard(Callback& callback)
{ return GenericGuard<Callback>(callback); }
} // namespace Opm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,142 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \copydoc PffGridVector
*/
#ifndef EWOMS_PFF_GRID_VECTOR_HH
#define EWOMS_PFF_GRID_VECTOR_HH
#include <opm/models/utils/prefetch.hh>
#include <dune/grid/common/mcmgmapper.hh>
#include <dune/common/version.hh>
#include <vector>
namespace Opm {
/*!
* \brief A random-access container which stores data attached to a grid's degrees of
* freedom in a prefetch friendly manner.
*
* This container often reduces the number of cache faults considerably, thus improving
* performance. On the flipside data cannot be written to on an individual basis and it
* requires significantly more memory than a plain array. PffVector stands for "PreFetch
* Friendly Grid Vector".
*/
template <class GridView, class Stencil, class Data, class DofMapper>
class PffGridVector
{
typedef typename GridView::template Codim<0>::Entity Element;
#if DUNE_VERSION_NEWER(DUNE_GRID, 2,6)
typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView> ElementMapper;
#else
typedef Dune::MultipleCodimMultipleGeomTypeMapper<GridView, Dune::MCMGElementLayout> ElementMapper;
#endif
public:
PffGridVector(const GridView& gridView, const DofMapper& dofMapper)
: gridView_(gridView)
#if DUNE_VERSION_NEWER(DUNE_GRID, 2,6)
, elementMapper_(gridView_, Dune::mcmgElementLayout())
#else
, elementMapper_(gridView_)
#endif
, dofMapper_(dofMapper)
{ }
template <class DistFn>
void update(const DistFn& distFn)
{
unsigned numElements = gridView_.size(/*codim=*/0);
unsigned numLocalDofs = computeNumLocalDofs_();
elemData_.resize(numElements);
data_.resize(numLocalDofs);
// update the pointers for the element data: for this, we need to loop over the
// whole grid and update a stencil for each element
Data *curElemDataPtr = &data_[0];
Stencil stencil(gridView_, dofMapper_);
auto elemIt = gridView_.template begin</*codim=*/0>();
const auto& elemEndIt = gridView_.template end</*codim=*/0>();
for (; elemIt != elemEndIt; ++elemIt) {
// set the DOF data pointer for the current element
const auto& elem = *elemIt;
unsigned elemIdx = elementMapper_.index(elem);
elemData_[elemIdx] = curElemDataPtr;
stencil.update(elem);
unsigned numDof = stencil.numDof();
for (unsigned localDofIdx = 0; localDofIdx < numDof; ++ localDofIdx)
distFn(curElemDataPtr[localDofIdx], stencil, localDofIdx);
// update the element data pointer to make it point to the beginning of the
// data for DOFs of the next element
curElemDataPtr += numDof;
}
}
void prefetch(const Element& elem) const
{
unsigned elemIdx = elementMapper_.index(elem);
// we use 0 as the temporal locality, because it is reasonable to assume that an
// entry will only be accessed once.
Opm::prefetch</*temporalLocality=*/0>(elemData_[elemIdx]);
}
const Data& get(const Element& elem, unsigned localDofIdx) const
{
unsigned elemIdx = elementMapper_.index(elem);
return elemData_[elemIdx][localDofIdx];
}
private:
unsigned computeNumLocalDofs_() const
{
unsigned result = 0;
// loop over the whole grid and sum up the number of local DOFs of all Stencils
Stencil stencil(gridView_, dofMapper_);
auto elemIt = gridView_.template begin</*codim=*/0>();
const auto& elemEndIt = gridView_.template end</*codim=*/0>();
for (; elemIt != elemEndIt; ++elemIt) {
stencil.update(*elemIt);
result += stencil.numDof();
}
return result;
}
GridView gridView_;
ElementMapper elementMapper_;
const DofMapper& dofMapper_;
std::vector<Data> data_;
std::vector<Data*> elemData_;
};
} // namespace Opm
#endif

View File

@ -0,0 +1,54 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \copydoc prefetch
*/
#ifndef EWOMS_PREFETCH_HH
#define EWOMS_PREFETCH_HH
namespace Opm {
/*!
* \brief Template function which emits prefetch instructions for a range of memory
*
* This function does not change the semantics of the code, but used correctly it will
* improve performace because the number of cache misses will be reduced.
*/
template <int temporalLocality = 3, int writeOnly = 0, class T = void>
void prefetch(const T& val, unsigned n = 1)
{
#if __clang__ || __GNUC__
// this value is architecture specific, but a cache line size of 64 bytes seems to be
// used by all contemporary architectures.
static const int cacheLineSize = 64;
const char *beginPtr = reinterpret_cast<const char*>(&val);
const char *endPtr = reinterpret_cast<const char*>(&val + n);
for (; beginPtr < endPtr; beginPtr += cacheLineSize)
__builtin_prefetch(beginPtr, writeOnly, temporalLocality);
#endif
}
} // namespace Opm
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,154 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \copydoc Opm::QuadrialteralQuadratureGeometry
*/
#ifndef EWOMS_QUADRATURE_GEOMETRIES_HH
#define EWOMS_QUADRATURE_GEOMETRIES_HH
#include <dune/common/fvector.hh>
#include <dune/common/fmatrix.hh>
#include <dune/geometry/type.hh>
namespace Opm {
/*!
* \brief Quadrature geometry for quadrilaterals.
*/
template <class Scalar, unsigned dim>
class QuadrialteralQuadratureGeometry
{
public:
enum { numCorners = (1 << dim) };
typedef Dune::FieldVector<Scalar, dim> LocalPosition;
typedef Dune::FieldVector<Scalar, dim> GlobalPosition;
Dune::GeometryType type() const
{ return Dune::GeometryType(/*topologyId=*/(1 << dim) - 1, dim); }
template <class CornerContainer>
void setCorners(const CornerContainer& corners, unsigned nCorners)
{
unsigned cornerIdx;
for (cornerIdx = 0; cornerIdx < nCorners; ++cornerIdx) {
for (unsigned j = 0; j < dim; ++j)
corners_[cornerIdx][j] = corners[cornerIdx][j];
}
assert(cornerIdx == nCorners);
center_ = 0;
for (cornerIdx = 0; cornerIdx < nCorners; ++cornerIdx)
center_ += corners_[cornerIdx];
center_ /= nCorners;
}
/*!
* \brief Returns the center of weight of the polyhedron.
*/
const GlobalPosition& center() const
{ return center_; }
/*!
* \brief Convert a local coordinate into a global one.
*/
GlobalPosition global(const LocalPosition& localPos) const
{
GlobalPosition globalPos(0.0);
for (unsigned cornerIdx = 0; cornerIdx < numCorners; ++cornerIdx)
globalPos.axpy(cornerWeight(localPos, cornerIdx),
corners_[cornerIdx]);
return globalPos;
}
/*!
* \brief Returns the Jacobian matrix of the local to global
* mapping at a given local position.
*/
void jacobian(Dune::FieldMatrix<Scalar, dim, dim>& jac,
const LocalPosition& localPos) const
{
jac = 0.0;
for (unsigned cornerIdx = 0; cornerIdx < numCorners; ++cornerIdx) {
for (unsigned k = 0; k < dim; ++k) {
Scalar dWeight_dk = (cornerIdx& (1 << k)) ? 1 : -1;
for (unsigned j = 0; j < dim; ++j) {
if (k != j) {
if (cornerIdx& (1 << j))
dWeight_dk *= localPos[j];
else
dWeight_dk *= 1 - localPos[j];
;
}
}
jac[k].axpy(dWeight_dk, corners_[cornerIdx]);
}
}
}
/*!
* \brief Return the determinant of the Jacobian of the mapping
* from local to global coordinates at a given local
* position.
*/
Scalar integrationElement(const LocalPosition& localPos) const
{
Dune::FieldMatrix<Scalar, dim, dim> jac;
jacobian(jac, localPos);
return jac.determinant();
}
/*!
* \brief Return the position of the corner with a given index
*/
const GlobalPosition& corner(unsigned cornerIdx) const
{ return corners_[cornerIdx]; }
/*!
* \brief Return the weight of an individual corner for the local
* to global mapping.
*/
Scalar cornerWeight(const LocalPosition& localPos, unsigned cornerIdx) const
{
GlobalPosition globalPos(0.0);
// this code is based on the Q1 finite element code from
// dune-localfunctions
Scalar weight = 1.0;
for (unsigned j = 0; j < dim; ++j)
weight *= (cornerIdx& (1 << j)) ? localPos[j] : (1 - localPos[j]);
return weight;
}
private:
GlobalPosition corners_[numCorners];
GlobalPosition center_;
};
} // namespace Opm
#endif // EWOMS_QUADRATURE_GEOMETRY_HH

View File

@ -0,0 +1,45 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \copydoc sgn()
*/
#ifndef EWOMS_SIGNUM_HH
#define EWOMS_SIGNUM_HH
namespace Opm {
/*!
* \brief Template function which returns the sign of a floating point value
*
* This is a type safe and fast implementation of a sign() function for arbitrary
* floating point values. It a slightly modified variant of
*
* https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
*/
template <class Scalar>
int signum(Scalar val)
{ return (0 < val) - (val < 0); }
} // namespace Opm
#endif

View File

@ -0,0 +1,957 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::Simulator
*/
#ifndef EWOMS_SIMULATOR_HH
#define EWOMS_SIMULATOR_HH
#include <ewoms/io/restart.hh>
#include <opm/models/utils/parametersystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/timer.hh>
#include <opm/models/utils/timerguard.hh>
#include <dune/common/version.hh>
#include <dune/common/parallel/mpihelper.hh>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <vector>
#include <string>
#include <memory>
BEGIN_PROPERTIES
NEW_PROP_TAG(Scalar);
NEW_PROP_TAG(Vanguard);
NEW_PROP_TAG(GridView);
NEW_PROP_TAG(Model);
NEW_PROP_TAG(Problem);
NEW_PROP_TAG(EndTime);
NEW_PROP_TAG(RestartTime);
NEW_PROP_TAG(InitialTimeStepSize);
NEW_PROP_TAG(PredeterminedTimeStepsFile);
END_PROPERTIES
#define EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(code) \
{ \
const auto& comm = Dune::MPIHelper::getCollectiveCommunication(); \
bool exceptionThrown = false; \
try { code; } \
catch (const Dune::Exception& e) { \
exceptionThrown = true; \
std::cerr << "Process " << comm.rank() << " threw a fatal exception: " \
<< e.what() << ". Abort!" << std::endl; \
} \
catch (const std::exception& e) { \
exceptionThrown = true; \
std::cerr << "Process " << comm.rank() << " threw a fatal exception: " \
<< e.what() << ". Abort!" << std::endl; \
} \
catch (...) { \
exceptionThrown = true; \
std::cerr << "Process " << comm.rank() << " threw a fatal exception. " \
<<" Abort!" << std::endl; \
} \
\
if (comm.max(exceptionThrown)) \
std::abort(); \
}
namespace Opm {
/*!
* \ingroup Common
*
* \brief Manages the initializing and running of time dependent
* problems.
*
* This class instantiates the grid, the model and the problem to be
* simlated and runs the simulation loop. The time axis is treated as
* a sequence of "episodes" which are defined as time intervals for
* which the problem exhibits boundary conditions and source terms
* that do not depend on time.
*/
template <class TypeTag>
class Simulator
{
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Vanguard) Vanguard;
typedef typename GET_PROP_TYPE(TypeTag, GridView) GridView;
typedef typename GET_PROP_TYPE(TypeTag, Model) Model;
typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
public:
// do not allow to copy simulators around
Simulator(const Simulator& ) = delete;
Simulator(bool verbose = true)
{
Opm::TimerGuard setupTimerGuard(setupTimer_);
setupTimer_.start();
const auto& comm = Dune::MPIHelper::getCollectiveCommunication();
verbose_ = verbose && comm.rank() == 0;
timeStepIdx_ = 0;
startTime_ = 0.0;
time_ = 0.0;
endTime_ = EWOMS_GET_PARAM(TypeTag, Scalar, EndTime);
timeStepSize_ = EWOMS_GET_PARAM(TypeTag, Scalar, InitialTimeStepSize);
const std::string& predetTimeStepFile =
EWOMS_GET_PARAM(TypeTag, std::string, PredeterminedTimeStepsFile);
if (!predetTimeStepFile.empty()) {
std::ifstream is(predetTimeStepFile);
while (!is.eof()) {
Scalar dt;
is >> dt;
forcedTimeSteps_.push_back(dt);
}
}
episodeIdx_ = 0;
episodeStartTime_ = 0;
episodeLength_ = std::numeric_limits<Scalar>::max();
finished_ = false;
if (verbose_)
std::cout << "Allocating the simulation vanguard\n" << std::flush;
int exceptionThrown = 0;
try
{ vanguard_.reset(new Vanguard(*this)); }
catch (const std::exception& e) {
exceptionThrown = 1;
if (verbose_)
std::cerr << "Rank " << comm.rank() << " threw an exception: " << e.what() << std::endl;
}
if (comm.max(exceptionThrown))
throw std::runtime_error("Allocating the simulation vanguard failed.");
if (verbose_)
std::cout << "Distributing the vanguard's data\n" << std::flush;
try
{ vanguard_->loadBalance(); }
catch (const std::exception& e) {
exceptionThrown = 1;
if (verbose_)
std::cerr << "Rank " << comm.rank() << " threw an exception: " << e.what() << std::endl;
}
if (comm.max(exceptionThrown))
throw std::runtime_error("Could not distribute the vanguard data.");
if (verbose_)
std::cout << "Allocating the model\n" << std::flush;
model_.reset(new Model(*this));
if (verbose_)
std::cout << "Allocating the problem\n" << std::flush;
problem_.reset(new Problem(*this));
if (verbose_)
std::cout << "Initializing the model\n" << std::flush;
try
{ model_->finishInit(); }
catch (const std::exception& e) {
exceptionThrown = 1;
if (verbose_)
std::cerr << "Rank " << comm.rank() << " threw an exception: " << e.what() << std::endl;
}
if (comm.max(exceptionThrown))
throw std::runtime_error("Could not initialize the model.");
if (verbose_)
std::cout << "Initializing the problem\n" << std::flush;
try
{ problem_->finishInit(); }
catch (const std::exception& e) {
exceptionThrown = 1;
if (verbose_)
std::cerr << "Rank " << comm.rank() << " threw an exception: " << e.what() << std::endl;
}
if (comm.max(exceptionThrown))
throw std::runtime_error("Could not initialize the problem.");
setupTimer_.stop();
if (verbose_)
std::cout << "Simulator successfully set up\n" << std::flush;
}
/*!
* \brief Registers all runtime parameters used by the simulation.
*/
static void registerParameters()
{
EWOMS_REGISTER_PARAM(TypeTag, Scalar, EndTime,
"The simulation time at which the simulation is finished [s]");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, InitialTimeStepSize,
"The size of the initial time step [s]");
EWOMS_REGISTER_PARAM(TypeTag, Scalar, RestartTime,
"The simulation time at which a restart should be attempted [s]");
EWOMS_REGISTER_PARAM(TypeTag, std::string, PredeterminedTimeStepsFile,
"A file with a list of predetermined time step sizes (one "
"time step per line)");
Vanguard::registerParameters();
Model::registerParameters();
Problem::registerParameters();
}
/*!
* \brief Return a reference to the grid manager of simulation
*/
Vanguard& vanguard()
{ return *vanguard_; }
/*!
* \brief Return a reference to the grid manager of simulation
*/
const Vanguard& vanguard() const
{ return *vanguard_; }
/*!
* \brief Return the grid view for which the simulation is done
*/
const GridView& gridView() const
{ return vanguard_->gridView(); }
/*!
* \brief Return the physical model used in the simulation
*/
Model& model()
{ return *model_; }
/*!
* \brief Return the physical model used in the simulation
*/
const Model& model() const
{ return *model_; }
/*!
* \brief Return the object which specifies the pysical setup of
* the simulation
*/
Problem& problem()
{ return *problem_; }
/*!
* \brief Return the object which specifies the pysical setup of
* the simulation
*/
const Problem& problem() const
{ return *problem_; }
/*!
* \brief Set the time of the start of the simulation.
*
* \param t The time \f$\mathrm{[s]}\f$ which should be jumped to
*/
void setStartTime(Scalar t)
{ startTime_ = t; }
/*!
* \brief Return the time of the start of the simulation.
*/
Scalar startTime() const
{ return startTime_; }
/*!
* \brief Set the current simulated time, don't change the current
* time step index.
*
* \param t The time \f$\mathrm{[s]}\f$ which should be jumped to
*/
void setTime(Scalar t)
{ time_ = t; }
/*!
* \brief Set the current simulated time and the time step index.
*
* \param t The time \f$\mathrm{[s]}\f$ which should be jumped to
* \param stepIdx The new time step index
*/
void setTime(Scalar t, unsigned stepIdx)
{
time_ = t;
timeStepIdx_ = stepIdx;
}
/*!
* \brief Return the number of seconds of simulated time which have elapsed since the
* start time.
*
* To get the time after the time integration, you have to add
* timeStepSize() to time().
*/
Scalar time() const
{ return time_; }
/*!
* \brief Set the time of simulated seconds at which the simulation runs.
*
* \param t The time \f$\mathrm{[s]}\f$ at which the simulation is finished
*/
void setEndTime(Scalar t)
{ endTime_ = t; }
/*!
* \brief Returns the number of (simulated) seconds which the simulation
* runs.
*/
Scalar endTime() const
{ return endTime_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed to
* set up and initialize the simulation
*/
const Opm::Timer& setupTimer() const
{ return setupTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed to
* run the simulation
*/
const Opm::Timer& executionTimer() const
{ return executionTimer_; }
Opm::Timer& executionTimer()
{ return executionTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed for
* pre- and postprocessing of the solutions.
*/
const Opm::Timer& prePostProcessTimer() const
{ return prePostProcessTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed for
* linarizing the solutions.
*/
const Opm::Timer& linearizeTimer() const
{ return linearizeTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed by
* the solver.
*/
const Opm::Timer& solveTimer() const
{ return solveTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed to
* the solutions of the non-linear system of equations.
*/
const Opm::Timer& updateTimer() const
{ return updateTimer_; }
/*!
* \brief Returns a reference to the timer object which measures the time needed to
* write the visualization output
*/
const Opm::Timer& writeTimer() const
{ return writeTimer_; }
/*!
* \brief Set the current time step size to a given value.
*
* If the step size would exceed the length of the current
* episode, the timeStep() method will take care that the step
* size won't exceed the episode or the end of the simulation,
* though.
*
* \param timeStepSize The new value for the time step size \f$\mathrm{[s]}\f$
*/
void setTimeStepSize(Scalar value)
{ timeStepSize_ = value; }
/*!
* \brief Set the current time step index to a given value.
*
* \param timeStepIndex The new value for the time step index
*/
void setTimeStepIndex(unsigned value)
{ timeStepIdx_ = value; }
/*!
* \brief Returns the time step length \f$\mathrm{[s]}\f$ so that we
* don't miss the beginning of the next episode or cross
* the end of the simlation.
*/
Scalar timeStepSize() const
{ return timeStepSize_; }
/*!
* \brief Returns number of time steps which have been
* executed since the beginning of the simulation.
*/
int timeStepIndex() const
{ return timeStepIdx_; }
/*!
* \brief Specify whether the simulation is finished
*
* \param yesno If true the simulation is considered finished
* before the end time is reached, else it is only
* considered finished if the end time is reached.
*/
void setFinished(bool yesno = true)
{ finished_ = yesno; }
/*!
* \brief Returns true if the simulation is finished.
*
* This is the case if either setFinished(true) has been called or
* if the end time is reached.
*/
bool finished() const
{
assert(timeStepSize_ >= 0.0);
Scalar eps =
std::max(Scalar(std::abs(this->time())), timeStepSize())
*std::numeric_limits<Scalar>::epsilon()*1e3;
return finished_ || (this->time()*(1.0 + eps) >= endTime());
}
/*!
* \brief Returns true if the simulation is finished after the
* time level is incremented by the current time step size.
*/
bool willBeFinished() const
{
static const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e3;
return finished_ || (this->time() + timeStepSize_)*(1.0 + eps) >= endTime();
}
/*!
* \brief Aligns the time step size to the episode boundary and to
* the end time of the simulation.
*/
Scalar maxTimeStepSize() const
{
if (finished())
return 0.0;
return std::min(episodeMaxTimeStepSize(),
std::max<Scalar>(0.0, endTime() - this->time()));
}
/*!
* \brief Change the current episode of the simulation.
*
* \param episodeStartTime Time when the episode began \f$\mathrm{[s]}\f$
* \param episodeLength Length of the episode \f$\mathrm{[s]}\f$
*/
void startNextEpisode(Scalar episodeStartTime, Scalar episodeLength)
{
++episodeIdx_;
episodeStartTime_ = episodeStartTime;
episodeLength_ = episodeLength;
}
/*!
* \brief Start the next episode, but don't change the episode
* identifier.
*
* \param len Length of the episode \f$\mathrm{[s]}\f$, infinite if not
* specified.
*/
void startNextEpisode(Scalar len = std::numeric_limits<Scalar>::max())
{
++episodeIdx_;
episodeStartTime_ = startTime_ + time_;
episodeLength_ = len;
}
/*!
* \brief Sets the index of the current episode.
*
* Use this method with care!
*/
void setEpisodeIndex(int episodeIdx)
{ episodeIdx_ = episodeIdx; }
/*!
* \brief Returns the index of the current episode.
*
* The first episode has the index 0.
*/
int episodeIndex() const
{ return episodeIdx_; }
/*!
* \brief Returns the absolute time when the current episode
* started \f$\mathrm{[s]}\f$.
*/
Scalar episodeStartTime() const
{ return episodeStartTime_; }
/*!
* \brief Sets the length in seconds of the current episode.
*
* Use this method with care!
*/
void setEpisodeLength(Scalar dt)
{ episodeLength_ = dt; }
/*!
* \brief Returns the length of the current episode in
* simulated time \f$\mathrm{[s]}\f$.
*/
Scalar episodeLength() const
{ return episodeLength_; }
/*!
* \brief Returns true if the current episode has just been started at the
* current time.
*/
bool episodeStarts() const
{
static const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e3;
return this->time() <= (episodeStartTime_ - startTime())*(1 + eps);
}
/*!
* \brief Returns true if the current episode is finished at the
* current time.
*/
bool episodeIsOver() const
{
static const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e3;
return this->time() >= (episodeStartTime_ - startTime() + episodeLength())*(1 - eps);
}
/*!
* \brief Returns true if the current episode will be finished
* after the current time step.
*/
bool episodeWillBeOver() const
{
static const Scalar eps = std::numeric_limits<Scalar>::epsilon()*1e3;
return this->time() + timeStepSize()
>= (episodeStartTime_ - startTime() + episodeLength())*(1 - eps);
}
/*!
* \brief Aligns the time step size to the episode boundary if the
* current time step crosses the boundary of the current episode.
*/
Scalar episodeMaxTimeStepSize() const
{
// if the current episode is over and the simulation
// wants to give it some extra time, we will return
// the time step size it suggested instead of trying
// to align it to the end of the episode.
if (episodeIsOver())
return 0.0;
// make sure that we don't exceed the end of the
// current episode.
return std::max<Scalar>(0.0,
(episodeStartTime() + episodeLength())
- (this->time() + this->startTime()));
}
/*
* \}
*/
/*!
* \brief Runs the simulation using a given problem class.
*
* This method makes sure that time steps sizes are aligned to
* episode boundaries, amongst other stuff.
*/
void run()
{
// create TimerGuard objects to hedge for exceptions
TimerGuard setupTimerGuard(setupTimer_);
TimerGuard executionTimerGuard(executionTimer_);
TimerGuard prePostProcessTimerGuard(prePostProcessTimer_);
TimerGuard writeTimerGuard(writeTimer_);
setupTimer_.start();
Scalar restartTime = EWOMS_GET_PARAM(TypeTag, Scalar, RestartTime);
if (restartTime > -1e30) {
// try to restart a previous simulation
time_ = restartTime;
Opm::Restart res;
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(res.deserializeBegin(*this, time_));
if (verbose_)
std::cout << "Deserialize from file '" << res.fileName() << "'\n" << std::flush;
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(this->deserialize(res));
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->deserialize(res));
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(model_->deserialize(res));
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(res.deserializeEnd());
if (verbose_)
std::cout << "Deserialization done."
<< " Simulator time: " << time() << humanReadableTime(time())
<< " Time step index: " << timeStepIndex()
<< " Episode index: " << episodeIndex()
<< "\n" << std::flush;
}
else {
// if no restart is done, apply the initial solution
if (verbose_)
std::cout << "Applying the initial solution of the \"" << problem_->name()
<< "\" problem\n" << std::flush;
Scalar oldTimeStepSize = timeStepSize_;
int oldTimeStepIdx = timeStepIdx_;
timeStepSize_ = 0.0;
timeStepIdx_ = -1;
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(model_->applyInitialSolution());
// write initial condition
if (problem_->shouldWriteOutput())
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->writeOutput());
timeStepSize_ = oldTimeStepSize;
timeStepIdx_ = oldTimeStepIdx;
}
setupTimer_.stop();
executionTimer_.start();
bool episodeBegins = episodeIsOver() || (timeStepIdx_ == 0);
// do the time steps
while (!finished()) {
prePostProcessTimer_.start();
if (episodeBegins) {
// notify the problem that a new episode has just been
// started.
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->beginEpisode());
if (finished()) {
// the problem can chose to terminate the simulation in
// beginEpisode(), so we have handle this case.
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->endEpisode());
prePostProcessTimer_.stop();
break;
}
}
episodeBegins = false;
if (verbose_) {
std::cout << "Begin time step " << timeStepIndex() + 1 << ". "
<< "Start time: " << this->time() << " seconds" << humanReadableTime(this->time())
<< ", step size: " << timeStepSize() << " seconds" << humanReadableTime(timeStepSize())
<< "\n";
}
// pre-process the current solution
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->beginTimeStep());
if (finished()) {
// the problem can chose to terminate the simulation in
// beginTimeStep(), so we have handle this case.
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->endTimeStep());
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->endEpisode());
prePostProcessTimer_.stop();
break;
}
prePostProcessTimer_.stop();
try {
// execute the time integration scheme
problem_->timeIntegration();
}
catch (...) {
// exceptions in the time integration might be recoverable. clean up in
// case they are
const auto& model = problem_->model();
prePostProcessTimer_ += model.prePostProcessTimer();
linearizeTimer_ += model.linearizeTimer();
solveTimer_ += model.solveTimer();
updateTimer_ += model.updateTimer();
throw;
}
const auto& model = problem_->model();
prePostProcessTimer_ += model.prePostProcessTimer();
linearizeTimer_ += model.linearizeTimer();
solveTimer_ += model.solveTimer();
updateTimer_ += model.updateTimer();
// post-process the current solution
prePostProcessTimer_.start();
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->endTimeStep());
prePostProcessTimer_.stop();
// write the result to disk
writeTimer_.start();
if (problem_->shouldWriteOutput())
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->writeOutput());
writeTimer_.stop();
// do the next time integration
Scalar oldDt = timeStepSize();
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->advanceTimeLevel());
if (verbose_) {
std::cout << "Time step " << timeStepIndex() + 1 << " done. "
<< "CPU time: " << executionTimer_.realTimeElapsed() << " seconds" << humanReadableTime(executionTimer_.realTimeElapsed())
<< ", end time: " << this->time() + oldDt << " seconds" << humanReadableTime(this->time() + oldDt)
<< ", step size: " << oldDt << " seconds" << humanReadableTime(oldDt)
<< "\n" << std::flush;
}
// advance the simulated time by the current time step size
time_ += oldDt;
++timeStepIdx_;
prePostProcessTimer_.start();
// notify the problem if an episode is finished
if (episodeIsOver()) {
// Notify the problem about the end of the current episode...
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->endEpisode());
episodeBegins = true;
}
else {
Scalar dt;
if (timeStepIdx_ < static_cast<int>(forcedTimeSteps_.size()))
// use the next time step size from the input file
dt = forcedTimeSteps_[timeStepIdx_];
else
// ask the problem to provide the next time step size
dt = std::min(maxTimeStepSize(), problem_->nextTimeStepSize());
setTimeStepSize(dt);
}
prePostProcessTimer_.stop();
// write restart file if mandated by the problem
writeTimer_.start();
if (problem_->shouldWriteRestartFile())
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(serialize());
writeTimer_.stop();
}
executionTimer_.stop();
EWOMS_CATCH_PARALLEL_EXCEPTIONS_FATAL(problem_->finalize());
}
/*!
* \brief Given a time step size in seconds, return it in a format which is more
* easily parsable by humans.
*
* e.g. 874000.0 will become "10.12 days"
*/
static std::string humanReadableTime(Scalar timeInSeconds, bool isAmendment=true)
{
std::ostringstream oss;
oss << std::setprecision(4);
if (isAmendment)
oss << " (";
if (timeInSeconds >= 365.25*24*60*60) {
int years = static_cast<int>(timeInSeconds/(365.25*24*60*60));
int days = static_cast<int>((timeInSeconds - years*(365.25*24*60*60))/(24*60*60));
double accuracy = 1e-2;
double hours =
std::round(1.0/accuracy*
(timeInSeconds
- years*(365.25*24*60*60)
- days*(24*60*60))/(60*60))
*accuracy;
oss << years << " years, " << days << " days, " << hours << " hours";
}
else if (timeInSeconds >= 24.0*60*60) {
int days = static_cast<int>(timeInSeconds/(24*60*60));
int hours = static_cast<int>((timeInSeconds - days*(24*60*60))/(60*60));
double accuracy = 1e-2;
double minutes =
std::round(1.0/accuracy*
(timeInSeconds
- days*(24*60*60)
- hours*(60*60))/60)
*accuracy;
oss << days << " days, " << hours << " hours, " << minutes << " minutes";
}
else if (timeInSeconds >= 60.0*60) {
int hours = static_cast<int>(timeInSeconds/(60*60));
int minutes = static_cast<int>((timeInSeconds - hours*(60*60))/60);
double accuracy = 1e-2;
double seconds =
std::round(1.0/accuracy*
(timeInSeconds
- hours*(60*60)
- minutes*60))
*accuracy;
oss << hours << " hours, " << minutes << " minutes, " << seconds << " seconds";
}
else if (timeInSeconds >= 60.0) {
int minutes = static_cast<int>(timeInSeconds/60);
double accuracy = 1e-3;
double seconds =
std::round(1.0/accuracy*
(timeInSeconds
- minutes*60))
*accuracy;
oss << minutes << " minutes, " << seconds << " seconds";
}
else if (!isAmendment)
oss << timeInSeconds << " seconds";
else
return "";
if (isAmendment)
oss << ")";
return oss.str();
}
/*!
* \name Saving/restoring the simulation state
* \{
*/
/*!
* \brief This method writes the complete state of the simulation
* to the harddisk.
*
* The file will start with the prefix returned by the name()
* method, has the current time of the simulation clock in it's
* name and uses the extension <tt>.ers</tt>. (Ewoms ReStart
* file.) See Opm::Restart for details.
*/
void serialize()
{
typedef Opm::Restart Restarter;
Restarter res;
res.serializeBegin(*this);
if (gridView().comm().rank() == 0)
std::cout << "Serialize to file '" << res.fileName() << "'"
<< ", next time step size: " << timeStepSize()
<< "\n" << std::flush;
this->serialize(res);
problem_->serialize(res);
model_->serialize(res);
res.serializeEnd();
}
/*!
* \brief Write the time manager's state to a restart file.
*
* \tparam Restarter The type of the object which takes care to serialize
* data
* \param restarter The serializer object
*/
template <class Restarter>
void serialize(Restarter& restarter)
{
restarter.serializeSectionBegin("Simulator");
restarter.serializeStream()
<< episodeIdx_ << " "
<< episodeStartTime_ << " "
<< episodeLength_ << " "
<< startTime_ << " "
<< time_ << " "
<< timeStepIdx_ << " ";
restarter.serializeSectionEnd();
}
/*!
* \brief Read the time manager's state from a restart file.
*
* \tparam Restarter The type of the object which takes care to deserialize
* data
* \param restarter The deserializer object
*/
template <class Restarter>
void deserialize(Restarter& restarter)
{
restarter.deserializeSectionBegin("Simulator");
restarter.deserializeStream()
>> episodeIdx_
>> episodeStartTime_
>> episodeLength_
>> startTime_
>> time_
>> timeStepIdx_;
restarter.deserializeSectionEnd();
}
private:
std::unique_ptr<Vanguard> vanguard_;
std::unique_ptr<Model> model_;
std::unique_ptr<Problem> problem_;
int episodeIdx_;
Scalar episodeStartTime_;
Scalar episodeLength_;
Opm::Timer setupTimer_;
Opm::Timer executionTimer_;
Opm::Timer prePostProcessTimer_;
Opm::Timer linearizeTimer_;
Opm::Timer solveTimer_;
Opm::Timer updateTimer_;
Opm::Timer writeTimer_;
std::vector<Scalar> forcedTimeSteps_;
Scalar startTime_;
Scalar time_;
Scalar endTime_;
Scalar timeStepSize_;
int timeStepIdx_;
bool finished_;
bool verbose_;
};
} // namespace Opm
#endif

443
opm/models/utils/start.hh Normal file
View File

@ -0,0 +1,443 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
* \brief Provides convenience routines to bring up the simulation at runtime.
*/
#ifndef EWOMS_START_HH
#define EWOMS_START_HH
#include <opm/models/utils/propertysystem.hh>
// the following header is not required here, but it must be included before
// dune/common/densematrix.hh because of some c++ ideosyncrasies
#include <opm/material/densead/Evaluation.hpp>
#include "parametersystem.hh"
#include <opm/models/utils/parametersystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/simulator.hh>
#include <opm/models/utils/timer.hh>
#include <opm/material/common/Valgrind.hpp>
#include <opm/material/common/ResetLocale.hpp>
#include <dune/grid/io/file/dgfparser/dgfparser.hh>
#include <dune/common/version.hh>
#include <dune/common/parametertreeparser.hh>
#include <dune/common/parallel/mpihelper.hh>
#if HAVE_DUNE_FEM
#include <dune/fem/misc/mpimanager.hh>
#endif
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <locale>
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include <signal.h>
#include <string.h>
#if HAVE_MPI
#include <mpi.h>
#endif
BEGIN_PROPERTIES
// forward declaration of property tags
NEW_PROP_TAG(Scalar);
NEW_PROP_TAG(Simulator);
NEW_PROP_TAG(ThreadManager);
NEW_PROP_TAG(PrintProperties);
NEW_PROP_TAG(PrintParameters);
NEW_PROP_TAG(ParameterFile);
NEW_PROP_TAG(Problem);
END_PROPERTIES
//! \cond SKIP_THIS
namespace Opm {
/*!
* \brief Announce all runtime parameters to the registry but do not specify them yet.
*/
template <class TypeTag>
static inline void registerAllParameters_(bool finalizeRegistration = true)
{
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename GET_PROP_TYPE(TypeTag, ThreadManager) ThreadManager;
EWOMS_REGISTER_PARAM(TypeTag, std::string, ParameterFile,
"An .ini file which contains a set of run-time "
"parameters");
EWOMS_REGISTER_PARAM(TypeTag, int, PrintProperties,
"Print the values of the compile time properties at "
"the start of the simulation");
EWOMS_REGISTER_PARAM(TypeTag, int, PrintParameters,
"Print the values of the run-time parameters at the "
"start of the simulation");
Simulator::registerParameters();
ThreadManager::registerParameters();
if (finalizeRegistration)
EWOMS_END_PARAM_REGISTRATION(TypeTag);
}
/*!
* \brief Register all runtime parameters, parse the command line
* arguments and the parameter file.
*
* \param argc The number of command line arguments
* \param argv Array with the command line argument strings
*/
template <class TypeTag>
static inline int setupParameters_(int argc,
const char **argv,
bool registerParams=true,
bool allowUnused=false,
bool handleHelp = true)
{
typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
// first, get the MPI rank of the current process
int myRank = 0;
////////////////////////////////////////////////////////////
// Register all parameters
////////////////////////////////////////////////////////////
if (registerParams)
registerAllParameters_<TypeTag>();
////////////////////////////////////////////////////////////
// set the parameter values
////////////////////////////////////////////////////////////
// fill the parameter tree with the options from the command line
const auto& positionalParamCallback = Problem::handlePositionalParameter;
std::string helpPreamble = "";
if (myRank == 0 && handleHelp)
helpPreamble = Problem::helpPreamble(argc, argv);
std::string s =
Parameters::parseCommandLineOptions<TypeTag>(argc,
argv,
helpPreamble,
positionalParamCallback);
if (!s.empty())
return /*status=*/1;
std::string paramFileName = EWOMS_GET_PARAM_(TypeTag, std::string, ParameterFile);
if (paramFileName != "") {
////////////////////////////////////////////////////////////
// add the parameters specified using an .ini file
////////////////////////////////////////////////////////////
// check whether the parameter file is readable.
std::ifstream tmp;
tmp.open(paramFileName.c_str());
if (!tmp.is_open()) {
std::ostringstream oss;
if (myRank == 0) {
oss << "Parameter file \"" << paramFileName
<< "\" does not exist or is not readable.";
Parameters::printUsage<TypeTag>(argv[0], oss.str());
}
return /*status=*/1;
}
// read the parameter file.
Parameters::parseParameterFile<TypeTag>(paramFileName, /*overwrite=*/false);
}
// make sure that no unknown parameters are encountered
typedef std::pair<std::string, std::string> KeyValuePair;
typedef std::list<KeyValuePair> ParamList;
ParamList usedParams;
ParamList unusedParams;
EWOMS_GET_PARAM_LISTS(TypeTag, usedParams, unusedParams);
if (!allowUnused && !unusedParams.empty()) {
if (myRank == 0) {
if (unusedParams.size() == 1)
std::cerr << "The following explicitly specified parameter is unknown:\n";
else
std::cerr << "The following " << unusedParams.size()
<< " explicitly specified parameters are unknown:\n";
std::cerr << "\n";
for (const auto& keyValue : unusedParams)
std::cerr << " " << keyValue.first << "=\"" << keyValue.second << "\"\n";
std::cerr << "\n";
std::cerr << "Use\n"
<< "\n"
<< " " << argv[0] << " --help\n"
<< "\n"
<<"to obtain the list of recognized command line parameters.\n\n";
}
return /*status=*/1;
}
return /*status=*/0;
}
/*!
* \brief Resets the current TTY to a usable state if the program was aborted.
*
* This is intended to be called as part of a generic exception handler
*/
static inline void resetTerminal_()
{
// make sure stderr and stderr do not contain any unwritten data and make sure that
// the TTY does not see any unfinished ANSI escape sequence.
std::cerr << " \r\n";
std::cerr.flush();
std::cout << " \r\n";
std::cout.flush();
// it seems like some terminals sometimes takes their time to react, so let's
// accommodate them.
usleep(/*usec=*/500*1000);
// this requires the 'stty' command to be available in the command search path. on
// most linux systems, is the case. (but even if the system() function fails, the
// worst thing which can happen is that the TTY stays potentially choked up...)
if (system("stty sane") != 0)
std::cout << "Executing the 'stty' command failed."
<< " Terminal might be left in an undefined state!\n";
}
/*!
* \brief Resets the current TTY to a usable state if the program was interrupted by
* SIGABRT or SIGINT.
*/
static inline void resetTerminal_(int signum)
{
// first thing to do when a nuke hits: restore the default signal handler
signal(signum, SIG_DFL);
#if HAVE_MPI
int rank = 0;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
if (rank != 0) {
// re-raise the signal
raise(signum);
return;
}
#endif
if (isatty(fileno(stdout)) && isatty(fileno(stdin))) {
std::cout << "\n\nReceived signal " << signum
<< " (\"" << strsignal(signum) << "\")."
<< " Trying to reset the terminal.\n";
resetTerminal_();
}
// after we did our best to clean the pedestrian way, re-raise the signal
raise(signum);
}
//! \endcond
/*!
* \ingroup Common
*
* \brief Provides a main function which reads in parameters from the
* command line and a parameter file and runs the simulation
*
* \tparam TypeTag The type tag of the problem which needs to be solved
*
* \param argc The number of command line arguments
* \param argv The array of the command line arguments
*/
template <class TypeTag>
static inline int start(int argc, char **argv)
{
typedef typename GET_PROP_TYPE(TypeTag, Scalar) Scalar;
typedef typename GET_PROP_TYPE(TypeTag, Simulator) Simulator;
typedef typename GET_PROP_TYPE(TypeTag, Problem) Problem;
typedef typename GET_PROP_TYPE(TypeTag, ThreadManager) ThreadManager;
// set the signal handlers to reset the TTY to a well defined state on unexpected
// program aborts
if (isatty(STDIN_FILENO)) {
signal(SIGINT, resetTerminal_);
signal(SIGHUP, resetTerminal_);
signal(SIGABRT, resetTerminal_);
signal(SIGFPE, resetTerminal_);
signal(SIGSEGV, resetTerminal_);
signal(SIGPIPE, resetTerminal_);
signal(SIGTERM, resetTerminal_);
}
Opm::resetLocale();
int myRank = 0;
try
{
int paramStatus = setupParameters_<TypeTag>(argc, const_cast<const char**>(argv));
if (paramStatus == 1)
return 1;
if (paramStatus == 2)
return 0;
ThreadManager::init();
// initialize MPI, finalize is done automatically on exit
#if HAVE_DUNE_FEM
Dune::Fem::MPIManager::initialize(argc, argv);
myRank = Dune::Fem::MPIManager::rank();
#else
myRank = Dune::MPIHelper::instance(argc, argv).rank();
#endif
// read the initial time step and the end time
Scalar endTime = EWOMS_GET_PARAM(TypeTag, Scalar, EndTime);
if (endTime < -1e50) {
if (myRank == 0)
Parameters::printUsage<TypeTag>(argv[0],
"Mandatory parameter '--end-time' not specified!");
return 1;
}
Scalar initialTimeStepSize = EWOMS_GET_PARAM(TypeTag, Scalar, InitialTimeStepSize);
if (initialTimeStepSize < -1e50) {
if (myRank == 0)
Parameters::printUsage<TypeTag>(argv[0],
"Mandatory parameter '--initial-time-step-size' "
"not specified!");
return 1;
}
if (myRank == 0) {
#ifdef EWOMS_VERSION
std::string versionString = EWOMS_VERSION;
#else
std::string versionString = "";
#endif
const std::string briefDescription = Problem::briefDescription();
if (!briefDescription.empty()) {
std::string tmp = Parameters::breakLines_(briefDescription,
/*indentWidth=*/0,
Parameters::getTtyWidth_());
std::cout << tmp << std::endl << std::endl;
}
else
std::cout << "eWoms " << versionString
<< " will now start the trip. "
<< "Please sit back, relax and enjoy the ride.\n"
<< std::flush;
}
// print the parameters if requested
int printParams = EWOMS_GET_PARAM(TypeTag, int, PrintParameters);
if (myRank == 0) {
std::string endParametersSeparator("# [end of parameters]\n");
if (printParams) {
bool printSeparator = false;
if (printParams == 1 || !isatty(fileno(stdout))) {
Opm::Parameters::printValues<TypeTag>();
printSeparator = true;
}
else
// always print the list of specified but unused parameters
printSeparator =
printSeparator ||
Opm::Parameters::printUnused<TypeTag>();
if (printSeparator)
std::cout << endParametersSeparator;
}
else
// always print the list of specified but unused parameters
if (Opm::Parameters::printUnused<TypeTag>())
std::cout << endParametersSeparator;
}
// print the properties if requested
int printProps = EWOMS_GET_PARAM(TypeTag, int, PrintProperties);
if (printProps && myRank == 0) {
if (printProps == 1 || !isatty(fileno(stdout)))
Opm::Properties::printValues<TypeTag>();
}
// instantiate and run the concrete problem. make sure to
// deallocate the problem and before the time manager and the
// grid
Simulator simulator;
simulator.run();
if (myRank == 0) {
std::cout << "eWoms reached the destination. If it is not the one that was intended, "
<< "change the booking and try again.\n"
<< std::flush;
}
return 0;
}
#if ! DUNE_VERSION_NEWER(DUNE_COMMON, 2,5)
catch (Dune::Exception& e)
{
if (myRank == 0) {
std::cout << "Dune reported an error: " << e.what() << std::endl << std::flush;
std::cout << "Trying to reset TTY.\n";
resetTerminal_();
}
return 2;
}
#endif
catch (std::exception& e)
{
if (myRank == 0) {
std::cout << e.what() << ". Abort!\n" << std::flush;
std::cout << "Trying to reset TTY.\n";
resetTerminal_();
}
return 1;
}
catch (...)
{
if (myRank == 0) {
std::cout << "Unknown exception thrown!\n" << std::flush;
std::cout << "Trying to reset TTY.\n";
resetTerminal_();
}
return 3;
}
}
} // namespace Opm
#endif

217
opm/models/utils/timer.hh Normal file
View File

@ -0,0 +1,217 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::Timer
*/
#ifndef EWOMS_TIMER_HH
#define EWOMS_TIMER_HH
#include <chrono>
#if HAVE_MPI
#include <mpi.h>
#endif
namespace Opm {
/*!
* \ingroup Common
*
* \brief Provides an encapsulation to measure the system time
*
* This means the wall clock time used by the simulation, the CPU time
* used by all threads of a single process and the CPU time used by
* the overall simulation. (i.e., the time used by all threads of all
* involved processes.)
*/
class Timer
{
struct TimeData
{
std::chrono::high_resolution_clock::time_point realtimeData;
std::clock_t cputimeData;
};
public:
Timer()
{ halt(); }
/*!
* \brief Start counting the time resources used by the simulation.
*/
void start()
{
isStopped_ = false;
measure_(startTime_);
}
/*!
* \brief Stop counting the time resources.
*
* Returns the wall clock time the timer was active.
*/
double stop()
{
if (!isStopped_) {
TimeData stopTime;
measure_(stopTime);
const auto& t1 = startTime_.realtimeData;
const auto& t2 = stopTime.realtimeData;
std::chrono::duration<double> dt =
std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1);
realTimeElapsed_ += dt.count();
cpuTimeElapsed_ +=
static_cast<double>(stopTime.cputimeData
- startTime_.cputimeData)/CLOCKS_PER_SEC;
}
isStopped_ = true;
return realTimeElapsed_;
}
/*!
* \brief Stop the measurement reset all timing values
*/
void halt()
{
isStopped_ = true;
cpuTimeElapsed_ = 0.0;
realTimeElapsed_ = 0.0;
}
/*!
* \brief Make the current point in time t=0 but do not change the status of the timer.
*/
void reset()
{
cpuTimeElapsed_ = 0.0;
realTimeElapsed_ = 0.0;
measure_(startTime_);
}
/*!
* \brief Return the real time [s] elapsed during the periods the timer was active
* since the last reset.
*/
double realTimeElapsed() const
{
if (isStopped_)
return realTimeElapsed_;
TimeData stopTime;
measure_(stopTime);
const auto& t1 = startTime_.realtimeData;
const auto& t2 = stopTime.realtimeData;
std::chrono::duration<double> dt =
std::chrono::duration_cast<std::chrono::duration<double> >(t2 - t1);
return realTimeElapsed_ + dt.count();
}
/*!
* \brief This is an alias for realTimeElapsed()
*
* Its main purpose is to make the API of the class a superset of Dune::Timer
*/
double elapsed() const
{ return realTimeElapsed(); }
/*!
* \brief Return the CPU time [s] used by all threads of the local process for the
* periods the timer was active
*/
double cpuTimeElapsed() const
{
if (isStopped_)
return cpuTimeElapsed_;
TimeData stopTime;
measure_(stopTime);
const auto& t1 = startTime_.cputimeData;
const auto& t2 = stopTime.cputimeData;
return cpuTimeElapsed_ + static_cast<double>(t2 - t1)/CLOCKS_PER_SEC;
}
/*!
* \brief Return the CPU time [s] used by all threads of the all processes of program
*
* The value returned only differs from cpuTimeElapsed() if MPI is used.
*/
double globalCpuTimeElapsed() const
{
double val = cpuTimeElapsed();
double globalVal = val;
#if HAVE_MPI
MPI_Reduce(&val,
&globalVal,
/*count=*/1,
MPI_DOUBLE,
MPI_SUM,
/*rootRank=*/0,
MPI_COMM_WORLD);
#endif
return globalVal;
}
/*!
* \brief Adds the time of another timer to the current one
*/
Timer& operator+=(const Timer& other)
{
realTimeElapsed_ += other.realTimeElapsed();
cpuTimeElapsed_ += other.cpuTimeElapsed();
return *this;
}
private:
// measure the current time and put it into the object passed via
// the argument.
static void measure_(TimeData& timeData)
{
// Note: On Linux -- or rather fully POSIX compliant systems -- using
// clock_gettime() would be more accurate for the CPU time.
timeData.realtimeData = std::chrono::high_resolution_clock::now();
timeData.cputimeData = std::clock();
}
bool isStopped_;
double cpuTimeElapsed_;
double realTimeElapsed_;
TimeData startTime_;
};
} // namespace Opm
#endif

View File

@ -0,0 +1,58 @@
// -*- mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
// vi: set et ts=4 sw=4 sts=4:
/*
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 2 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/>.
Consult the COPYING file in the top-level source directory of this
module for the precise wording of the license and the list of
copyright holders.
*/
/*!
* \file
*
* \copydoc Opm::TimerGuard
*/
#ifndef EWOMS_TIMER_GUARD_HH
#define EWOMS_TIMER_GUARD_HH
#include "timer.hh"
namespace Opm {
/*!
* \ingroup Common
*
* \brief A simple class which makes sure that a timer gets stopped if an exception is
* thrown.
*/
class TimerGuard
{
public:
TimerGuard(Timer& timer)
: timer_(timer)
{ }
~TimerGuard()
{
timer_.stop();
}
private:
Timer& timer_;
};
} // namespace Opm
#endif

View File

@ -31,8 +31,8 @@
#include "residreductioncriterion.hh"
#include "linearsolverreport.hh"
#include <ewoms/common/timer.hh>
#include <ewoms/common/timerguard.hh>
#include <opm/models/utils/timer.hh>
#include <opm/models/utils/timerguard.hh>
#include <opm/material/common/Exceptions.hpp>

View File

@ -43,8 +43,8 @@
#ifndef EWOMS_ISTL_PRECONDITIONER_WRAPPERS_HH
#define EWOMS_ISTL_PRECONDITIONER_WRAPPERS_HH
#include <ewoms/common/propertysystem.hh>
#include <ewoms/common/parametersystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <dune/istl/preconditioners.hh>

View File

@ -43,8 +43,8 @@
#ifndef EWOMS_ISTL_SOLVER_WRAPPERS_HH
#define EWOMS_ISTL_SOLVER_WRAPPERS_HH
#include <ewoms/common/propertysystem.hh>
#include <ewoms/common/parametersystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <dune/istl/solvers.hh>

View File

@ -29,8 +29,8 @@
#include "convergencecriterion.hh"
#include <ewoms/common/timer.hh>
#include <ewoms/common/timerguard.hh>
#include <opm/models/utils/timer.hh>
#include <opm/models/utils/timerguard.hh>
namespace Opm {
namespace Linear {

View File

@ -36,9 +36,9 @@
#include <opm/simulators/linalg/parallelbasebackend.hh>
#include <opm/simulators/linalg/istlpreconditionerwrappers.hh>
#include <ewoms/common/genericguard.hh>
#include <ewoms/common/propertysystem.hh>
#include <ewoms/common/parametersystem.hh>
#include <opm/models/utils/genericguard.hh>
#include <opm/models/utils/propertysystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <opm/simulators/linalg/matrixblock.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>

View File

@ -30,7 +30,7 @@
#if HAVE_SUPERLU
#include <ewoms/linear/istlsparsematrixbackend.hh>
#include <ewoms/common/parametersystem.hh>
#include <opm/models/utils/parametersystem.hh>
#include <opm/material/common/Unused.hpp>

View File

@ -31,7 +31,7 @@
*/
#include "config.h"
#include <ewoms/common/propertysystem.hh>
#include <opm/models/utils/propertysystem.hh>
#include <iostream>