Commit 0462c4db authored by webmanue's avatar webmanue
Browse files

Merge remote-tracking branch 'origin/master' into 90-add-assemblemassmatrixplugin

parents 7ebbd501 07018cfd
Pipeline #139047 passed with stages
in 6 minutes and 50 seconds
......@@ -13,5 +13,10 @@
],
"dockerComposeFile": "../docker-compose.yml",
"service": "dev-real",
"workspaceFolder": "/mnt/io"
}
"workspaceFolder": "/mnt/io",
"remoteEnv": {
"OMPI_ALLOW_RUN_AS_ROOT": "1",
"OMPI_ALLOW_RUN_AS_ROOT_CONFIRM": "1",
"OMPI_MCA_btl_vader_single_copy_mechanism": "none"
}
}
\ No newline at end of file
......@@ -65,6 +65,7 @@ build-image-docu:
check-code-format:
stage: analyze
needs: ["build-image-dev-real"]
image: $CI_REGISTRY_IMAGE/dev-real:$CI_COMMIT_REF_SLUG
script:
- >
......@@ -77,28 +78,32 @@ check-code-format:
check-license-header:
stage: analyze
needs: ["build-image-dev-real"]
image: $CI_REGISTRY_IMAGE/dev-real:$CI_COMMIT_REF_SLUG
script:
- >
! grep \
grep \
--recursive \
--exclude-dir='.git' \
--exclude='*.json' \
--exclude='*.txt' \
--exclude='*.vtu' \
--files-without-match "Apache License" \
.
check-script:
stage: analyze
needs: ["build-image-dev-real"]
image: $CI_REGISTRY_IMAGE/dev-real:$CI_COMMIT_REF_SLUG
script:
- find . -name "*.py" -print0 | xargs -0 python3 -m black --check
- find . -name "*.py" -print0 | xargs -0 python3 -m pylint
- find . -name "*.py" -print0 | xargs -0 python3 -m pylint --generated-members=vtk.*
- find . -name "*.py" -print0 | xargs -0 python3 -m mypy --python-version 3.7 --ignore-missing
- find . -name "*.py" -print0 | xargs -0 python3 -m doctest
.build-library: &build-library
stage: build
coverage: '/^lines:\s*\d+\.\d+\%/'
script:
- useradd developer
- mkdir build
......@@ -114,16 +119,20 @@ check-script:
'
artifacts:
reports:
cobertura: build/coverage.xml
coverage_report:
coverage_format: cobertura
path: build/coverage.xml
junit: build/*/test/gtest-results.xml
when: always
build-library-real:
image: $CI_REGISTRY_IMAGE/dev-real:$CI_COMMIT_REF_SLUG
needs: ["build-image-dev-real"]
<<: *build-library
build-library-complex:
image: $CI_REGISTRY_IMAGE/dev-complex:$CI_COMMIT_REF_SLUG
needs: ["build-image-dev-complex"]
<<: *build-library
.install-library: &install-library
......@@ -146,14 +155,17 @@ build-library-complex:
install-library-real:
image: $CI_REGISTRY_IMAGE/dev-real:$CI_COMMIT_REF_SLUG
needs: ["build-image-dev-real"]
<<: *install-library
install-library-complex:
image: $CI_REGISTRY_IMAGE/dev-complex:$CI_COMMIT_REF_SLUG
needs: ["build-image-dev-complex"]
<<: *install-library
build-documentation:
stage: build
needs: ["build-image-docu"]
image: $CI_REGISTRY_IMAGE/docu:$CI_COMMIT_REF_SLUG
script:
- mkdir build
......
......@@ -56,9 +56,9 @@ The project uses [CMake](https://cmake.org) as its build system generator. The f
- [Google Test](https://github.com/google/googletest): version 1.8.1
- [HDF5](https://www.hdfgroup.org/solutions/hdf5/): version 1.10
- [MPI](https://cmake.org/cmake/help/latest/module/FindMPI.html): version 3.1
- [PETSc](https://www.mcs.anl.gov/petsc/): version 3.12
- [Range-v3](https://github.com/ericniebler/range-v3): version 0.10
- [SLEPc](https://slepc.upv.es/): version 3.12
- [PETSc](https://www.mcs.anl.gov/petsc/): version 3.15
- [Range-v3](https://github.com/ericniebler/range-v3): version 0.11
- [SLEPc](https://slepc.upv.es/): version 3.15
Of course, these libraries are covered by their own license terms. Since PETSc and SLEPc do not provide a CMake configuration file, these libraries are found using the provided find modules in ```cmake/modules/```, which in turn are based on ```pkg-config```.
......
......@@ -34,7 +34,6 @@ add_library(${PROJECT_NAME}-assembly
./FeaturePlugins.cc
./HasUniqueTypeTrait.cc
./IsSingleUniqueType.cc
./StaticLooper.cc
./UpdateInternalVariablesPlugin.cc
./deserialize.cc
./groupElementDataPerVertex.cc
......@@ -54,6 +53,6 @@ target_link_libraries(${PROJECT_NAME}-assembly
PUBLIC Eigen3::Eigen
)
target_compile_features(${PROJECT_NAME}-assembly PUBLIC cxx_std_11)
target_compile_features(${PROJECT_NAME}-assembly PUBLIC cxx_std_17)
ae108_install_library(assembly)
......@@ -66,7 +66,7 @@ public:
/**
* @param args Are used to construct the plugins.
*/
template <class... Args> explicit Assembler(Args &&... args);
template <class... Args> explicit Assembler(Args &&...args);
using ElementView = typename cpppetsc::LocalElementView<mesh_type>;
......@@ -82,7 +82,7 @@ public:
* constructor.
*/
template <class... Args>
void emplaceElement(ElementView view, Args &&... constructorArguments);
void emplaceElement(ElementView view, Args &&...constructorArguments);
/**
* @brief Returns a range of iterators pointing to a struct with two methods:
......@@ -191,13 +191,13 @@ namespace assembly {
template <class Element, class Plugins, class Policy>
template <class... Args>
Assembler<Element, Plugins, Policy>::Assembler(Args &&... args)
Assembler<Element, Plugins, Policy>::Assembler(Args &&...args)
: PluginBase(std::forward<Args>(args)...) {}
template <class Element, class Plugins, class Policy>
template <class... Args>
void Assembler<Element, Plugins, Policy>::emplaceElement(
ElementView view, Args &&... constructorArguments) {
ElementView view, Args &&...constructorArguments) {
_elements.emplace_back(std::move(view),
std::forward<Args>(constructorArguments)...);
}
......@@ -220,7 +220,7 @@ public:
* @param args Are used to construct in-place the element instance.
*/
template <class... Args>
explicit AnnotatedElement(ElementView view, Args &&... args)
explicit AnnotatedElement(ElementView view, Args &&...args)
: _meshView(std::move(view)), _instance(std::forward<Args>(args)...) {}
const ElementView &meshView() const { return _meshView; }
......
......@@ -37,22 +37,30 @@ class AssemblerGroup : public DerivePluginsUniquely<
AssemblerGroup<SingleElementAssemblers...>,
typename ConcatenatePlugins<typename PluginTypeTrait<
SingleElementAssemblers>::type...>::type> {
template <std::size_t N>
using member_assembler_type =
typename MemberTypeTrait<AssemblerGroup, N>::type;
public:
template <class... Args> explicit AssemblerGroup(Args &&... args);
template <class... Args> explicit AssemblerGroup(Args &&...args);
/**
* @brief Get the Nth member assembler.
*/
template <std::size_t N> const member_assembler_type<N> &get() const;
template <std::size_t N> const auto &get() const & {
return std::get<N>(_assemblers);
}
/**
* @brief Get the Nth member assembler.
*/
template <std::size_t N> member_assembler_type<N> &get();
template <std::size_t N> auto &get() & { return std::get<N>(_assemblers); }
/**
* @brief Return the tuple of assemblers.
*/
const auto &assemblers() const &noexcept { return _assemblers; }
/**
* @brief Return the tuple of assemblers.
*/
auto &assemblers() &noexcept { return _assemblers; }
private:
using tuple_type = std::tuple<SingleElementAssemblers...>;
......@@ -138,25 +146,6 @@ template <class... SingleElementAssemblers>
struct IsGroupTypeTrait<AssemblerGroup<SingleElementAssemblers...>>
: std::true_type {};
/**
* @brief Specialization: The number of assemblers in the group is the number of
* SingleElementAssemblers-template-parameters.
*/
template <class... SingleElementAssemblers>
struct NumberOfMembersTypeTrait<AssemblerGroup<SingleElementAssemblers...>>
: std::integral_constant<std::size_t, sizeof...(SingleElementAssemblers)> {
};
/**
* @brief Specialization: The Nth member is the Nth element of
* SingleElementAssemblers.
*/
template <std::size_t N, class... SingleElementAssemblers>
struct MemberTypeTrait<AssemblerGroup<SingleElementAssemblers...>, N> {
using type =
typename std::tuple_element<N,
std::tuple<SingleElementAssemblers...>>::type;
};
} // namespace assembly
} // namespace ae108
......@@ -169,24 +158,8 @@ namespace assembly {
template <class... SingleElementAssemblers>
template <class... Args>
AssemblerGroup<SingleElementAssemblers...>::AssemblerGroup(Args &&... args)
AssemblerGroup<SingleElementAssemblers...>::AssemblerGroup(Args &&...args)
: _assemblers(std::forward<Args>(args)...) {}
template <class... SingleElementAssemblers>
template <std::size_t N>
const typename AssemblerGroup<
SingleElementAssemblers...>::template member_assembler_type<N> &
AssemblerGroup<SingleElementAssemblers...>::get() const {
return std::get<N>(_assemblers);
}
template <class... SingleElementAssemblers>
template <std::size_t N>
typename AssemblerGroup<
SingleElementAssemblers...>::template member_assembler_type<N> &
AssemblerGroup<SingleElementAssemblers...>::get() {
return std::get<N>(_assemblers);
}
} // namespace assembly
} // namespace ae108
......@@ -71,17 +71,5 @@ template <class Assembler> struct PluginTypeTrait {};
* (designed for the nongroup case) the value is false.
*/
template <class Assembler> struct IsGroupTypeTrait : std::false_type {};
/**
* @brief Deduces the number of member assemblers. By default (designed for the
* nongroup case) this number is undefined.
*/
template <class Assembler> struct NumberOfMembersTypeTrait {};
/**
* @brief Deduces the type of the member assembler at a given index. By default
* (designed for the nongroup case) this type is undefined.
*/
template <class Assembler, std::size_t> struct MemberTypeTrait {};
} // namespace assembly
} // namespace ae108
......@@ -16,11 +16,26 @@
#pragma once
#include "ae108/assembly/AssemblerTypeTraits.h"
#include <functional>
#include <tuple>
#include <utility>
#define DEFINE_ASSEMBLER_METHOD_BASE(methodName, cvQualifiers) \
template <class... Args> void methodName(Args &&... args) cvQualifiers { \
this->dispatch(std::forward<Args>(args)...); \
#define DEFINE_ASSEMBLER_METHOD_BASE(PluginName, methodName, cvQualifiers) \
template <class... Args> void methodName(Args &&...args) cvQualifiers { \
if constexpr (!::ae108::assembly::IsGroupTypeTrait< \
typename PluginName::assembler_type>::value) { \
execute(std::forward<Args>(args)...); \
} else { \
const auto conditionalCall = [&](auto &a) { \
using A = std::decay_t<decltype(a)>; \
if constexpr (std::is_base_of_v<PluginName<A>, A>) { \
static_cast<cvQualifiers PluginName<A> &>(a).execute(args...); \
} \
}; \
std::apply( \
[&](auto &...as) { (..., std::invoke(conditionalCall, as)); }, \
this->assembler().assemblers()); \
} \
}
#define DEFINE_ASSEMBLER_PLUGIN_BASE(PluginName, methodName, methodArguments, \
......@@ -28,6 +43,7 @@
template <class Assembler> \
class PluginName \
: public ::ae108::assembly::FeaturePlugin<Assembler, PluginName> { \
using assembler_type = Assembler; \
using element_type = \
typename ::ae108::assembly::ElementTypeTrait<Assembler>::type; \
using matrix_type = \
......@@ -45,7 +61,7 @@
\
public: \
void execute methodArguments cvQualifiers; \
DEFINE_ASSEMBLER_METHOD_BASE(methodName, cvQualifiers) \
DEFINE_ASSEMBLER_METHOD_BASE(PluginName, methodName, cvQualifiers) \
\
protected: \
~PluginName() = default; \
......@@ -63,29 +79,21 @@
namespace ae108 {
namespace assembly {
template <class Assembler, template <class> class Plugin> class FeaturePlugin {
template <class Assembler_, template <class> class Plugin_>
class FeaturePlugin {
using assembler_type = Assembler_;
template <class T> using plugin_type = Plugin_<T>;
protected:
/**
* @brief Returns a reference to the Assembler base class.
*/
Assembler &assembler();
assembler_type &assembler();
/**
* @brief Returns a reference to the Assembler base class.
*/
const Assembler &assembler() const;
/**
* @brief Calls execute with the given parameters for all (member) assemblers
* that have the plugin (const version).
*/
template <class... Args> void dispatch(Args &&... args) const;
/**
* @brief Calls execute with the given parameters for all (member) assemblers
* that have the plugin (nonconst version).
*/
template <class... Args> void dispatch(Args &&... args);
const assembler_type &assembler() const;
~FeaturePlugin() = default;
};
......@@ -96,65 +104,9 @@ protected:
* implementations
*******************************************************************/
#include "ae108/assembly/utilities/StaticLooper.h"
#include <type_traits>
namespace ae108 {
namespace assembly {
namespace detail {
template <class Assembler, template <class> class Plugin>
using HasPlugin = std::is_base_of<Plugin<Assembler>, Assembler>;
template <class Assembler, template <class> class Plugin>
using PluginType = Plugin<typename std::remove_const<Assembler>::type>;
template <class Assembler, template <class> class Plugin>
using CastType =
typename std::conditional<std::is_const<Assembler>::value,
const PluginType<Assembler, Plugin> &,
PluginType<Assembler, Plugin> &>::type;
template <template <class> class Plugin> struct Executor {
template <class Assembler, class... Args>
void operator()(Assembler &assembler, Args &&... args) const {
operatorImpl(
HasPlugin<typename std::remove_const<Assembler>::type, Plugin>{},
assembler, std::forward<Args>(args)...);
}
private:
template <class Assembler, class... Args>
void operatorImpl(std::true_type, Assembler &assembler,
Args &&... args) const {
static_cast<CastType<Assembler, Plugin>>(assembler).execute(
std::forward<Args>(args)...);
}
template <class Assembler, class... Args>
void operatorImpl(std::false_type, Assembler &, Args &&...) const {}
};
/**
* @brief Implementation of dispatch for the assembler-group case.
*/
template <template <class> class Plugin, class Assembler, class... Args>
void dispatchImpl(std::true_type, Assembler &assembler, Args &&... args) {
utilities::StaticLooper<NumberOfMembersTypeTrait<typename std::remove_const<
Assembler>::type>::value>::run(detail::Executor<Plugin>{}, assembler,
std::forward<Args>(args)...);
}
/**
* @brief Implementation of dispatch for the non-assembler-group case.
*/
template <template <class> class Plugin, class Assembler, class... Args>
void dispatchImpl(std::false_type, Assembler &assembler, Args &&... args) {
static_cast<CastType<Assembler, Plugin>>(assembler).execute(
std::forward<Args>(args)...);
}
} // namespace detail
template <class Assembler, template <class> class Plugin>
Assembler &FeaturePlugin<Assembler, Plugin>::assembler() {
return static_cast<Assembler &>(static_cast<Plugin<Assembler> &>(*this));
......@@ -165,19 +117,5 @@ const Assembler &FeaturePlugin<Assembler, Plugin>::assembler() const {
return static_cast<const Assembler &>(
static_cast<const Plugin<Assembler> &>(*this));
}
template <class Assembler, template <class> class Plugin>
template <class... Args>
void FeaturePlugin<Assembler, Plugin>::dispatch(Args &&... args) const {
detail::dispatchImpl<Plugin>(IsGroupTypeTrait<Assembler>{}, assembler(),
std::forward<Args>(args)...);
}
template <class Assembler, template <class> class Plugin>
template <class... Args>
void FeaturePlugin<Assembler, Plugin>::dispatch(Args &&... args) {
detail::dispatchImpl<Plugin>(IsGroupTypeTrait<Assembler>{}, assembler(),
std::forward<Args>(args)...);
}
} // namespace assembly
} // namespace ae108
......@@ -29,7 +29,7 @@ DEFINE_CONST_ASSEMBLER_PLUGIN(AssembleConsistentMassMatrixPlugin,
std::vector<value_type> outputBuffer;
for (const auto &meshElement : this->assembler().meshElements()) {
const auto matrix = meshElement.instance().computeConsistentMassMatrix();
const auto matrix = compute_consistent_mass_matrix(meshElement.instance());
outputBuffer.resize(matrix.rows() * matrix.cols());
utilities::serialize(matrix, outputBuffer.begin());
......
......@@ -29,7 +29,7 @@ DEFINE_CONST_ASSEMBLER_PLUGIN(AssembleLumpedMassMatrixPlugin,
std::vector<value_type> outputBuffer;
for (const auto &meshElement : this->assembler().meshElements()) {
const auto matrix = meshElement.instance().computeLumpedMassMatrix();
const auto matrix = compute_lumped_mass_matrix(meshElement.instance());
outputBuffer.resize(matrix.rows() * matrix.cols());
utilities::serialize(matrix, outputBuffer.begin());
......
// © 2020 ETH Zurich, Mechanics and Materials Lab
// © 2020 California Institute of Technology
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <cstddef>
#include <utility>
namespace ae108 {
namespace assembly {
namespace utilities {
/**
* @brief Executes functor with parameters value.get<N>() and args for all N
* from From to To (excluding).
*/
template <std::size_t To, std::size_t From = 0u> struct StaticLooper {
template <class Functor, class Value, class... Args>
static void run(Functor &&functor, Value &&value, Args &&... args);
};
/**
* @brief Special case: Does not execute functor.
*/
template <std::size_t To> struct StaticLooper<To, To> {
template <class Functor, class Value, class... Args>
static void run(Functor &&, Value &&, Args &&... args);
};
} // namespace utilities
} // namespace assembly
} // namespace ae108
/********************************************************************
* implementations
*******************************************************************/
namespace ae108 {
namespace assembly {
namespace utilities {
template <std::size_t To, std::size_t From>
template <class Functor, class Value, class... Args>
void StaticLooper<To, From>::run(Functor &&functor, Value &&value,
Args &&... args) {
functor(value.template get<From>(), args...);
StaticLooper<To, From + 1>::run(std::forward<Functor>(functor),
std::forward<Value>(value),
std::forward<Args>(args)...);
}
template <std::size_t To>
template <class Functor, class Value, class... Args>
void StaticLooper<To, To>::run(Functor &&, Value &&, Args &&...) {}
} // namespace utilities
} // namespace assembly
} // namespace ae108
\ No newline at end of file
......@@ -68,12 +68,13 @@ OutputIterator serialize(const std::vector<ValueType> &vector,
template <class OutputIterator, class ValueType, int Rows, int Cols>
OutputIterator serialize(const Eigen::Matrix<ValueType, Rows, Cols> &vector,
OutputIterator bufferBegin) {
std::array<ValueType, Rows * Cols> buffer;
Eigen::Map<Eigen::Matrix<ValueType, Rows, Cols,
Cols == 1 ? Eigen::ColMajor : Eigen::RowMajor>>
wrappedBuffer(buffer.data(), vector.rows(), vector.cols());
wrappedBuffer = vector;
return std::copy(buffer.begin(), buffer.end(), bufferBegin);
for (Eigen::Index i = 0; i < vector.rows(); ++i) {
for (Eigen::Index j = 0; j < vector.cols(); ++j) {
*bufferBegin = vector(i, j);
bufferBegin++;
}
}
return bufferBegin;
}
/**
......
......@@ -21,9 +21,9 @@ add_executable(${PROJECT_NAME}-AssemblyTests
./ConcatenateFeaturePlugins_Test.cc
./DerivePluginsUniquely_Test.cc
./DeriveUniquely_Test.cc
./FeaturePlugin_Test.cc
./HasUniqueTypeTrait_Test.cc
./IsSingleTypeTrait_Test.cc
./StaticLooper_Test.cc
./deserialize_Test.cc
./resizeIfPossible_Test.cc
./serialize_Test.cc
......
// © 2022 ETH Zurich, Mechanics and Materials Lab
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
#include "ae108/assembly/FeaturePlugin.h"
namespace {
DEFINE_ASSEMBLER_PLUGIN(TestPlugin, testMethod, (double)) {}
DEFINE_CONST_ASSEMBLER_PLUGIN(TestPluginConst, testMethodConst, (double)) {}
} // namespace
namespace ae108 {
namespace assembly {
namespace {
DEFINE_ASSEMBLER_PLUGIN(TestPlugin, testMethod, (double)) {}