Commit d5e52d52 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Fix some tests using the new algorithms

parent d773c643
Pipeline #5681 failed with stage
in 7 minutes
#pragma once
#include <array>
#include <tuple>
#include <vector>
#include <dune/common/tuplevector.hh>
#include <amdis/common/Apply.hpp>
namespace AMDiS {
namespace Recursive {
template <class T>
struct Apply;
/// \brief Recursive application of a transformation functor `f` to a hierarchic
/// container of containers, returning the transformed container.
/**
* This utility function applies the given functor `f` to the "leaf" entries in
* a hierarchic container that returns a transformed container. Therefore, the
* container is traversed recursively, using specializations of the `Apply<Container>::impl`
* class method. If no specialization is provided, the function is applied to the
* whole container or leaf entry, respectively.
**/
template <class F, class T>
auto apply(F&& f, T const& t)
{
return Apply<T>::impl(f,t);
}
// specializations for container types
/// Default implementation of the recursive \ref map function.
template <class T>
struct Apply
{
template <class F>
static auto impl(F&& f, T const& t)
{
return f(t);
}
};
template <class T, std::size_t n>
struct Apply<std::array<T,n>>
{
template <class F>
static auto impl(F&& f, std::array<T,n> const& a)
{
return Ranges::applyIndices<n>([&](auto... ii) {
return std::array{Recursive::apply(f,a[ii])...}; });
}
};
template <class... TT>
struct Apply<std::tuple<TT...>>
{
template <class F>
static auto impl(F&& f, std::tuple<TT...> const& t)
{
return Ranges::apply([&](auto const&... ti) {
return std::tuple{Recursive::apply(f,ti)...}; }, t);
}
};
template <class T1, class T2>
struct Apply<std::pair<T1,T2>>
{
template <class F>
static auto impl(F&& f, std::pair<T1,T2> const& t)
{
return std::pair{Recursive::apply(f,t.first), Recursive::apply(f,t.second)};
}
};
template <class... TT>
struct Apply<Dune::TupleVector<TT...>>
{
template <class F>
static auto impl(F&& f, Dune::TupleVector<TT...> const& t)
{
return Ranges::apply([&](auto const&... ti) {
return Dune::makeTupleVector(Recursive::apply(f,ti)...); }, t);
}
};
template <class T>
struct Apply<std::vector<T>>
{
template <class F>
static auto impl(F&& f, std::vector<T> const& v)
{
using U = TYPEOF(Recursive::apply(f,std::declval<T>()));
std::vector<U> out;
out.reserve(v.size());
for (std::size_t i = 0; i < v.size(); ++i)
out.emplace_back(Recursive::apply(f,v[i]));
return out;
}
};
}} // end namespace AMDiS::Recursive
\ No newline at end of file
install(FILES
Apply.hpp
ForEach.hpp
InnerProduct.hpp
Map.hpp
Transform.hpp
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/amdis/algorithm)
......@@ -20,7 +20,7 @@ struct ForEach;
/**
* This utility function applies the given functor `f` to the "leaf" entries in
* a hierarchic container. Therefore, the container is traversed recursively,
* using specializations of the `ForEach<Container>::apply` class method.
* using specializations of the `ForEach<Container>::impl` class method.
* If no specialization is provided, the function is applied to the whole container
* or leaf entry, respectively.
**/
......
......@@ -15,14 +15,36 @@ namespace Recursive {
template <class>
struct InnerProduct;
/// \brief Recursive inner product of two containers [in1] and [in2] following the signature
/// of `std::inner_product` but applied to the leaf elements of the possibly hierarchic containers
template <class In1, class In2, class T, class BinaryOperation1, class BinaryOperation2>
T innerProduct (In1 const& in1, In2 const& in2, T init, BinaryOperation1 op1, BinaryOperation2 op2)
/**
* \brief Recursive inner product of two containers [in1] and [in2] following the
* signature of `std::inner_product` but applied to the leaf elements of the possibly
* hierarchic containers.
*
* This implements the reduction operation of the form
* ```
* T result = init;
* for (i...)
* result = op1(result, op2(in1[i], in2[i]);
* return result;
* ```
**/
template <class In1, class In2, class T, class BinaryOp1, class BinaryOp2>
T innerProduct (In1 const& in1, In2 const& in2, T init, BinaryOp1 op1, BinaryOp2 op2)
{
return InnerProduct<In1>::impl(in1, in2, std::move(init), op1, op2);
}
/// Specialization of \ref innerProduct if no functors are given, use plus and multiplies
/// by default.
/**
* This implements the standard Euclidean inner product
* ```
* result = init + sum_i in1[i] * in2[i]
* ```
*
* Note, no conjugation of the first or second argument is used in this default.
**/
template <class In1, class In2, class T>
T innerProduct (In1 const& in1, In2 const& in2, T init)
{
......@@ -40,7 +62,8 @@ private:
class = decltype(std::begin(std::declval<In1>())),
class = decltype(std::end(std::declval<In1>())),
class = decltype(std::begin(std::declval<In2>()))>
static T impl2 (Dune::PriorityTag<2>, In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
static T impl2 (Dune::PriorityTag<2>, In1 const& in1, In2 const& in2, T init,
BinOp1 op1, BinOp2 op2)
{
auto first1 = std::begin(in1);
auto first2 = std::begin(in2);
......@@ -52,7 +75,8 @@ private:
// ranges with static index access
template <class In1, class In2, class T, class BinOp1, class BinOp2,
class = decltype(std::declval<In1>()[std::integral_constant<std::size_t,0>{}])>
static T impl2 (Dune::PriorityTag<1>, In1 const& in1, In2 const& in2, T init, BinOp1 op1, BinOp2 op2)
static T impl2 (Dune::PriorityTag<1>, In1 const& in1, In2 const& in2, T init,
BinOp1 op1, BinOp2 op2)
{
static_assert(static_size_v<In1> == static_size_v<In2>);
Ranges::forIndices<static_size_v<In1>>([&](auto ii) {
......
......@@ -14,13 +14,14 @@ namespace Recursive {
template <class>
struct Transform;
/// \brief Recursive application of a functor `op` to a hierarchic container of containers.
/// \brief Recursive application of a functor `op` to a hierarchic container of
/// containers.
/**
* This utility function applies the given functor `op` to the "leaf" entries in
* hierarchic containers {in...} and assigns the output to the hierarchic container [out].
* Therefore, the containers are traversed recursively, using specializations of the
* `Transform<Container>::impl` class method. If no such specialization is provided, the function
* is applied to the whole containers or leaf entries, respectively.
* `Transform<Container>::impl` class method. If no such specialization is provided,
* the function is applied to the whole containers or leaf entries, respectively.
**/
template <class Out, class Op, class... In>
void transform (Out& out, Op&& op, In const&... in)
......@@ -34,21 +35,23 @@ struct Transform
{
private:
// ranges with dynamic index access
template <class OutIter, class Op, class... InIter>
static void impl3 (OutIter d_first, OutIter d_last, Op&& op, InIter... first)
template <class OutIter, class Op, class In0, class... InIter>
static void impl3 (OutIter d_first, Op&& op, In0 first0, In0 last0, InIter... first)
{
while (d_first != d_last)
Recursive::transform(*d_first++, op, *first++...);
while (first0 != last0)
Recursive::transform(*d_first++, op, *first0++, *first++...);
}
// ranges with dynamic index access
template <class Out, class Op, class... In,
template <class Out, class Op, class In0, class... In,
class = decltype(std::begin(std::declval<Out>())),
class = decltype(std::end(std::declval<Out>())),
class = std::void_t<decltype(std::begin(std::declval<In>()))...>>
static void impl2 (Dune::PriorityTag<3>, Out& out, Op&& op, In const&... in)
class = decltype(std::begin(std::declval<In0>())),
class = decltype(std::end(std::declval<In0>())),
class = decltype((std::begin(std::declval<In>()),...))>
static void impl2 (Dune::PriorityTag<3>, Out& out, Op&& op, In0 const& in0,
In const&... in)
{
impl3(std::begin(out), std::end(out), op, std::begin(in)...);
impl3(std::begin(out), op, std::begin(in0), std::end(in0), std::begin(in)...);
}
// ranges with static index access
......
......@@ -7,15 +7,6 @@ if (CCACHE_PROGRAM)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
endif ()
if (UNIX AND NOT APPLE)
execute_process(COMMAND ${CMAKE_C_COMPILER} -fuse-ld=gold -Wl,--version ERROR_QUIET OUTPUT_VARIABLE ld_version)
if ("${ld_version}" MATCHES "GNU gold")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags")
endif()
endif()
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")
......
......@@ -32,11 +32,11 @@ void test_dofvector(DOFVector<B,T>& vec)
vec.insert(MultiIndex{0}, T(1));
vec.finish();
AMDIS_TEST_EQ(vec.at(MultiIndex{0}), T(1));
AMDIS_TEST_EQ(vec.get(MultiIndex{0}), T(1));
T min(10);
T max(-10);
vec.forEach([&min,&max](auto, auto value) {
Recursive::forEach(vec.coefficients(), [&min,&max](auto value) {
min = std::min(min, value);
max = std::max(max, value);
});
......
......@@ -17,6 +17,7 @@
#include <amdis/ProblemStat.hpp>
#include <amdis/ProblemStatTraits.hpp>
#include <amdis/algorithm/InnerProduct.hpp>
#include "Tests.hpp"
......@@ -80,7 +81,7 @@ double calcError(Problem const& prob, Fcts const& funcs)
{
auto& globalBasis = *prob->globalBasis();
auto localView = globalBasis.localView();
auto const& sol = prob->solution().coefficients();
auto sol = prob->solution();
auto ref = makeDOFVector(globalBasis, DataTransferOperation::NO_OPERATION);
int k = 0;
......@@ -94,11 +95,9 @@ double calcError(Problem const& prob, Fcts const& funcs)
});
// compare the solution with the reference
double maxError = 0;
sol.forEach([&](auto dof, double coeff) {
double error = std::abs(ref.at(dof) - coeff);
maxError = std::max(maxError, error);
});
double maxError = Recursive::innerProduct(ref.coefficients(), sol.coefficients(), 0.0,
[](double a, double b) { return std::max(a, b); },
[](double a, double b) { return std::abs(a - b); });
return maxError;
}
......
......@@ -8,7 +8,6 @@
#include <amdis/AMDiS.hpp>
#include <amdis/ProblemStat.hpp>
#include <amdis/common/Apply.hpp>
#include <amdis/common/RecursiveForEach.hpp>
#include <amdis/gridfunctions/DiscreteFunction.hpp>
#include <amdis/typetree/TreePath.hpp>
......@@ -71,7 +70,7 @@ bool compare(DOFVector<GB,T> const& U, DOFVector<GB,T> const& V)
for (size_type i = 0; i < lv.size(); ++i)
{
auto multiIndex = lv.index(i);
if (!compare(U.at(multiIndex), V.at(multiIndex)))
if (!compare(U.get(multiIndex), V.get(multiIndex)))
return false;
}
}
......
#include <config.h>
#include <amdis/Environment.hpp>
#include <amdis/algorithm/Apply.hpp>
#include <amdis/algorithm/Map.hpp>
#include <amdis/algorithm/ForEach.hpp>
#include "Tests.hpp"
......@@ -19,7 +19,7 @@ void test(Container& container)
Recursive::forEach(container, [&](auto const& c) { sum += c; });
// create a new container with scaled elements
auto scaled = Recursive::apply([&](auto const& c) { return 2*c; }, container);
auto scaled = Recursive::map([&](auto const& c) { return 2*c; }, container);
// sum up agains
int sum2 = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment