Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • amdis/amdis-core
  • s5272799/amdis-core
  • joun738c/amdis-core
3 results
Show changes
Commits on Source (19)
Showing
with 473 additions and 72 deletions
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_FLAGS "-pedantic-errors")
# fold expressions (a + ...)
check_cxx_source_compiles("
template <class... Args>
......@@ -53,3 +55,5 @@ check_cxx_source_compiles("
}
" AMDIS_HAS_CXX_AUTO_TEMPLATE_PARAMETER
)
unset(CMAKE_REQUIRED_FLAGS)
\ No newline at end of file
include(AmdisCXXFeatures)
include(AddAmdisExecutable)
set(BACKEND "ISTL" CACHE STRING "LinearAlgebra backend. One of MTL, EIGEN, ISTL")
set_property(CACHE BACKEND PROPERTY STRINGS "MTL" "EIGEN" "ISTL")
if (NOT BACKEND)
set(BACKEND "ISTL" CACHE STRING "LinearAlgebra backend. One of MTL, EIGEN, PETSC, ISTL")
set_property(CACHE BACKEND PROPERTY STRINGS "MTL" "EIGEN" "ISTL" "PETSC")
endif (NOT BACKEND)
if (BACKEND STREQUAL "MTL" OR BACKEND STREQUAL "MTL4")
find_package(MTL REQUIRED)
set(HAVE_MTL MTL_FOUND)
set(HAVE_MTL TRUE)
if (MTL_FOUND)
message(STATUS " Found MTL, version: ${MTL_VERSION}")
dune_register_package_flags(LIBRARIES MTL::MTL COMPILE_DEFINITIONS "ENABLE_MTL=1")
endif (MTL_FOUND)
elseif (BACKEND STREQUAL "EIGEN" OR BACKEND STREQUAL "EIGEN3")
find_package(Eigen3 REQUIRED 3.3.5)
set(HAVE_EIGEN EIGEN_FOUND)
set(HAVE_EIGEN TRUE)
if (EIGEN3_FOUND)
message(STATUS " Found Eigen3, version: ${Eigen3_VERSION}")
dune_register_package_flags(LIBRARIES Eigen3::Eigen COMPILE_DEFINITIONS "ENABLE_EIGEN=1")
endif (EIGEN3_FOUND)
elseif (BACKEND STREQUAL "PETSC")
find_package(PETSc REQUIRED)
if (PETSc_FOUND)
set(HAVE_PETSC TRUE)
dune_register_package_flags(LIBRARIES PETSc::PETSc COMPILE_DEFINITIONS "ENABLE_PETSC=1")
endif (PETSc_FOUND)
elseif (BACKEND STREQUAL "ISTL")
if (NOT dune-istl_FOUND)
message(FATAL_ERROR "Need dune-istl, MTL, or Eigen3 as linear algebra backend. Change flag BACKEND!")
message(FATAL_ERROR "Need dune-istl, MTL, PETSc, or Eigen3 as linear algebra backend. Change flag BACKEND!")
endif ()
else ()
message(FATAL_ERROR "BACKEND must be one of MTL, EIGEN, ISTL")
message(FATAL_ERROR "BACKEND must be one of MTL, EIGEN, PETSC, ISTL")
endif ()
set(DUNE_CUSTOM_PKG_CONFIG_SECTION "set(BACKEND \"${BACKEND}\")")
\ No newline at end of file
......@@ -22,6 +22,7 @@ find_path(MTL_INCLUDE_DIR boost/numeric/mtl/mtl.hpp
${CMAKE_CURRENT_SOURCE_DIR}/../../libs/mtl4
${CMAKE_CURRENT_SOURCE_DIR}/../../include/mtl4
${MTL_DIR}/../../include
$ENV{MTL_DIR}/../../include
ENV EBROOTMTL
PATHS
/opt/software/mtl
......
# FindPETSc.cmake
#
# Finds the PETSc library
#
# This will define the following variables
#
# PETSc_FOUND
# PETSc_VERSION
#
# and the following imported targets
#
# PETSc::PETSc
#
# Author: Simon Praetorius <simon.praetorius@tu-dresden.de>
include(FindPkgConfig)
if (NOT PKG_CONFIG_FOUND)
message(FATAL_ERROR "Can not find PkgConfig!")
endif()
mark_as_advanced(PETSc_FOUND PETSc_VERSION PETSC_PKG_CONFIG)
find_path(PETSC_PKG_CONFIG "PETSc.pc"
HINTS
${PETSC_DIR}
${PETSC_ROOT}
ENV PETSC_DIR
ENV PETSC_ROOT
ENV PKG_CONFIG_PATH
PATHS
/etc/alternatives
/usr/lib/petsc
/usr/lib/petsc/linux-gnu-cxx-opt
/usr/lib/petsc/linux-gnu-c-opt
PATH_SUFFIXES lib/pkgconfig/
)
if (PETSC_PKG_CONFIG)
set(ENV{PKG_CONFIG_PATH} "${PETSC_PKG_CONFIG}:$ENV{PKG_CONFIG_PATH}")
endif (PETSC_PKG_CONFIG)
if (PETSc_FIND_VERSION)
pkg_check_modules(PETSC PETSc>=${PETSc_FIND_VERSION})
else ()
pkg_check_modules(PETSC PETSc)
endif ()
if (PETSC_STATIC_FOUND)
set(_prefix PETSC_STATIC)
elseif (PETSC_FOUND)
set(_prefix PETSC)
endif ()
set(PETSc_VERSION "${${_prefix}_VERSION}")
if ((PETSC_STATIC_FOUND OR PETSC_FOUND) AND NOT TARGET PETSc::PETSc)
add_library(PETSc::PETSc INTERFACE IMPORTED GLOBAL)
if (${_prefix}_INCLUDE_DIRS)
set_property(TARGET PETSc::PETSc PROPERTY
INTERFACE_INCLUDE_DIRECTORIES "${${_prefix}_INCLUDE_DIRS}")
endif ()
if (${_prefix}_LINK_LIBRARIES)
set_property(TARGET PETSc::PETSc PROPERTY
INTERFACE_LINK_LIBRARIES "${${_prefix}_LINK_LIBRARIES}")
else ()
# extract the absolute paths of link libraries from the LDFLAGS
include(PkgConfigLinkLibraries)
pkg_config_link_libraries(${_prefix} _libs)
set_property(TARGET PETSc::PETSc PROPERTY
INTERFACE_LINK_LIBRARIES "${_libs}")
unset(_libs)
endif ()
if (${_prefix}_LDFLAGS_OTHER)
set_property(TARGET PETSc::PETSc PROPERTY
INTERFACE_LINK_OPTIONS "${${_prefix}_LDFLAGS_OTHER}")
endif ()
if (${_prefix}_CFLAGS_OTHER)
set_property(TARGET PETSc::PETSc PROPERTY
INTERFACE_COMPILE_OPTIONS "${${_prefix}_CFLAGS_OTHER}")
endif ()
endif ()
unset(_prefix)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PETSc
REQUIRED_VARS PETSc_VERSION
VERSION_VAR PETSc_VERSION
)
# text for feature summary
set_package_properties("PETSc" PROPERTIES
DESCRIPTION "Portable, Extensible Toolkit for Scientific Computation")
\ No newline at end of file
# PkgConfigLinkLibraries.cmake
#
# Scan the LDFLAGS returned by pkg-config for library directories and
# libraries and figure out the absolute paths of that libraries in the
# given directories.
#
# This macro is extracted from FindPkgConfig.cmake
#
# This will define the following macro
#
# pkg_config_link_libraries(PREFIX, OUTPUT)
#
# .. cmake_macro:: pkg_config_link_libraries
#
# .. cmake_brief::
#
# Creates a list ob absolute path for link libraries
#
# .. cmake_param:: PREFIX
# :single:
#
# The module prefix (including _STATIC for static libraries)
#
# .. cmake_param:: OUTPUT
# :single:
#
# The name of the output list of absolute paths
#
#
# Author: Simon Praetorius <simon.praetorius@tu-dresden.de>
macro(pkg_config_link_libraries _prefix _output)
unset(_search_paths)
foreach (flag IN LISTS ${_prefix}_LDFLAGS)
if (flag MATCHES "^-L(.*)")
list(APPEND _search_paths ${CMAKE_MATCH_1})
continue()
endif()
if (flag MATCHES "^-l(.*)")
set(_pkg_search "${CMAKE_MATCH_1}")
else()
continue()
endif()
if(_search_paths)
# Firstly search in -L paths
find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
NAMES ${_pkg_search}
HINTS ${_search_paths} NO_DEFAULT_PATH)
endif()
find_library(pkgcfg_lib_${_prefix}_${_pkg_search}
NAMES ${_pkg_search}
${_find_opts})
list(APPEND ${_output} "${pkgcfg_lib_${_prefix}_${_pkg_search}}")
endforeach()
endmacro(pkg_config_link_libraries)
\ No newline at end of file
......@@ -40,12 +40,15 @@
/* Define to the revision of amdis */
#define AMDIS_VERSION_REVISION @AMDIS_VERSION_REVISION@
/* Define to ENABLE_MTL if the MTL library is available */
/* Define to true if the MTL library is available */
#cmakedefine HAVE_MTL 1
/* Define to ENABLE_EIGEN if the Eigen3 library is available */
/* Define to true if the Eigen3 library is available */
#cmakedefine HAVE_EIGEN 1
/* Define to true if the PETSc library is available */
#cmakedefine HAVE_PETSC ENABLE_PETSC
/* some detected compiler features may be used in AMDiS */
#cmakedefine AMDIS_HAS_CXX_FOLD_EXPRESSIONS 1
#cmakedefine AMDIS_HAS_CXX_CONSTEXPR_IF 1
......
......@@ -71,6 +71,7 @@ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis)
add_subdirectory("common")
add_subdirectory("functions")
add_subdirectory("gridfunctions")
add_subdirectory("io")
add_subdirectory("linearalgebra")
add_subdirectory("localoperators")
add_subdirectory("operations")
......
......@@ -17,10 +17,9 @@
#include <dune/grid/common/geometry.hh>
#include <dune/grid/common/rangegenerators.hh>
#include <dune/functions/common/functionfromcallable.hh>
#include <amdis/Output.hpp>
#include <amdis/common/ConcurrentCache.hpp>
#include <amdis/functions/FunctionFromCallable.hpp>
#include <amdis/typetree/Traversal.hpp>
namespace AMDiS {
......@@ -373,9 +372,8 @@ bool NodeDataTransfer<N,C,B>::
return fatherDOFsTemp_[currentDOF++];
};
using FFC
= Dune::Functions::FunctionFromCallable<LIRangeType(LIDomainType), decltype(evalLeaf)>;
fatherFE.localInterpolation().interpolate(FFC(evalLeaf), fatherDOFs);
auto evalLeafFct = functionFromCallable<LIRangeType(LIDomainType)>(evalLeaf);
fatherFE.localInterpolation().interpolate(evalLeafFct, fatherDOFs);
// Return true if all father DOFs have been evaluated
return std::accumulate(finishedDOFs_.begin(), finishedDOFs_.end(), true,
......@@ -413,9 +411,8 @@ void NodeDataTransfer<N,C,B>::
auto const& childFE = childNode.finiteElement();
thread_local std::vector<T> childDOFs;
using FFC = Dune::Functions
::FunctionFromCallable<LIRangeType(LIDomainType), decltype(evalFather)>;
childFE.localInterpolation().interpolate(FFC(evalFather), childDOFs);
auto evalFatherFct = functionFromCallable<LIRangeType(LIDomainType)>(evalFather);
childFE.localInterpolation().interpolate(evalFatherFct, childDOFs);
for (std::size_t i = 0; i < childDOFs.size(); ++i)
(*coeff_)[lv_->index(childNode.localIndex(i))] = childDOFs[i];
......
......@@ -4,6 +4,10 @@
#include "Environment.hpp"
#if HAVE_PETSC
#include <petscsys.h>
#endif
// AMDiS includes
#include <amdis/Initfile.hpp>
#include <amdis/Output.hpp>
......@@ -17,13 +21,17 @@ namespace AMDiS
Parameters::init(initFileName);
}
Environment::Environment(int& argc, char**& argv, std::string const& initFileName)
: Environment(initFileName)
{
auto& helper = Dune::MPIHelper::instance(argc, argv);
#if HAVE_PETSC
PetscInitialize(&argc, &argv, PETSC_NULL, PETSC_NULL);
petscInitialized_ = true;
#endif
auto& mpi = Mpi::instance();
mpi.registerMpiHelper(helper);
mpi.registerMpiHelper(Dune::MPIHelper::instance(argc, argv));
Parameters::clearData();
if (initFileName.empty()) {
......@@ -34,4 +42,13 @@ namespace AMDiS
}
}
Environment::~Environment()
{
#if HAVE_PETSC
if (petscInitialized_)
PetscFinalize();
#endif
}
} // end namespace AMDiS
......@@ -56,6 +56,9 @@ namespace AMDiS
/// or the provided initfile filename.
Environment(int& argc, char**& argv, std::string const& initFileName = "");
/// Finishes MPI and PETSc
~Environment();
/// Return the MPI_Rank of the current processor.
static int mpiRank()
{
......@@ -67,6 +70,15 @@ namespace AMDiS
{
return Mpi::instance().size();
}
/// Return the MPI_Comm object (or a fake communicator)
static typename Dune::MPIHelper::MPICommunicator comm()
{
return Dune::MPIHelper::getCommunicator();
}
private:
bool petscInitialized_ = false;
};
} // end namespace AMDiS
......@@ -5,8 +5,7 @@
#include <dune/functions/functionspacebases/lagrangebasis.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
#include <dune/grid/io/file/vtk/vtksequencewriter.hh>
//#include <dune/geometry/referenceelements.hh>
#include <dune/grid/io/file/vtk/subsamplingvtkwriter.hh>
#include <dune/typetree/childextraction.hh>
#include <amdis/FileWriterInterface.hpp>
......@@ -15,6 +14,7 @@
#include <amdis/common/StaticSize.hpp>
#include <amdis/common/ValueCategory.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/io/VTKSequenceWriter.hpp>
namespace AMDiS
{
......@@ -86,9 +86,11 @@ namespace AMDiS
vtkWriter_ = std::make_shared<Dune::VTKWriter<GridView>>(gridView());
if (animation_)
vtkSeqWriter_ = std::make_shared<Dune::VTKSequenceWriter<GridView>>(vtkWriter_, filename_, dir_, "");
vtkSeqWriter_ = std::make_shared<VTKSequenceWriter<GridView>>(vtkWriter_);
vtkWriter_->addVertexData(discreteFct_, Dune::VTK::FieldInfo(name_, VTKFieldType<Range>, VTKFieldSize<Range>));
test_exit(dir_ == "." || filesystem::exists(dir_), "Output directory '{}' does not exist!",dir_);
}
void init(std::string const&, tag::unknown) {}
......@@ -96,12 +98,11 @@ namespace AMDiS
/// Implements \ref FileWriterInterface::writeFiles
void writeFiles(AdaptInfo& adaptInfo, bool force) override
{
test_exit(dir_ == "." || filesystem::exists(dir_), "Output directory '{}' does not exist!",dir_);
filesystem::create_directories(dir_ + "/_piecefiles");
if (vtkSeqWriter_)
vtkSeqWriter_->write(adaptInfo.time(), mode_);
vtkSeqWriter_->pwrite(adaptInfo.time(), filename_, dir_, "_piecefiles", mode_);
else if (vtkWriter_)
vtkWriter_->write(filesystem::path({dir_, filename_}).string(), mode_);
vtkWriter_->pwrite(filename_, dir_, "_piecefiles", mode_);
}
protected:
......@@ -114,7 +115,7 @@ namespace AMDiS
DiscreteFunction<GB,VT,TP> discreteFct_;
std::shared_ptr<Dune::VTKWriter<GridView>> vtkWriter_;
std::shared_ptr<Dune::VTKSequenceWriter<GridView>> vtkSeqWriter_;
std::shared_ptr<VTKSequenceWriter<GridView>> vtkSeqWriter_;
// write .pvd if animation=true, otherwise write only .vtu
bool animation_;
......
......@@ -67,12 +67,12 @@ void InitfileParser::readInitfile(std::istream& in, Dune::ParameterTree& pt, boo
std::size_t pos = sw.find_first_not_of(whitespaces, pos0 + std::string("#include").size() + 1);
std::size_t epos = 0;
std::string fn = "";
std::map<char,char> closing = { {'<','>'}, {'\"', '\"'} };
switch (char c = swap[pos++]) {
case '<':
c= '>';
// [[fallthrough]];
case '\"':
delimiter += c;
delimiter += closing[c];
epos = sw.find_first_of(delimiter, pos);
fn = sw.substr(pos, epos - pos);
......
......@@ -14,14 +14,11 @@
#include <stdexcept>
#endif
#ifdef HAVE_MPI
#include <mpi.h>
#endif
/// Use the formatting librart fmtlib::fmt
#include <fmt/core.h>
#include <fmt/ostream.h>
#include <amdis/Environment.hpp>
#include <amdis/common/TypeTraits.hpp>
/**
......@@ -41,6 +38,11 @@
#endif
#endif
/// Level bound for output of additional information. See \ref info() and \ref info_()
#ifndef AMDIS_INFO_LEVEL
#define AMDIS_INFO_LEVEL 1
#endif
#define AMDIS_UNUSED(var) __attribute__((unused)) var
#define AMDIS_FUNCNAME(nn) AMDIS_UNUSED(const char *funcName); funcName = nn;
......@@ -59,23 +61,27 @@ namespace AMDiS
namespace Impl
{
template <class OStream, class... Args>
OStream& msg(OStream& out, Args&&... args)
OStream& msg_all(OStream& out, std::string const& str, Args&&... args)
{
if (Environment::mpiSize() > 1)
fmt::print(out, "[" + std::to_string(Environment::mpiRank()) + "] " + str, FWD(args)...);
else
fmt::print(out, str, FWD(args)...);
return out;
}
template <class OStream, class... Args>
OStream& msg(OStream& out, std::string const& str, Args&&... args)
{
#ifdef AMDIS_HAS_MPI
int rank = -1;
int num_ranks = -1;
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &num_ranks);
if (num_ranks > 1 && rank == 0) {
out << "[0] ";
fmt::print(out, FWD(args)...);
} else if (num_ranks == 1) {
fmt::print(out, FWD(args)...);
}
#ifdef AMDIS_MSG_ALL_RANKS
return msg_all(out, str, FWD(args)...);
#else
fmt::print(out, FWD(args)...);
#endif
if (Environment::mpiSize() > 1 && Environment::mpiRank() == 0)
fmt::print(out, "[0] " + str, FWD(args)...);
else if (Environment::mpiSize() == 1)
fmt::print(out, str, FWD(args)...);
return out;
#endif
}
} // end namespace Impl
......@@ -89,9 +95,17 @@ namespace AMDiS
* ```
**/
template <class... Args>
void msg(Args&&... args)
void msg(std::string const& str, Args&&... args)
{
Impl::msg(std::cout, str + "\n", FWD(args)...);
}
/// prints a message, if Environment::infoLevel() >= noInfoLevel
template <class... Args>
void info(int noInfoLevel, std::string const& str, Args&&... args)
{
Impl::msg(std::cout, FWD(args)...) << std::endl;
if (int(AMDIS_INFO_LEVEL) >= noInfoLevel)
Impl::msg(std::cout, str + "\n", FWD(args)...);
}
......@@ -103,11 +117,20 @@ namespace AMDiS
* ```
**/
template <class... Args>
void msg_(Args&&... args)
void msg_(std::string const& str, Args&&... args)
{
Impl::msg(std::cout, FWD(args)...);
Impl::msg(std::cout, str, FWD(args)...);
}
/// prints a message, if Environment::infoLevel() >= noInfoLevel
template <class... Args>
void info_(int noInfoLevel, std::string const& str, Args&&... args)
{
if (int(AMDIS_INFO_LEVEL) >= noInfoLevel)
Impl::msg(std::cout, str, FWD(args)...);
}
/// \brief print a message and exit
/**
......@@ -116,17 +139,13 @@ namespace AMDiS
* type \ref std::runtime_Error is thrown.
**/
template <class... Args>
void error_exit(Args&&... args)
void error_exit(std::string const& str, Args&&... args)
{
#ifdef AMDIS_NO_THROW
Impl::msg(std::cerr << "ERROR: ", FWD(args)...) << std::endl;
#ifndef NDEBUG
assert(false);
#else
std::exit(EXIT_FAILURE);
#endif
Impl::msg_all(std::cerr, "ERROR: " + str + "\n", FWD(args)...);
std::abort();
#else
throw std::runtime_error( std::string("ERROR: ") + fmt::format(FWD(args)...));
throw std::runtime_error( std::string("ERROR: ") + fmt::format(str, FWD(args)...));
#endif
}
......@@ -141,16 +160,16 @@ namespace AMDiS
* \p condition argument.
**/
template <class... Args>
void test_exit(bool condition, Args&&... args)
void test_exit(bool condition, std::string const& str, Args&&... args)
{
if (!condition) { error_exit(FWD(args)...); }
if (!condition) { error_exit(str, FWD(args)...); }
}
template <class... Args>
void warning(Args&&... args)
void warning(std::string const& str, Args&&... args)
{
Impl::msg(std::cout << "WARNING: ", FWD(args)...) << std::endl;
Impl::msg(std::cout, "WARNING: " + str + "\n", FWD(args)...);
}
......@@ -161,9 +180,9 @@ namespace AMDiS
* string "WARNING".
**/
template <class... Args>
void test_warning(bool condition, Args&&... args)
void test_warning(bool condition, std::string const& str, Args&&... args)
{
if (!condition) { warning(FWD(args)...); }
if (!condition) { warning(str, FWD(args)...); }
}
......
......@@ -211,9 +211,8 @@ coords(Node const& tree, std::vector<std::size_t> const& localIndices) const
std::array<std::vector<typename RangeType::field_type>, D::dimension> coeffs;
for (int d = 0; d < D::dimension; ++d) {
auto evalCoord = [&](DomainType const& local) -> RangeType { return geometry.global(local)[d]; };
using FFC = Dune::Functions::FunctionFromCallable<RangeType(DomainType), decltype(evalCoord)>;
localInterpol.interpolate(FFC(evalCoord), coeffs[d]);
auto evalCoord = functionFromCallable<RangeType(DomainType)>([&](DomainType const& local) -> RangeType { return geometry.global(local)[d]; });
localInterpol.interpolate(evalCoord, coeffs[d]);
}
for (std::size_t j = 0; j < localIndices.size(); ++j) {
......
#install headers
install(FILES
FunctionFromCallable.hpp
GlobalIdSet.hpp
HierarchicNodeToRangeMap.hpp
Interpolate.hpp
......
#pragma once
#include <dune/common/typeutilities.hh>
#include <dune/functions/common/functionfromcallable.hh>
namespace AMDiS
{
namespace Impl
{
template <class Traits, class F,
class Range = typename Traits::RangeType,
class Domain = typename Traits::DomainType>
auto functionFromCallableImpl(F const& f, Dune::PriorityTag<2>)
{
return Dune::Functions::FunctionFromCallable<Range(Domain), F>(f);
}
template <class Signature, class F>
auto functionFromCallableImpl(F const& f, Dune::PriorityTag<1>)
{
return Dune::Functions::FunctionFromCallable<Signature, F>(f);
}
}
template <class SigTraits, class F>
auto functionFromCallable(F const& f)
{
return Impl::functionFromCallableImpl<SigTraits>(f, Dune::PriorityTag<10>{});
}
} // end namespace AMDiS
install(FILES
VtkSequenceWriter.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/io)
#pragma once
#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <memory>
#include <dune/grid/io/file/vtk/common.hh>
#include <dune/common/path.hh>
#include <dune/grid/io/file/vtk/vtkwriter.hh>
namespace AMDiS
{
/// \brief class to write pvd-files which contains a list of all collected vtk-files
/**
* Write pvd-file suitable for easy visualization with
* <a href="http://www.vtk.org/">The Visualization Toolkit (VTK)</a>.
*
* \tparam GridView Grid view of the grid we are writing
*/
template <class GridView>
class VTKSequenceWriter
{
using VTKWriter = Dune::VTKWriter<GridView>;
public:
/// \brief Set up the VTKSequenceWriter class
/**
* \param vtkWriter Writer object used to write the individual time step data files
*/
VTKSequenceWriter(std::shared_ptr<VTKWriter> vtkWriter)
: vtkWriter_(std::move(vtkWriter))
{}
/// \brief Set up the VTKSequenceWriter class by creating a timestep writer of type \ref VTKWriter
/**
* \param gridView GridView object passed to the constructor of the VTKWriter
* \param args... Additional arguments forwarded to the VTKWriter constructor.
*/
template <class... Args>
VTKSequenceWriter(GridView const& gridView, Args&&... args)
: VTKSequenceWriter<GridView>(std::make_shared<VTKWriter>(gridView, FWD(args)...))
{}
virtual ~VTKSequenceWriter() = default;
/// accessor for the underlying VTKWriter instance
std::shared_ptr<VTKWriter> const& vtkWriter() const
{
return vtkWriter_;
}
/// \brief Adds a field of cell data to the VTK file
template <class... Args>
void addCellData(Args&&... args)
{
vtkWriter_->addCellData(FWD(args)...);
}
/// \brief Adds a field of vertex data to the VTK file
template <class... Args>
void addVertexData (Args&&... args)
{
vtkWriter_->addVertexData(FWD(args)...);
}
/// \brief Writes VTK data for the given time,
/**
* \param time The time(step) for the data to be written.
* \param name The basename of the .pvd file (without file extension)
* \param type VTK output type.
*/
virtual void write(double time, std::string const& name, Dune::VTK::OutputType type = Dune::VTK::ascii)
{
pwrite(time, name, ".", "", type);
}
/// \brief Writes VTK data for the given time,
/**
* \param time The time(step) for the data to be written.
* \param name The basename of the .pvd file (without file extension)
* \param path The directory where to put the .pvd file
* \param extendpath The (relative) subdirectory to path, where to put the timestep files
* \param type VTK output type.
*/
virtual void pwrite(double time, std::string const& name, std::string const& path, std::string const& extendpath,
Dune::VTK::OutputType type = Dune::VTK::ascii)
{
// remember current time step
unsigned int count = timesteps_.size();
timesteps_.push_back(time);
// write VTK file
vtkWriter_->pwrite(seqName(name, count), Dune::concatPaths(path, extendpath), "", type);
// write pvd file ... only on rank 0
if (Environment::mpiRank() == 0) {
std::ofstream pvdFile;
pvdFile.exceptions(std::ios_base::badbit | std::ios_base::failbit |
std::ios_base::eofbit);
std::string pvdname = path + "/" + name + ".pvd";
pvdFile.open(pvdname.c_str());
pvdFile << "<?xml version=\"1.0\"?>\n"
<< "<VTKFile type=\"Collection\" version=\"0.1\" byte_order=\"" << Dune::VTK::getEndiannessString() << "\">\n"
<< "<Collection>\n";
for (unsigned int i = 0; i <= count; ++i) {
std::string piecepath = extendpath;
std::string fullname = getParallelHeaderName(seqName(name,i), piecepath, Environment::mpiSize());
pvdFile << "<DataSet timestep=\"" << timesteps_[i]
<< "\" part=\"0\" file=\""
<< fullname << "\"/>\n";
}
pvdFile << "</Collection>\n"
<< "</VTKFile>\n" << std::flush;
pvdFile.close();
}
}
protected:
// create sequence name
static std::string seqName(std::string const& name, unsigned int count)
{
std::stringstream n;
n.fill('0');
n << name << "-" << std::setw(5) << count;
return n.str();
}
static std::string getParallelHeaderName(std::string const& name, std::string const& path, int commSize)
{
std::ostringstream s;
if (path.size() > 0) {
s << path;
if (path[path.size()-1] != '/')
s << '/';
}
s << 's' << std::setw(4) << std::setfill('0') << commSize << '-';
s << name;
if (GridView::dimension > 1)
s << ".pvtu";
else
s << ".pvtp";
return s.str();
}
private:
std::shared_ptr<VTKWriter> vtkWriter_;
std::vector<double> timesteps_;
};
} // end namespace AMDiS
......@@ -28,8 +28,7 @@ dune_add_test(SOURCES DOFVectorTest.cpp
LINK_LIBRARIES amdis)
dune_add_test(SOURCES DiscreteFunctionTest.cpp
LINK_LIBRARIES amdis
CMD_ARGS "${CMAKE_SOURCE_DIR}/examples/init/ellipt.dat.2d")
LINK_LIBRARIES amdis)
dune_add_test(SOURCES ExpressionsTest.cpp
LINK_LIBRARIES amdis)
......@@ -65,8 +64,7 @@ dune_add_test(SOURCES ISTLCommTest.cpp
CMAKE_GUARD "MPI_FOUND AND dune-istl_FOUND")
dune_add_test(SOURCES IntegrateTest.cpp
LINK_LIBRARIES amdis
CMD_ARGS "${CMAKE_SOURCE_DIR}/examples/init/ellipt.dat.2d")
LINK_LIBRARIES amdis)
dune_add_test(SOURCES MarkerTest.cpp
LINK_LIBRARIES amdis)
......