Commit 5d6a1f99 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Rewriting adaptive grid

parent c03faa46
......@@ -26,20 +26,35 @@ dune-2.6 ubuntu-18.04 clang-6-17:
- dunecontrol --current make -j4 examples
dune-git debian-10 gcc-8-17:
image: registry.dune-project.org/docker/ci/dune:git-debian-10-gcc-8-17
.dune-git:
before_script:
- . /duneci/bin/duneci-init-job
- duneci-install-module https://gitlab.dune-project.org/core/dune-common.git
- duneci-install-module https://gitlab.dune-project.org/core/dune-geometry.git
- duneci-install-module https://gitlab.dune-project.org/core/dune-localfunctions.git
- duneci-install-module https://gitlab.dune-project.org/staging/dune-uggrid.git
- duneci-install-module https://gitlab.dune-project.org/core/dune-grid.git
- duneci-install-module https://gitlab.dune-project.org/core/dune-istl.git
- duneci-install-module https://gitlab.dune-project.org/staging/dune-typetree.git
- duneci-install-module https://gitlab.dune-project.org/staging/dune-functions.git
script:
- duneci-standard-test
- dunecontrol --current make -j4 examples
dune-git debian-10 gcc-8-17:
extends: .dune-git
image: registry.dune-project.org/docker/ci/debian:10
variables:
DUNECI_TOOLCHAIN: gcc-8-17
dune-git debian-9 gcc-6-14:
image: registry.dune-project.org/docker/ci/dune:git-debian-9-gcc-6-14
script:
- duneci-standard-test
- dunecontrol --current make -j4 examples
extends: .dune-git
image: registry.dune-project.org/docker/ci/debian:9
variables:
DUNECI_TOOLCHAIN: gcc-6-14
dune-git ubuntu-18.04 clang-6-17:
image: registry.dune-project.org/docker/ci/dune:git-ubuntu-18.04-clang-6-17
script:
- duneci-standard-test
- dunecontrol --current make -j4 examples
extends: .dune-git
image: registry.dune-project.org/docker/ci/ubuntu:18.04
variables:
DUNECI_TOOLCHAIN: clang-6-17
This diff is collapsed.
......@@ -65,7 +65,7 @@ namespace AMDiS
public:
/// Constructor. Stores the shared_ptr of the basis and creates a new DataTransfer.
DOFVector(std::shared_ptr<GB> basis,
DOFVector(std::shared_ptr<GB> const& basis,
DataTransferOperation op = DataTransferOperation::INTERPOLATE)
: Super(basis)
, Obs(basis)
......
......@@ -43,10 +43,11 @@ namespace AMDiS
enum { dimworld = Grid::dimensionworld };
using ctype = typename Grid::ctype;
using HostGrid = typename AdaptiveGrid_t<Grid>::HostGrid;
/// Construct a new MeshCreator
/**
* \param name The name of the mesh used in the initifile
* \param name The name of the mesh used in the initfile
**/
MeshCreator(std::string const& name)
: name_(name)
......@@ -64,11 +65,11 @@ namespace AMDiS
*
* Otherwise tries to create a grid depending on the grid type.
**/
std::shared_ptr<AdaptiveGrid<Grid>> create() const
std::shared_ptr<Grid> create() const
{
auto filename = Parameters::get<std::string>(name_ + "->macro file name");
auto structured = Parameters::get<std::string>(name_ + "->structured");
std::shared_ptr<Grid> gridPtr;
std::unique_ptr<HostGrid> gridPtr;
if (filename) {
// read a macro file
gridPtr = create_unstructured_grid(filename.value());
......@@ -83,26 +84,26 @@ namespace AMDiS
}
} else {
// decide by inspecting the grid type how to create the grid
gridPtr = create_by_gridtype<Grid>(Dune::PriorityTag<42>{});
gridPtr = create_by_gridtype<HostGrid>(Dune::PriorityTag<42>{});
}
return AdaptiveGrid<Grid>::instance(gridPtr);
return construct(std::move(gridPtr));
}
/// Create a structured cube grid
std::unique_ptr<Grid> create_cube_grid() const
std::unique_ptr<HostGrid> create_cube_grid() const
{
return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells)
{
return Dune::StructuredGridFactory<Grid>::createCubeGrid(lower, upper, numCells);
return Dune::StructuredGridFactory<HostGrid>::createCubeGrid(lower, upper, numCells);
});
}
/// Create a structured simplex grid
std::unique_ptr<Grid> create_simplex_grid() const
std::unique_ptr<HostGrid> create_simplex_grid() const
{
return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells)
{
return Dune::StructuredGridFactory<Grid>::createSimplexGrid(lower, upper, numCells);
return Dune::StructuredGridFactory<HostGrid>::createSimplexGrid(lower, upper, numCells);
});
}
......@@ -119,9 +120,20 @@ namespace AMDiS
}
private:
static std::shared_ptr<Grid> construct(std::unique_ptr<Grid> hostGrid)
{
return std::move(hostGrid);
}
template <class HG>
static std::shared_ptr<Grid> construct(std::unique_ptr<HG> hostGrid)
{
return std::make_shared<Grid>(std::move(hostGrid));
}
// use the structured grid factory to create the grid
template <class Size = unsigned int, class Factory>
std::unique_ptr<Grid> create_structured_grid(Factory factory) const
std::unique_ptr<HostGrid> create_structured_grid(Factory factory) const
{
// Lower left corner of the domain
Dune::FieldVector<ctype,int(dimworld)> lower(0);
......@@ -137,16 +149,16 @@ namespace AMDiS
}
// read a filename from `[meshName]->macro file name` and determine from the extension the fileformat
std::unique_ptr<Grid> create_unstructured_grid(std::string const& filename) const
std::unique_ptr<HostGrid> create_unstructured_grid(std::string const& filename) const
{
filesystem::path fn(filename);
auto ext = fn.extension();
if (ext == ".msh") {
return read_gmsh_file<Grid>(filename, Dune::PriorityTag<42>{});
return read_gmsh_file<HostGrid>(filename, Dune::PriorityTag<42>{});
}
else if (ext == ".1d" || ext == ".2d" || ext == ".3d" || ext == ".amc") {
return read_alberta_file<Grid>(filename, Dune::PriorityTag<42>{});
return read_alberta_file<HostGrid>(filename, Dune::PriorityTag<42>{});
}
else {
error_exit("Cannot read grid file. Unknown file extension.");
......@@ -160,7 +172,7 @@ namespace AMDiS
std::declval<std::shared_ptr<Dune::BoundarySegment<GridType::dimension, GridType::dimensionworld> >>()) );
// use GmshReader if GridFactory supports insertBoundarySegments
template <class GridType = Grid,
template <class GridType = HostGrid,
REQUIRES(Dune::Std::is_detected<SupportsGmshReader, GridType>::value)>
std::unique_ptr<GridType> read_gmsh_file(std::string const& filename, Dune::PriorityTag<1>) const
{
......@@ -169,7 +181,7 @@ namespace AMDiS
}
// fallback if GmshReader cannot be used
template <class GridType = Grid>
template <class GridType = HostGrid>
std::unique_ptr<GridType> read_gmsh_file(std::string const& filename, Dune::PriorityTag<0>) const
{
error_exit("Gmsh reader not supported for this grid type!");
......@@ -183,7 +195,7 @@ namespace AMDiS
using IsAlbertaGrid = decltype(std::declval<GridType>().alberta2dune(0,0));
// construct the albertagrid directly from a filename
template <class GridType = Grid,
template <class GridType = HostGrid,
REQUIRES(GridType::dimensionworld == DIM_OF_WORLD),
REQUIRES(Dune::Std::is_detected<IsAlbertaGrid, GridType>::value)>
std::unique_ptr<GridType> read_alberta_file(std::string const& filename, Dune::PriorityTag<3>) const
......@@ -192,7 +204,7 @@ namespace AMDiS
}
// use a gridfactory and the generic AlbertaReader
template <class GridType = Grid,
template <class GridType = HostGrid,
REQUIRES(GridType::dimensionworld == DIM_OF_WORLD)>
std::unique_ptr<GridType> read_alberta_file(std::string const& filename, Dune::PriorityTag<2>) const
{
......@@ -205,7 +217,7 @@ namespace AMDiS
}
// error if WORLDDIM not the same as Grid::dimensionworld
template <class GridType = Grid,
template <class GridType = HostGrid,
REQUIRES(GridType::dimensionworld != DIM_OF_WORLD)>
std::unique_ptr<GridType> read_alberta_file(std::string const& filename, Dune::PriorityTag<1>) const
{
......@@ -225,19 +237,19 @@ namespace AMDiS
#if HAVE_ALBERTA
// albertagrid -> simplex
template <class GridType = Grid,
template <class GridType = HostGrid,
REQUIRES(Dune::Std::is_detected<IsAlbertaGrid, GridType>::value)>
std::unique_ptr<GridType> create_by_gridtype(Dune::PriorityTag<3>) const
{
return create_structured_grid([](auto&& lower, auto&& upper, auto&& numCells)
{
return MacroGridFactory<Grid>::createSimplexGrid(lower, upper, numCells);
return MacroGridFactory<GridType>::createSimplexGrid(lower, upper, numCells);
});
}
#endif
// yasp grid -> cube
template <class GridType = Grid,
template <class GridType = HostGrid,
class = typename GridType::YGrid>
std::unique_ptr<GridType> create_by_gridtype(Dune::PriorityTag<2>) const
{
......@@ -250,27 +262,27 @@ namespace AMDiS
}
template <int dim, class ct>
std::unique_ptr<Grid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::EquidistantCoordinates<ct,dim>>>,
std::unique_ptr<HostGrid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::EquidistantCoordinates<ct,dim>>>,
int overlap, std::bitset<dimension> const& per) const
{
return create_structured_grid<int>([&](auto&& /*lower*/, auto&& upper, std::array<int,dimension> const& numCells)
{
return std::make_unique<Grid>(upper, numCells, per, overlap);
return std::make_unique<HostGrid>(upper, numCells, per, overlap);
});
}
template <int dim, class ct>
std::unique_ptr<Grid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::EquidistantOffsetCoordinates<ct,dim>>>,
std::unique_ptr<HostGrid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::EquidistantOffsetCoordinates<ct,dim>>>,
int overlap, std::bitset<dimension> const& per) const
{
return create_structured_grid<int>([&](auto&& lower, auto&& upper, std::array<int,dimension> const& numCells)
{
return std::make_unique<Grid>(lower, upper, numCells, per, overlap);
return std::make_unique<HostGrid>(lower, upper, numCells, per, overlap);
});
}
template <int dim, class ct>
std::unique_ptr<Grid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::TensorProductCoordinates<ct,dim>>>,
std::unique_ptr<HostGrid> create_yaspgrid(Types<Dune::YaspGrid<dim,Dune::TensorProductCoordinates<ct,dim>>>,
int overlap, std::bitset<dimension> const& per) const
{
error_exit("MeshCreator cannot create YaspGrid with TensorProductCoordinates.");
......@@ -280,7 +292,7 @@ namespace AMDiS
#if HAVE_DUNE_SPGRID
// spgrid -> cube
template <class GridType = Grid,
template <class GridType = HostGrid,
class = typename GridType::ReferenceCube,
class = typename GridType::MultiIndex>
std::unique_ptr<GridType> create_by_gridtype(Dune::PriorityTag<1>) const
......@@ -294,7 +306,7 @@ namespace AMDiS
#endif
// final fallback
template <class GridType = Grid>
template <class GridType = HostGrid>
std::unique_ptr<GridType> create_by_gridtype(Dune::PriorityTag<0>) const
{
error_exit("Don't know how to create the grid.");
......
......@@ -5,6 +5,8 @@
#include <memory>
#include <type_traits>
#include <dune/common/typeutilities.hh>
#include <amdis/common/ConceptsBase.hpp>
#include <amdis/Output.hpp>
......@@ -12,135 +14,128 @@ namespace AMDiS
{
namespace Impl
{
// Forward declaration
// forward declaration
template <class Event>
class SignalInterface;
class ObserverInterface;
template <class Event>
class ObserverInterface
class SignalBase
{
public:
virtual ~ObserverInterface() = default;
/// Attach the observer to a subject. It will then receive notifications from the subject when
/// an event of type Event it triggered.
void attach(std::shared_ptr<SignalInterface<Event>> const& subject)
/// Attaches an observer to this class. This method will be called by all observers with
/// with themselves as argument.
void attachObserver(ObserverInterface<Event>* o) const
{
subject->attachObserver(this);
observers_.push_back(o);
}
/// Detach the observer from the subject. It will then no longer receive notifications. This
/// must be called before the observer is deleted.
void detach(std::shared_ptr<SignalInterface<Event>> const& subject)
/// Detaches an observer to this class. This method will be called by all observers with
/// with themselves as argument.
void detachObserver(ObserverInterface<Event>* o) const
{
subject->detachObserver(this);
auto it = std::find(observers_.begin(), observers_.end(), o);
if (it != observers_.end())
observers_.erase(it);
}
/// This method will be called by the subject when triggering the event.
virtual void update(Event const&)
/// Notify all observers that have called attachObserver but have not called detachObserver
void notify(Event const& e) const
{
error_exit("Method must be overridden by derived class");
for (ObserverInterface<Event>* o : observers_)
o->update(e);
}
};
template <class Event>
class SignalInterface
{
public:
virtual ~SignalInterface() = default;
/// Attaches an observer to this class. This method will be called by all observers with
/// with themselves as argument.
virtual void attachObserver(ObserverInterface<Event>*) = 0;
/// Detaches an observer to this class. This method will be called by all observers with
/// with themselves as argument.
virtual void detachObserver(ObserverInterface<Event>*) = 0;
/// Notify all observers that have called attachObserver but have not called detachObserver
virtual void notify(Event const&) const = 0;
private:
/// List of observers that need to be notified in case of an event
// NOTE: this list is mutable, since the notification list itself is not part
// of the internal state of the object signaling the event.
mutable std::list<ObserverInterface<Event>*> observers_;
};
template <class Event>
class SignalsImpl
: virtual public SignalInterface<Event>
class ObserverInterface
{
public:
virtual ~SignalsImpl() = default;
virtual ~ObserverInterface() = default;
void attachObserver(ObserverInterface<Event>* o) override
/// Attach the observer to a subject. It will then receive notifications from the subject when
/// an event of type Event it triggered.
void attach(std::shared_ptr<SignalBase<Event> const> const& subject)
{
observers_.push_back(o);
if (bool(subject))
subject->attachObserver(this);
}
void detachObserver(ObserverInterface<Event>* o) override
/// Detach the observer from the subject. It will then no longer receive notifications. This
/// must be called before the observer is deleted.
void detach(std::shared_ptr<SignalBase<Event> const> const& subject)
{
auto it = std::find(observers_.begin(), observers_.end(), o);
if (it != observers_.end())
observers_.erase(it);
if (bool(subject))
subject->detachObserver(this);
}
void notify(Event const& e) const override
/// This method will be called by the subject when triggering the event.
virtual void update(Event const&)
{
for (ObserverInterface<Event>* o : observers_)
o->update(e);
error_exit("Method must be overridden by derived class");
}
private:
std::list<ObserverInterface<Event>*> observers_;
};
template <class Event>
class SignalsDummy
: virtual public SignalInterface<Event>
{
public:
virtual ~SignalsDummy() = default;
void attachObserver(ObserverInterface<Event>* o) override {}
void detachObserver(ObserverInterface<Event>* o) override {}
void notify(Event const& e) const override {}
};
template <class Event>
class ObserverImpl
class ObserverBase
: virtual public ObserverInterface<Event>
{
using Self = ObserverImpl;
using Self = ObserverBase;
ObserverImpl()
: subject_(std::make_shared<SignalsDummy<Event>>())
{}
private:
ObserverBase() = default;
public:
ObserverImpl(std::shared_ptr<SignalInterface<Event>> subject)
// use subject if Event is handled directly
template <class S,
REQUIRES(std::is_base_of<SignalBase<Event>, S>::value)>
ObserverBase(std::shared_ptr<S const> subject, Dune::PriorityTag<2>)
: subject_(std::move(subject))
{
this->attach(subject_);
}
// Get next subject in hierarchy if Event is not handled
template <class Subject,
REQUIRES(!std::is_convertible<std::shared_ptr<Subject>, std::shared_ptr<SignalInterface<Event>>>::value)>
ObserverImpl(std::shared_ptr<Subject> subject)
: Self(subject->getSubject())
// get next subject in hierarchy if Event is not handled
template <class Observer,
class = void_t<decltype(std::declval<Observer>().subject_)> >
ObserverBase(std::shared_ptr<Observer const> const& o, Dune::PriorityTag<1>)
: ObserverBase(o->subject_)
{}
// non-observable type
template <class T>
ObserverBase(std::shared_ptr<T const> const& other, Dune::PriorityTag<0>)
{
/* fallback implementation */
}
public:
template <class T>
ObserverBase(std::shared_ptr<T const> const& arg)
: ObserverBase(arg, Dune::PriorityTag<42>{})
{}
/// Copy constructor
ObserverImpl(Self const& that)
ObserverBase(Self const& that)
: subject_(that.subject_)
{
this->attach(subject_);
}
/// Move constructor
ObserverImpl(Self&& that)
: ObserverImpl()
ObserverBase(Self&& that)
{
swap(*this, that);
}
/// Destructor. Detaches observer from the subject
virtual ~ObserverImpl()
~ObserverBase() override
{
this->detach(subject_);
}
......@@ -165,11 +160,14 @@ namespace AMDiS
private:
/// The observed subject
std::shared_ptr<SignalInterface<Event>> subject_;
std::shared_ptr<SignalBase<Event> const> subject_ = nullptr;
};
}
/** Mixin for signaling of certain events.
} // end namespace Impl
/// \brief Mixin for signaling of certain events.
/**
* Derived classes T can emit a signal e by calling notify(e). This will send the signal to all
* classes U... deriving from Observer<S, Events...> if
* - the type of the event is included in Events,
......@@ -179,54 +177,56 @@ namespace AMDiS
*/
template <class Event, class... Events>
class Signals
: public Impl::SignalsImpl<Event>
: public Impl::SignalBase<Event>
, public Signals<Events...>
{
public:
using Impl::SignalsImpl<Event>::notify;
using Impl::SignalBase<Event>::notify;
using Signals<Events...>::notify;
};
template <class Event>
class Signals<Event>
: public Impl::SignalsImpl<Event>
: public Impl::SignalBase<Event>
{
public:
using Impl::SignalsImpl<Event>::notify;
using Impl::SignalBase<Event>::notify;
};
/** Mixin for reacting to certain events
* Derived classes T can react to events by implementing the functions update(Event& e) for
/// \brief Mixin for reacting to certain events.
/**
* Derived classes can react to events by implementing the functions `update(Event)` for
* all Events specified in the template parameter list, whose origin is an instance of class
* Subject specified in the constructor to Observer and any indirectly observed class instances.
* `Subject` specified in the constructor to Observer and any indirectly observed class instances.
* Observed instances may include:
* - the instance of class Subject passed to the constructor
* - the instance passed to the constructor of Subject::Observer<S> if Subject inherits from
* Observer<S>
* - all other instances indirectly accesible in the above way
* For each event E the first object in the above hierarchy that implements Signals<Es> with E
* included in Es will be observed by this class.
* - the instance of class `Subject` passed to the constructor
* - the instance passed to the constructor of `Subject::Observer<S>` if Subject inherits from
* \ref Observer<S>
* - all other instances indirectly accessible in the above way
*
* For each event E the first object in the above hierarchy that implements \ref Signals<Es...> with E
* included in Es... will be observed by this class.
*/
template <class Subject, class... Events>
class Observer
: public Impl::ObserverImpl<Events>...
: public Impl::ObserverBase<Events>...
{
template <class E>
friend class Impl::ObserverImpl;
friend class Impl::ObserverBase;
public:
Observer(std::shared_ptr<Subject> s)
: Impl::ObserverImpl<Events>(s)...
Observer(std::shared_ptr<Subject const> const& s)
: Impl::ObserverBase<Events>(s)...
, subject_(std::move(s))
{}
private:
/// Get the direct subject of this instance. Used by the implementation to move upwards in the
/// observer hierarchy.
std::shared_ptr<Subject> const& getSubject() { return subject_; }
Observer(std::shared_ptr<Subject> const& s)
: Observer(std::const_pointer_cast<Subject const>(s))
{}
std::shared_ptr<Subject> subject_;
private:
std::shared_ptr<Subject const> subject_ = nullptr;
};
} // end namespace AMDiS
......@@ -66,9 +66,7 @@ namespace AMDiS
using GlobalBasis = typename Traits::GlobalBasis;
using GridView = typename GlobalBasis::GridView;
// TODO(FM): Make this GridView::Grid::HostGrid as soon as AdaptiveGrid is a complete metagrid
using HostGrid = typename GridView::Grid;
using Grid = AdaptiveGrid<HostGrid>;
using Grid = AdaptiveGrid_t<typename GridView::Grid>;
using Element = typename GridView::template Codim<0>::Entity;
using WorldVector = typename Element::Geometry::GlobalCoordinate;
using WorldMatrix = FieldMatrix<typename WorldVector::field_type, WorldVector::dimension, WorldVector::dimension>;
......@@ -102,13 +100,13 @@ namespace AMDiS
ProblemStat(std::string const& name, Grid_&& grid)
: ProblemStat(name)
{
adoptGrid(Grid::instance(FWD(grid)));
adoptGrid(wrap_or_share(FWD(grid)));
}
/// \brief Constructor taking a grid and basis
/// Wraps both in shared pointers.
template <class Grid_, class GB>
ProblemStat(std::string const& name, Grid_&& grid, GB&& globalBasis)
template <class Grid_, class Basis_>
ProblemStat(std::string const& name, Grid_&& grid, Basis_&& globalBasis)