From 5b28ec730f593807e5dfe0214d1ae4f028918b9c Mon Sep 17 00:00:00 2001 From: Seung Hyun Kim Date: Thu, 11 Jul 2024 23:47:22 -0500 Subject: [PATCH] files: add Rod-related traits and include trees --- backend/src/Systems/CosseratRods/Access.hpp | 302 ++++ backend/src/Systems/CosseratRods/Aliases.hpp | 7 + backend/src/Systems/CosseratRods/Block.hpp | 1348 +++++++++++++++++ .../Systems/CosseratRods/BlockInitializer.hpp | 362 +++++ .../src/Systems/CosseratRods/BlockSlice.hpp | 215 +++ .../src/Systems/CosseratRods/BlockView.hpp | 240 +++ backend/src/Systems/CosseratRods/Concepts.org | 126 ++ .../CosseratRods/CosseratRodPlugin.hpp | 839 ++++++++++ .../CosseratRods/CosseratRodTraits.hpp | 457 ++++++ .../src/Systems/CosseratRods/CosseratRods.hpp | 53 + .../src/Systems/CosseratRods/Initializers.hpp | 7 + .../CosseratRods/Initializers/CMakeLists.txt | 34 + .../Initializers/ComposeInitializers.hpp | 232 +++ .../Initializers/Initializers.hpp | 29 + .../Initializers/StraightCosseratRod.hpp | 88 ++ .../Initializers/UserDefinedCosseratRod.hpp | 60 + .../Initializers/detail/Affordances.hpp | 150 ++ .../Initializers/detail/CMakeLists.txt | 26 + .../Initializers/detail/Common.hpp | 82 + .../Initializers/detail/Elasticity.hpp | 134 ++ .../Initializers/detail/Geometry.hpp | 308 ++++ .../Initializers/detail/Kinematics.hpp | 77 + .../Initializers/detail/Transformations.hpp | 61 + .../src/Systems/CosseratRods/Protocols.hpp | 9 + .../CosseratRods/Traits/DataOpsTraits.hpp | 15 +- .../DataType/BlazeBackend/DataTypeTraits.hpp | 13 - .../DataType/BlazeBackend/MatrixTag.hpp | 13 - .../DataType/BlazeBackend/TensorTag.hpp | 13 - .../DataType/BlazeBackend/VectorTag.hpp | 13 - .../Traits/DataType/Protocols.hpp | 13 - .../CosseratRods/Traits/DataType/Rank.hpp | 13 - .../Traits/DataType/ScalarTag.hpp | 13 - .../Operations/BlazeBackend/BackendKind.hpp | 46 + .../Operations/BlazeBackend/CMakeLists.txt | 40 + .../BlazeBackend/Calculus/CMakeLists.txt | 34 + .../Calculus/Difference/BaseTemplate.hpp | 32 + .../Calculus/Difference/Blaze.hpp | 22 + .../Calculus/Difference/CMakeLists.txt | 37 + .../Calculus/Difference/Kernels.hpp | 5 + .../Calculus/Difference/Operation.hpp | 36 + .../BlazeBackend/Calculus/Difference/SIMD.hpp | 30 + .../Calculus/Difference/Scalar.hpp | 30 + .../Calculus/KernelGenerators/CMakeLists.txt | 31 + .../Calculus/KernelGenerators/SIMD.hpp | 149 ++ .../Calculus/KernelGenerators/Scalar.hpp | 79 + .../BlazeBackend/Calculus/Kernels.hpp | 4 + .../Calculus/Quadrature/BaseTemplate.hpp | 31 + .../Calculus/Quadrature/Blaze.hpp | 22 + .../Calculus/Quadrature/CMakeLists.txt | 37 + .../Calculus/Quadrature/Kernels.hpp | 5 + .../Calculus/Quadrature/Operation.hpp | 37 + .../BlazeBackend/Calculus/Quadrature/SIMD.hpp | 30 + .../Calculus/Quadrature/Scalar.hpp | 30 + .../InvRotateDivide/BaseTemplate.hpp | 32 + .../BlazeBackend/InvRotateDivide/Blaze.hpp | 70 + .../InvRotateDivide/CMakeLists.txt | 31 + .../BlazeBackend/InvRotateDivide/SIMD.hpp | 215 +++ .../BlazeBackend/InvRotateDivide/Scalar.hpp | 126 ++ .../InvRotateDivide/instructions.py | 22 + .../BlazeBackend/LinearAlgebra/CMakeLists.txt | 37 + .../CrossProduct/BaseTemplate.hpp | 31 + .../LinearAlgebra/CrossProduct/Blaze.hpp | 23 + .../LinearAlgebra/CrossProduct/CMakeLists.txt | 36 + .../LinearAlgebra/CrossProduct/Kernels.hpp | 5 + .../LinearAlgebra/CrossProduct/Operation.hpp | 81 + .../LinearAlgebra/CrossProduct/SIMD.hpp | 30 + .../LinearAlgebra/CrossProduct/Scalar.hpp | 30 + .../KernelGenerators/CMakeLists.txt | 17 + .../KernelGenerators/MatVec/CMakeLists.txt | 32 + .../KernelGenerators/MatVec/Checks.hpp | 39 + .../KernelGenerators/MatVec/SIMD.hpp | 189 +++ .../KernelGenerators/MatVec/Scalar.hpp | 75 + .../KernelGenerators/VecScalar/CMakeLists.txt | 32 + .../KernelGenerators/VecScalar/Checks.hpp | 37 + .../KernelGenerators/VecScalar/SIMD.hpp | 172 +++ .../KernelGenerators/VecScalar/Scalar.hpp | 63 + .../KernelGenerators/VecVec/CMakeLists.txt | 32 + .../KernelGenerators/VecVec/Checks.hpp | 36 + .../KernelGenerators/VecVec/SIMD.hpp | 200 +++ .../KernelGenerators/VecVec/Scalar.hpp | 79 + .../BlazeBackend/LinearAlgebra/Kernels.hpp | 6 + .../LinearAlgebra/MatVec/BaseTemplate.hpp | 30 + .../LinearAlgebra/MatVec/Blaze.hpp | 22 + .../LinearAlgebra/MatVec/CMakeLists.txt | 36 + .../LinearAlgebra/MatVec/Kernels.hpp | 5 + .../LinearAlgebra/MatVec/Operation.hpp | 41 + .../LinearAlgebra/MatVec/SIMD.hpp | 30 + .../LinearAlgebra/MatVec/Scalar.hpp | 30 + .../VecScalarDiv/BaseTemplate.hpp | 31 + .../LinearAlgebra/VecScalarDiv/Blaze.hpp | 39 + .../LinearAlgebra/VecScalarDiv/CMakeLists.txt | 36 + .../LinearAlgebra/VecScalarDiv/Kernels.hpp | 5 + .../LinearAlgebra/VecScalarDiv/Operation.hpp | 21 + .../LinearAlgebra/VecScalarDiv/SIMD.hpp | 30 + .../LinearAlgebra/VecScalarDiv/Scalar.hpp | 30 + .../VecScalarMult/BaseTemplate.hpp | 31 + .../LinearAlgebra/VecScalarMult/Blaze.hpp | 39 + .../VecScalarMult/CMakeLists.txt | 36 + .../LinearAlgebra/VecScalarMult/Kernels.hpp | 5 + .../LinearAlgebra/VecScalarMult/Operation.hpp | 21 + .../LinearAlgebra/VecScalarMult/SIMD.hpp | 30 + .../LinearAlgebra/VecScalarMult/Scalar.hpp | 30 + .../Operations/BlazeBackend/OpsTraits.hpp | 362 +++++ .../BlazeBackend/OptimizationLevel.hpp | 26 + .../Traits/Operations/CMakeLists.txt | 14 + .../CosseratRods/Traits/PlacementTrait.hpp | 53 + .../Traits/PlacementTraits/CMakeLists.txt | 29 + .../PlacementTraits/PlacementTraits.hpp | 157 ++ .../Traits/PlacementTraits/Protocols.hpp | 101 ++ .../Traits/PlacementTraits/TypeTraits.hpp | 193 +++ .../Systems/CosseratRods/Traits/Protocols.hpp | 7 + .../src/Systems/CosseratRods/TypeTraits.hpp | 35 + .../CosseratRods/Utility/CMakeLists.txt | 28 + .../CosseratRods/Utility/CenterOfMass.hpp | 172 +++ .../Systems/CosseratRods/Utility/Energy.hpp | 274 ++++ 115 files changed, 9821 insertions(+), 105 deletions(-) create mode 100644 backend/src/Systems/CosseratRods/Access.hpp create mode 100644 backend/src/Systems/CosseratRods/Aliases.hpp create mode 100644 backend/src/Systems/CosseratRods/Block.hpp create mode 100644 backend/src/Systems/CosseratRods/BlockInitializer.hpp create mode 100644 backend/src/Systems/CosseratRods/BlockSlice.hpp create mode 100644 backend/src/Systems/CosseratRods/BlockView.hpp create mode 100644 backend/src/Systems/CosseratRods/Concepts.org create mode 100644 backend/src/Systems/CosseratRods/CosseratRodPlugin.hpp create mode 100644 backend/src/Systems/CosseratRods/CosseratRodTraits.hpp create mode 100644 backend/src/Systems/CosseratRods/CosseratRods.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Initializers/ComposeInitializers.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/Initializers.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/StraightCosseratRod.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/UserDefinedCosseratRod.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Affordances.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Common.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Elasticity.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Geometry.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Kinematics.hpp create mode 100644 backend/src/Systems/CosseratRods/Initializers/detail/Transformations.hpp create mode 100644 backend/src/Systems/CosseratRods/Protocols.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/BackendKind.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Difference/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/KernelGenerators/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/KernelGenerators/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/KernelGenerators/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/Calculus/Quadrature/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/InvRotateDivide/instructions.py create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/CrossProduct/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/MatVec/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/MatVec/Checks.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/MatVec/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/MatVec/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecScalar/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecScalar/Checks.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecScalar/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecScalar/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecVec/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecVec/Checks.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecVec/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/KernelGenerators/VecVec/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/MatVec/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarDiv/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/BaseTemplate.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/Blaze.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/Kernels.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/Operation.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/SIMD.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/LinearAlgebra/VecScalarMult/Scalar.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/OpsTraits.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/BlazeBackend/OptimizationLevel.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Operations/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/PlacementTrait.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/PlacementTraits/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Traits/PlacementTraits/PlacementTraits.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/PlacementTraits/Protocols.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/PlacementTraits/TypeTraits.hpp create mode 100644 backend/src/Systems/CosseratRods/Traits/Protocols.hpp create mode 100644 backend/src/Systems/CosseratRods/TypeTraits.hpp create mode 100644 backend/src/Systems/CosseratRods/Utility/CMakeLists.txt create mode 100644 backend/src/Systems/CosseratRods/Utility/CenterOfMass.hpp create mode 100644 backend/src/Systems/CosseratRods/Utility/Energy.hpp diff --git a/backend/src/Systems/CosseratRods/Access.hpp b/backend/src/Systems/CosseratRods/Access.hpp new file mode 100644 index 00000000..9d6ff92f --- /dev/null +++ b/backend/src/Systems/CosseratRods/Access.hpp @@ -0,0 +1,302 @@ +#pragma once + +//****************************************************************************** +// Includes +//****************************************************************************** + +#include // size_t + +#include "Systems/common/Access.hpp" +/// Forward declarations +#include "Systems/CosseratRods/Types.hpp" +/// +#include "Systems/CosseratRods/CosseratRodPlugin.hpp" + +namespace elastica { + + //============================================================================ + // + // ACCESS API FUNCTIONS + // + //============================================================================ + + //**Position functions******************************************************** + /*!\name Position functions */ + //@{ + /*!\brief Specialization of elastica::position() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) position( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + // get_position() wraps around a free function, so the API is still not bad + return cosserat_rod.self().get_position(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) position( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + // tentative, can change + // ideally should be position(blocks::slice(cosserat_rod, index)); + // but slice(cosserat_rod_slice) is not defined (and we do not need it per + // se). + + // Other option is + // blocks::slice(position(cosserat_rod), index); + // which is very close to what we have below. The problem here is that + // position(cosserat_rod) is not a block anymore, so the semantics are not + // well formed. + return cosserat_rod.self().get_position(index); + } + + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) position( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_position(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) position( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_position(index); + } + //@} + //**************************************************************************** + + //**Director functions******************************************************** + /*!\name Director functions */ + //@{ + /*!\brief Specialization of elastica::director() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) director( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + return cosserat_rod.self().get_director(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) director( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_director(index); + } + + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) director( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_director(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) director( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_director(index); + } + //@} + //**************************************************************************** + + //**Velocity functions******************************************************** + /*!\name Velocity functions */ + //@{ + /*!\brief Specialization of elastica::velocity() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) velocity( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + return cosserat_rod.self().get_velocity(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) velocity( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_velocity(index); + } + + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) velocity( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_velocity(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) velocity( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_velocity(index); + } + //@} + //**************************************************************************** + + //**Angular Velocity functions************************************************ + /*!\name Angular Velocity functions */ + //@{ + /*!\brief Specialization of elastica::angular_velocity() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) angular_velocity( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + return cosserat_rod.self().get_angular_velocity(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) angular_velocity( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_angular_velocity(index); + } + + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) angular_velocity( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_angular_velocity(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) angular_velocity( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_angular_velocity(index); + } + //@} + //**************************************************************************** + + //**External loads functions************************************************** + /*!\name External loads functions */ + //@{ + /*!\brief Specialization of elastica::external_loads() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_loads( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + return cosserat_rod.self().get_external_loads(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_loads( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_external_loads(index); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_loads( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_external_loads(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_loads( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_external_loads(index); + } + //@} + //**************************************************************************** + + //**External torques functions************************************************ + /*!\name External torques functions */ + //@{ + /*!\brief Specialization of elastica::external_torques() for Cosserat rods + * \ingroup cosserat_rod + */ + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_torques( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...>& cosserat_rod) noexcept { + return cosserat_rod.self().get_external_torques(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_torques( + ::elastica::cosserat_rod::CosseratRodPlugin& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_external_torques(index); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_torques( + ::elastica::cosserat_rod::CosseratRodPlugin const& + cosserat_rod) noexcept { + return cosserat_rod.self().get_external_torques(); + } + template class ComputationalBlock, + template + class... Components> + inline constexpr decltype(auto) external_torques( + ::elastica::cosserat_rod::CosseratRodPlugin< + CRT, ComputationalBlock, Components...> const& cosserat_rod, + std::size_t index) noexcept { + return cosserat_rod.self().get_external_torques(index); + } + //@} + //**************************************************************************** + +} // namespace elastica diff --git a/backend/src/Systems/CosseratRods/Aliases.hpp b/backend/src/Systems/CosseratRods/Aliases.hpp new file mode 100644 index 00000000..073e941c --- /dev/null +++ b/backend/src/Systems/CosseratRods/Aliases.hpp @@ -0,0 +1,7 @@ +#pragma once + +//****************************************************************************** +// Includes +//****************************************************************************** +#include "Systems/CosseratRods/Aliases/CosseratRod.hpp" +#include "Systems/CosseratRods/Aliases/CosseratRodWithoutDamping.hpp" diff --git a/backend/src/Systems/CosseratRods/Block.hpp b/backend/src/Systems/CosseratRods/Block.hpp new file mode 100644 index 00000000..9d847207 --- /dev/null +++ b/backend/src/Systems/CosseratRods/Block.hpp @@ -0,0 +1,1348 @@ +#pragma once + +//****************************************************************************** +// Includes +//****************************************************************************** + +#include + +/// Forward declarations +#include "Systems/CosseratRods/Types.hpp" +/// + +#include "ErrorHandling/Assert.hpp" +#include "Systems/Block/Block.hpp" +#include "Systems/CosseratRods/BlockInitializer.hpp" +#include "Systems/CosseratRods/BlockSlice.hpp" +#include "Systems/CosseratRods/CosseratRodPlugin.hpp" +#include "Systems/common/SymplecticStepperAdapter.hpp" +/// +#include "Utilities/NonCopyable.hpp" +#include "Utilities/Requires.hpp" +// #include "Utilities/StdHelpers.hpp" +#include "Utilities/TMPL.hpp" + +// serialization support, feels strange coming from simulator +// #include "Simulator/IO/Serialization/Serialize.hpp" + +namespace blocks { + + //============================================================================ + // + // CLASS DEFINITION + // + //============================================================================ + + //**************************************************************************** + /*! \cond ELASTICA_INTERNAL */ + /*!\brief Specialization of blocks::Block for CosseratRodPlugin + * \ingroup blocks + * + * \tparam CRT The traits class for a Cosserat rod + * \tparam Components Components customizing a Cosserat rod (such as geometry, + * elasticity) + * + * \see blocks::Block + */ + template + class... Components> + class Block< + elastica::cosserat_rod::CosseratRodPlugin> + // final (not final because testing requires deriving) + : private elastica::NonCopyable, + // public ::elastica::SymplecticPolicy< + // BlockFacade>> + public BlockFacade> { + private: + //**Type definitions******************************************************** + //! Traits type + using Traits = CRT; + //! Facade type + using Facade = BlockFacade< + elastica::cosserat_rod::CosseratRodPlugin>; + //! Parent type + // using Parent = ::elastica::SymplecticPolicy; + using Parent = Facade; + //! Plugin type + using Plugin = typename Parent::PluginType; + //! This type + using This = Block; + //! This slice type + using ThisSlice = + BlockSlice>; + //! Plugin type for the slice + using SlicePlugin = typename ThisSlice::PluginType; + + public: + //! List of variables + using typename Parent::Variables; + + protected: + //! List of variables placed on the whole rod + using VariablesOnRod = + tmpl::filter>; + //! List of variables placed on the nodes in the grid + using VariablesOnNode = + tmpl::filter>; + //! List of variables placed on the elements in the grid + using VariablesOnElement = + tmpl::filter>; + //! List of variables placed on the voronois in the grid + using VariablesOnVoronoi = + tmpl::filter>; + //! Template type of expected initializer + template + using CosseratInitializer = + // note : here it is not templated on the slice of the plugin but rather + // the plugin itself + ::elastica::cosserat_rod::CosseratInitializer; + //! Type of index + using index_type = typename Traits::index_type; + // Same as typename Traits::DataType::Index::type::ElementType; + // but this one is tailored to blaze + //! Type of size + using size_type = typename Traits::size_type; + //! Type of total element count + using TotalElementCount = size_type; + //! Type of ghost node indices + using GhostNodeIndices = std::vector; + //************************************************************************** + + public: + //************************************************************************** + //! Tag to place on nodes + using typename Plugin::OnNode; + //! Tag to place on elements + using typename Plugin::OnElement; + //! Tag to place on voronois + using typename Plugin::OnVoronoi; + //! Tag to place on the whole rod rather than at discrete points + using typename Plugin::OnRod; + //************************************************************************** + + private: + //**Friendships************************************************************* + // Friend the Facade (for what?) + friend Parent; + // Friend the serialization struct + // friend elastica::io::Serialize; + //************************************************************************** + + //**Parent methods********************************************************** + //! Methods inherited from parent class + public: + using Plugin::n_elements; + using Plugin::total_n_elements; + using Plugin::total_n_nodes; + using Plugin::total_n_voronois; + // for n_units() free function + using Parent::n_ghosts; + using Parent::n_units; + //************************************************************************** + + /* Not really needed? + static constexpr std::size_t get_number_of_node_members() { + return tmpl::size::value; + } + + static constexpr std::size_t get_number_of_element_members() { + return tmpl::size::value; + } + + static constexpr std::size_t get_number_of_voronoi_members() { + return tmpl::size::value; + } + */ + + //************************************************************************** + /*!\name Get variable helpers */ + //@{ + /*!\brief Helper to get the list of variables based on the stagger type + */ + public: // FIXME : Does not work since get_variables instantiates it + static constexpr inline auto GetVariablesHelper(OnRod) noexcept -> + typename This::VariablesOnRod; + static constexpr inline auto GetVariablesHelper(OnNode) noexcept -> + typename This::VariablesOnNode; + static constexpr inline auto GetVariablesHelper(OnElement) noexcept -> + typename This::VariablesOnElement; + static constexpr inline auto GetVariablesHelper(OnVoronoi) noexcept -> + typename This::VariablesOnVoronoi; + //@} + //************************************************************************** + + public: + //**Type definitions******************************************************** + //! Template type for getting the list of variables based on + //! the stagger type + template + using get_variables_placed = + decltype(GetVariablesHelper(std::declval())); + //************************************************************************** + + //************************************************************************** + /*!\name Start of slice */ + //@{ + private: + //************************************************************************** + template + using identity = tmpl::type_; + /* Dev note: + * Need tag dispatch here as function specialization is not valid + * (even with a single template parameter) because it is an + * Explicit specialization in non-namespace scope + * This was corrected in a later draft, so Clang++ works fine. However + * GCC bugs out, even with the retroactive fix applied to C++14 compilers. + * https://stackoverflow.com/questions/3052579/explicit-specialization-in-non-namespace-scope + */ + template + inline auto get_start_of_slice_helper( + index_type const unit, identity) const noexcept + -> size_type { + // Zero-based indexing + // this is implemented in check() now + // ELASTICA_ASSERT(ghost_node_indices_.size() >= unit, + // "Wrong number of units requested"); + + // unit - 1 cannot be negative + return unit ? (ghost_node_indices_[unit - 1UL] + 1UL) : 0UL; + } + inline auto get_start_of_slice_helper(index_type const unit, + identity) const noexcept + -> size_type { + return unit; + } + //************************************************************************** + + public: + //************************************************************************** + /*!\brief Gets starting location of new slice, based on the stagger type + */ + template + inline auto get_start_of_slice(index_type const unit) const noexcept + -> size_type { + return get_start_of_slice_helper(unit, identity{}); + } + //@} + //************************************************************************** + + //************************************************************************** + /*!\brief Gets size of new slice, based on the stagger type + */ + template + inline auto get_size_of_slice( + index_type const index_to_be_sliced) const noexcept -> size_type { + return OnStaggerType::get_dofs(n_elements(index_to_be_sliced)); + } + //************************************************************************** + private: + //************************************************************************** + + //************************************************************************** + /*!\brief Gets size of new slice, based on the stagger type + * Non-rod specialization + */ + template + inline auto get_size_of_slice_helper( + index_type const start_index, size_type const slice_size, + identity /*meta*/) const noexcept -> size_type { + return OnStaggerType::get_dofs(n_elements(start_index, slice_size)); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Gets size of new slice, based on the stagger type + * + * For types on rod the size of the slice is the size requested itself. + * The get_dofs() is designed to always return 1, so this is a workaround. + */ + inline auto get_size_of_slice_helper( + index_type const, size_type const slice_size, + identity /*meta*/) const noexcept -> size_type { + return slice_size; + } + //************************************************************************** + + public: + //************************************************************************** + /*!\brief Gets size of new slice, based on the stagger type + */ + template + inline auto get_size_of_slice(index_type const start_index, + size_type const slice_size) const noexcept + -> size_type { + return get_size_of_slice_helper(start_index, slice_size, + identity{}); + } + //************************************************************************** + + public: + //************************************************************************** + /* + * \note + * Most of the non-default public interface should more or less come from + * the Cosserat Rod plugin class per design + */ + //************************************************************************** + + //////////////////////////// start conformance ///////////////////////////// + // To work with block facade, implement customization point for generating + // a slice. + //**Slice functions********************************************************* + /*!\name Slice functions */ + //@{ + + //************************************************************************** + /*!\brief Takes slice of each individual variable + */ + template + inline constexpr typename Var::slice_type slice( + index_type index_to_be_sliced) & { + return Var::slice( + blocks::get(*this), + get_start_of_slice(index_to_be_sliced), + get_size_of_slice(index_to_be_sliced)); + } + template + inline constexpr typename Var::const_slice_type slice( + index_type index_to_be_sliced) const& { + return Var::slice( + blocks::get(*this), + get_start_of_slice(index_to_be_sliced), + get_size_of_slice(index_to_be_sliced)); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Takes slice of each individual variable in a range + */ + template + inline constexpr typename Var::slice_type slice(index_type start_index, + size_type slice_size) & { + return Var::slice( + blocks::get(*this), + get_start_of_slice(start_index), + get_size_of_slice(start_index, slice_size)); + } + template + inline constexpr typename Var::const_slice_type slice( + index_type start_index, size_type slice_size) const& { + return Var::slice( + blocks::get(*this), + get_start_of_slice(start_index), + get_size_of_slice(start_index, slice_size)); + } + //************************************************************************** + + //@} + //************************************************************************** + ///////////////////////////// end conformance ////////////////////////////// + + public: + //**Constructors************************************************************ + /*!\name Constructors */ + //@{ + + //************************************************************************** + /*!\brief The default constructor. + * + */ + Block() : Parent(), ghost_node_indices_(){}; + //************************************************************************** + + //************************************************************************** + /*!\brief The move constructor. + * + * \param other Other block to move from + */ + Block(Block&& other) noexcept + : Parent(std::move(other)), + ghost_node_indices_(std::move(other.ghost_node_indices_)){}; + //************************************************************************** + + //@} + //************************************************************************** + + //**Destructor************************************************************** + /*!\name Destructor */ + //@{ + ~Block() = default; + //@} + //************************************************************************** + + protected: + //**Resizing functions****************************************************** + /*!\name Resizing functions */ + //@{ + + //************************************************************************** + /*!\brief Prepares for resizing the entire rod, with some bounds checking + * + * \param n_elems The number of elements in the newly introduced rod + */ + auto prepare_for_resize(std::size_t n_elems) -> size_type { + ELASTICA_ASSERT(n_elems > 1UL, "Cannot have rods with < 2 elements!"); + const size_type current_n_units = n_units(); + size_type total_n_elements_after_resizing(0UL); + + // A. increase units count taken care by the plugin + // element_counts_.push_back(n_elems); + + // A. resize dofs + if (current_n_units) { + // pre-existing block, so + + // 1. push back a new ghost node (based on zero-indexing) + // i > 0 + // gn_indices[i] + // = gn_indices[i - 1] + (n_elements[i] + 1) + 1 + // = gn_indices[i - 1] + n_nodes[i] + 1 + // = gn_indices[i - 1] + 1 + n_nodes[i] + // = gn_indices[i - 2] + (1 + n_nodes[i-1]) + (1 + n_nodes[i]) + // i = 0 + // ghost_node_indices[0UL] = n_elements[0UL] + 1 + // = n_nodes[0] + // meanwhile + // total_n_nodes = n_nodes[0] + 1 + n_nodes[1] + 1 + .... + nodes[i - 1] + // and hence they are equivalent + ghost_node_indices_.push_back(total_n_nodes()); + + // 2. calculate the new number of elements including ghosts + total_n_elements_after_resizing = + total_n_elements() + n_elems + n_ghosts(OnElement{}); + + } else { + // Fresh block, so + ELASTICA_ASSERT(ghost_node_indices_.empty(), + "Block assert failed, contact developers"); + // cannot call total_n_elements() as we have an assert inside it + // ghost_node_indices_.push_back(void) => No ghosts in this case + + // 1. Increment total number of elements => No ghosts in this case + total_n_elements_after_resizing = n_elems; + } + return total_n_elements_after_resizing; + } + //************************************************************************** + + //************************************************************************** + /*!\brief Resizes variables placed on entire rods + * + * \param total_number_of_units The total number of units/rods + */ + void resize_members_on_rod(size_type const total_number_of_units) { + tmpl::for_each( + [this, new_size = total_number_of_units](auto v) { + using Variable = tmpl::type_from; + auto& var = blocks::get(*this); + Variable::resize(var, new_size); + }); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Resizes variables placed `OnStaggerType` + * + * \param total_elements The total elements across rods + * + * \tparam OnStaggerType The staggering/placement type + */ + template + void resize_members_placed(TotalElementCount const total_elements) { + using VariablesPlacedOnStaggerType = get_variables_placed; + // new size does not depend on the variable, so we can factor it outside + // the lambda + tmpl::for_each( + [this, new_size = OnStaggerType::get_dofs(total_elements)](auto v) { + using Variable = tmpl::type_from; + auto& var = blocks::get(*this); + Variable::resize(var, new_size); + }); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Resizes variables other than those placed on the rod + * + * \param total_elements The total elements across rods + */ + void resize_members_not_on_rod(TotalElementCount const total_elements) { + resize_members_placed(total_elements); + resize_members_placed(total_elements); + resize_members_placed(total_elements); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Resizes all variables in the current Block + * + * \param total_elements The total elements across all rods + * \param total_number_of_units The total number of units/rods + */ + void resize_internal(TotalElementCount const total_elements, + size_type const total_number_of_units) { + // 2.1 resize dofs on rods by new_n_units + resize_members_on_rod(total_number_of_units); + + // 2.2 resize dofs on nodes, elements and voronoi by total_n_elements_ + resize_members_not_on_rod(total_elements); + } + //************************************************************************** + + //@} + //************************************************************************** + + public: + //************************************************************************** + /*!\brief Gets the ghost nodes buffer + * + * \details + * This is mostly used in contexts such as serialization + */ + inline constexpr auto get_ghost_node_buffer() & noexcept + -> GhostNodeIndices& { + return ghost_node_indices_; + } + //************************************************************************** + + //************************************************************************** + /*!\brief Gets the ghost nodes buffer for a const Block + * + * \details + * This is mostly used in contexts such as serialization + */ + inline constexpr auto get_ghost_node_buffer() const& noexcept + -> GhostNodeIndices const& { + return ghost_node_indices_; + } + //************************************************************************** + + //@} + //************************************************************************** + + protected: + //**Element buffer function************************************************* + /*!\brief Initialize the element buffer at a given location + * + * \param n_elems Number of elements in the new rod + * \param loc_n_units Fill location + * + * \note + * This is mainly useful in testing + */ + inline void initialize_elements_buffer( + size_type const n_elems, size_type const loc_n_units) noexcept { + n_elements(loc_n_units) = n_elems; + } + //************************************************************************** + + public: + //************************************************************************** + /*!\brief Emplaces a new rod to the block + * + * \details + * This is the main entry-point for the Simulator to add new rods to the + * current Block. + * + * \param block_initializer The initializer to fill in all elements of the + * new block + */ + template + auto emplace( + CosseratInitializer&& block_initializer) + -> ThisSlice { + using Init = CosseratInitializer; + // 0. number of preexisting rods + const size_type curr_n_units = n_units(); + const size_type new_n_units = curr_n_units + 1UL; + + // 1. increase total number of elements and ghosts (block specific) + const size_type n_elements_added( + static_cast(block_initializer).n_elems()); + const size_type total_n_elements_after_resizing = + prepare_for_resize(n_elements_added); + + // 2. Resize the block to fit the new rod + // 2.1 resize dofs on nodes, elements and voronoi by total_n_elements_ + // 2.2 resize dofs on rods by new_n_units + resize_internal(total_n_elements_after_resizing, new_n_units); + + // 3. The slicing logic (which calls check() to see if a buffer overflows) + // requires that we know the number of elements that + // needs to be sliced before making the slice itself, which is taken from + // the elements buffer. So here we fill in the total_n_elements + initialize_elements_buffer(n_elements_added, curr_n_units); + + // after resizing the units should match + ELASTICA_ASSERT(n_units() == new_n_units, + "Invariant violation, contact the developers"); + + // 4. fill ghosts + fill_ghosts(*this); + + // after this step, we should have enough capacity for the n'th rod + + // 5. make a slice for the n'th unit (0 based indexing with checks) + ThisSlice latest_slice(blocks::slice(*this, curr_n_units)); + + // ... and initialize it ... + Parent::initialize(latest_slice, std::move(block_initializer)); + + // copied to the output buffer, NRVO should kick in + return latest_slice; + } + //************************************************************************** + + //************************************************************************** + /*!\brief Emplaces (back) a new rod to the block + * + * \param block_initializer The initializer to fill in all elements of the + * new block + * + * \see emplace + */ + template + inline decltype(auto) emplace_back( + CosseratInitializer&& block_initializer) { + return emplace(std::move(block_initializer)); + } + //************************************************************************** + + protected: + //**Member variables******************************************************** + /*!\name Member variables */ + //@{ + /// Extra members for book-keeping + //! Indices of nodal ghosts across + GhostNodeIndices ghost_node_indices_; + //@} + //************************************************************************** + }; + /*! \endcond */ + //**************************************************************************** + + //**Ghosting functions******************************************************** + /*!\name Ghosting functions + * \ingroup cosserat_rod */ + //@{ + + //**************************************************************************** + /*!\brief Fills ghosts for a `Variable` in the current Block over a + * certain region + * + * \tparam Variable + * \param block_like Block to fill ghosts + * \param region_start Start of region + * \param region_size Size of region + * \param deficit The number of ghosts to be filled, from the ghost node + * index location. + */ + template + class... Components> + void fill_ghosts_for(Block>& block_like, + std::size_t region_start, std::size_t region_size, + std::size_t deficit) noexcept { + // kernel + auto& var = blocks::get(block_like); + const auto ghost_value = Variable::ghost_value(); + + using signedt = std::make_signed_t; + auto const it = + std::cbegin(block_like.get_ghost_node_buffer()) + signedt(region_start); + std::for_each(it, it + signedt(region_size), + [&](std::size_t const ghost_node_idx) { + const auto ghost_stop_idx = ghost_node_idx; + ELASTICA_ASSERT(ghost_stop_idx > deficit, + "Ghost invariant violated!"); + const auto ghost_start_idx = ghost_stop_idx - deficit; + + for (auto ghost_idx = ghost_stop_idx; + ghost_idx > ghost_start_idx; --ghost_idx) { + Variable::slice(var, ghost_idx) = ghost_value; + } + // rewrite the loop above using positive indices + // for (auto ghost_idx = ghost_start_idx + 1; + // ghost_idx <= ghost_stop_idx; ++ghost_idx) { + // Variable::slice(var, ghost_idx) = ghost_value; + // } + }); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts for a variable of tag `Tag` in the current Block + * + * \tparam Tag Tag of the variable + * \param block_like Block to fill ghosts + * \param region_start Start of region + * \param region_size Size of region + */ + template + class... Components> + void fill_ghosts_for(Block>& block_like, + std::size_t region_start, + std::size_t region_size) noexcept { + using Variable = typename std::remove_reference_t< + decltype(block_like)>::VariableMap::template variable_from; + const auto deficit = block_like.n_ghosts(typename Variable::Stagger{}); + fill_ghosts_for(block_like, region_start, region_size, deficit); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts for a variable of tag `Tag` in the current Block + * + * \tparam Tag Tag of the variable + * \param block_like Block to fill ghosts + */ + template + class... Components> + inline void fill_ghosts_for( + Block< + elastica::cosserat_rod::CosseratRodPlugin>& + block_like) noexcept { + fill_ghosts_for(block_like, 0UL, + block_like.get_ghost_node_buffer().size()); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts on variables placed `OnStaggerType` + * + * \param block_like Block to fill ghosts + * \param region_start Start of region + * \param region_size Size of region + * \param deficit The number of ghosts to be filled, from the ghost node + * index location. + * + * \tparam OnStaggerType The staggering/placement type + */ + template + class... Components> + void fill_ghosts_placed(Block>& block_like, + std::size_t region_start, std::size_t region_size, + const std::size_t deficit) noexcept { + using B = std::remove_reference_t; + using VariablesPlacedOnStaggeredType = + typename B::template get_variables_placed; + + tmpl::for_each([=, &block_like](auto v) { + using Variable = tmpl::type_from; + fill_ghosts_for(block_like, region_start, region_size, deficit); + }); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts on variables placed `OnStaggerType` + * + * \param block_like Block to fill ghosts + * \param region_start Start of region + * \param region_size Size of region + * + * \tparam OnStaggerType The staggering/placement type + */ + template + class... Components> + inline void fill_ghosts_placed( + Block>& block_like, + std::size_t region_start, std::size_t region_size) noexcept { + auto const deficit = block_like.n_ghosts(OnStaggerType{}); + fill_ghosts_placed(block_like, region_start, region_size, + deficit); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts on variables placed `OnStaggerType` + * + * \param block_like Block to fill ghosts + * + * \tparam OnStaggerType The staggering/placement type + */ + template + class... Components> + inline void fill_ghosts_placed( + Block< + elastica::cosserat_rod::CosseratRodPlugin>& + block_like) noexcept { + auto const gs = block_like.get_ghost_node_buffer().size(); + fill_ghosts_placed(block_like, 0UL, gs); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts for all variables in the current Block + * + * \param block_like Block to fill ghosts + * \param region_start Start of region + * \param region_size Size of region + */ + template + class... Components> + void fill_ghosts(Block>& block_like, + std::size_t region_start, std::size_t region_size) noexcept { + using B = std::remove_reference_t; + + // fill ghosts for members not on rod, others don't need it + fill_ghosts_placed(block_like, region_start, + region_size); + fill_ghosts_placed(block_like, region_start, + region_size); + fill_ghosts_placed(block_like, region_start, + region_size); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Fills ghosts for all variables in the current Block + * + * \param block_like Block to fill ghosts + */ + template + class... Components> + void fill_ghosts(Block>& block_like) noexcept { + using B = std::remove_reference_t; + + // fill ghosts for members not on rod, others don't need it + fill_ghosts_placed(block_like); + fill_ghosts_placed(block_like); + fill_ghosts_placed(block_like); + } + //**************************************************************************** + + //@} + //**************************************************************************** + +} // namespace blocks + +namespace blocks { + + //============================================================================ + // + // CLASS DEFINITION + // + //============================================================================ + + //**************************************************************************** + /*! \cond ELASTICA_INTERNAL */ + /*!\brief Specialization of blocks::Block for a TaggedCosseratRodPlugin + * \ingroup blocks + * + * \tparam CRT The traits class for a Tagged Cosserat plugin + * \tparam Tag The tag for the Tagged Cosserat plugin + * \tparam Components Components customizing a Cosserat rod (such as geometry, + * elasticity) + * + * \see blocks::Block + */ + template + class... Components> + class Block> + : public Sliceable>>, + public Viewable>>, + public Block> { + private: + //**Type definitions******************************************************** + //! This type + using This = + Block>; + //! This slice type + using ThisSlice = + BlockSlice>; + //! Parent type + using Parent = Block< + elastica::cosserat_rod::CosseratRodPlugin>; + //! Sliceable type + using SliceAffordance = Sliceable; + //! Viewable type + using ViewAffordance = Viewable; + + protected: + //! Template type of expected initializer + template + using CosseratInitializer = + typename Parent::template CosseratInitializer; + //************************************************************************** + + public: + //**Access operators******************************************************** + /*!\name Access operators */ + //@{ + //! Operator for slicing + using SliceAffordance::operator[]; + //! Operator for viewing + using ViewAffordance::operator[]; + //@} + //************************************************************************** + + public: + //************************************************************************** + /*!\brief Emplaces a new rod to the block + * + * \details + * This is the main entry-point for the Simulator to add new rods to the + * current Block. + * + * \param block_initializer The initializer to fill in all elements of the + * new block + */ + template + auto emplace( + CosseratInitializer&& block_initializer) + -> ThisSlice { + // converts to a tagged slice + return Parent::emplace(std::move(block_initializer)); + } + //************************************************************************** + + //************************************************************************** + /*!\brief Emplaces (back) a new rod to the block + * + * \param block_initializer The initializer to fill in all elements of the + * new block + * + * \see emplace + */ + template + inline decltype(auto) emplace_back( + CosseratInitializer&& block_initializer) { + return This::emplace(std::move(block_initializer)); + } + //************************************************************************** + }; + //**************************************************************************** + +} // namespace blocks + +namespace blocks { + + //============================================================================ + // + // FREE FUNCTIONS + // + //============================================================================ + + // These slice overloads are added to prevent template deduction failure from + // Sliceable and Sliceable (which we derive from). + + //**************************************************************************** + /*!\brief Slices a tagged Cosserat Rod. + * \ingroup cosserat_rod blocks + * + * \param cosserat_rod The current cosserat rod. + * \param index The index of the slice (int or from_end) + */ + template + class... Components, + typename Index> + inline decltype(auto) slice( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>>& cosserat_rod, + Index index) /*noexcept*/ { + using Affordance = + Sliceable>>; + return slice(static_cast(cosserat_rod), index); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Slices a tagged Cosserat Rod. + * \ingroup cosserat_rod blocks + * + * \param cosserat_rod The current cosserat rod. + * \param index The index of the slice (int or from_end) + */ + template + class... Components, + typename Index> + inline decltype(auto) slice( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>> const& cosserat_rod, + Index index) /*noexcept*/ { + using Affordance = + Sliceable>>; + return slice(static_cast(cosserat_rod), index); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Slices a tagged Cosserat Rod. + * \ingroup cosserat_rod blocks + * + * \param cosserat_rod The current cosserat rod. + * \param index The index of the slice (int or from_end) + */ + template + class... Components, + typename StartIndex, typename StopIndex> + inline decltype(auto) slice( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>>& cosserat_rod, + StartIndex start_index, StopIndex stop_index) /*noexcept*/ { + using Affordance = + Viewable>>; + return slice(static_cast(cosserat_rod), std::move(start_index), + std::move(stop_index)); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Slices a tagged Cosserat Rod. + * \ingroup cosserat_rod blocks + * + * \param cosserat_rod The current cosserat rod. + * \param index The index of the slice (int or from_end) + */ + template + class... Components, + typename StartIndex, typename StopIndex> + inline decltype(auto) slice( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>> const& cosserat_rod, + StartIndex start_index, StopIndex stop_index) /*noexcept*/ { + using Affordance = + Viewable>>; + return slice(static_cast(cosserat_rod), + std::move(start_index), std::move(stop_index)); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Returns the size of the Cosserat Rod. + * \ingroup cosserat_rod blocks + * + * \param cosserat_rod The current cosserat rod. + * \return The number of elements in the cosserat rod. + */ + template + class... Components> + inline constexpr auto size( + Block<::elastica::cosserat_rod::CosseratRodPlugin< + CRT, Block, Components...>> const& cosserat_rod) noexcept { + // it might be not the best idea to have a size() member in the first place + return cosserat_rod.size(); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Get number of units within a CosseratRod + * \ingroup cosserat_rod blocks + * + * \details + * Get number of units from a Block. By 'units' we mean the number of + * individual BlockSlice(s) composing the Block. + * + * \usage + * \code + Block<...> b; + std::size_t n_units = blocks::n_units(b); + * \endcode + * + * \param cosserat_rod The cosserat rod whose n_units is to be extracted + */ + template + class... Components> + inline auto n_units( + Block<::elastica::cosserat_rod::CosseratRodPlugin< + CRT, Block, Components...>> const& cosserat_rod) noexcept + -> std::size_t { + return cosserat_rod.n_units(); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Returns the size of the Cosserat Rod. + * \ingroup cosserat_rod + * + * \param cosserat_rod The current cosserat rod. + * \return The number of elements in the cosserat rod. + */ + template + class... Components> + inline constexpr auto size( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>> const& cosserat_rod) noexcept { + // it might be not the best idea to have a size() member in the first place + return cosserat_rod.size(); + } + //**************************************************************************** + + //**************************************************************************** + /*!\brief Get number of units within a CosseratRod + * \ingroup cosserat_rod blocks + * + * \details + * Get number of units from a Block. By 'units' we mean the number of + * individual BlockSlice(s) composing the Block. + * + * \usage + * \code + Block<...> b; + std::size_t n_units = blocks::n_units(b); + * \endcode + * + * \param cosserat_rod The cosserat rod whose n_units is to be extracted + */ + template + class... Components> + inline auto n_units( + Block<::elastica::cosserat_rod::TaggedCosseratRodPlugin< + CRT, Block, Tag, Components...>> const& cosserat_rod) noexcept + -> std::size_t { + return cosserat_rod.n_units(); + } + //**************************************************************************** + +} // namespace blocks + +// template ComputationalBlock, // Block with +// implementation +// template +// class... Components> // Skills +// class CosseratRodPlugin; + +// template Block + +// template