diff --git a/bindings/python/src/State.cxx b/bindings/python/src/State.cxx index 314857f3f..b3c6b1283 100644 --- a/bindings/python/src/State.cxx +++ b/bindings/python/src/State.cxx @@ -43,8 +43,8 @@ static pybind11::object State_getExternalStateVariables( } // end of State_getExternalStateVariables static void State_setMaterialProperty(mgis::behaviour::State& s, - const std::string& n, - const mgis::real v) { + const std::string& n, + const mgis::real v) { mgis::behaviour::setMaterialProperty(s, n, v); } // end of State_setMaterialProperty diff --git a/docs/web/CMakeLists.txt b/docs/web/CMakeLists.txt index acb5cfdfc..958b66a26 100644 --- a/docs/web/CMakeLists.txt +++ b/docs/web/CMakeLists.txt @@ -86,6 +86,8 @@ if(MGIS_HAVE_PANDOC) mgis_pandoc_generate_html_page(release-notes-3.0.2 "--toc" "--toc-depth=3") mgis_pandoc_generate_html_page(release-notes-3.0.3 "--toc" "--toc-depth=3") mgis_pandoc_generate_html_page(release-notes-3.1 "--toc" "--toc-depth=3") + mgis_pandoc_generate_html_page(release-notes-3.1.1 "--toc" "--toc-depth=3") + mgis_pandoc_generate_html_page(release-notes-3.2 "--toc" "--toc-depth=3") mgis_pandoc_generate_html_page(orthotropic-behaviours "--toc" "--toc-depth=3") mgis_pandoc_generate_html_page(behaviour-integration-failure-analysis "--toc" "--toc-depth=3") mgis_pandoc_generate_html_page(functions "--toc" "--toc-depth=3") diff --git a/docs/web/mgis-template.html b/docs/web/mgis-template.html index 3a069345e..477b559d4 100644 --- a/docs/web/mgis-template.html +++ b/docs/web/mgis-template.html @@ -127,6 +127,11 @@
  • Version 3.1.x +
  • Version 3.2.x +
  • diff --git a/docs/web/release-notes-3.1.1.md b/docs/web/release-notes-3.1.1.md new file mode 100644 index 000000000..b6942b6d3 --- /dev/null +++ b/docs/web/release-notes-3.1.1.md @@ -0,0 +1,28 @@ +--- +title: MFrontGenericInterfaceSupport Version 3.1.1 +author: Thomas Helfer +date: 2026 +lang: en-EN +numbersections: true +documentclass: article +from: markdown+tex_math_single_backslash +geometry: + - margin=2cm +papersize: a4 +link-citations: true +colorlinks: true +figPrefixTemplate: "$$i$$" +tabPrefixTemplate: "$$i$$" +secPrefixTemplate: "$$i$$" +eqnPrefixTemplate: "($$i$$)" +bibliography: bibliography.bib +--- + +The page describes the new functionalities of Version 3.1.1 of the +`MFrontGenericInterfaceSupport` project. + +# Issues fixed + +## Issue 197: [MGIS/Function] Fix `CoalescedMemoryAccessCompositeTensorsView` for scalar values + +For more details, see diff --git a/docs/web/release-notes-3.2.md b/docs/web/release-notes-3.2.md new file mode 100644 index 000000000..383e674dc --- /dev/null +++ b/docs/web/release-notes-3.2.md @@ -0,0 +1,90 @@ +--- +title: MFrontGenericInterfaceSupport Version 3.2 +author: Thomas Helfer +date: 2026 +lang: en-EN +numbersections: true +documentclass: article +from: markdown+tex_math_single_backslash +geometry: + - margin=2cm +papersize: a4 +link-citations: true +colorlinks: true +figPrefixTemplate: "$$i$$" +tabPrefixTemplate: "$$i$$" +secPrefixTemplate: "$$i$$" +eqnPrefixTemplate: "($$i$$)" +bibliography: bibliography.bib +--- + +This version is meant to be used with `TFEL` Version 5.2. + +# New features of the `MGIS/Function` library + +## Functions using a strided memory access + +The following classes have been introduced: + +- `StridedCoalescedMemoryAccessTensorView` +- `StridedCoalescedMemoryAccessCompositeTensorsView` + +### `StridedCoalescedMemoryAccessTensorView` + +`StridedCoalescedMemoryAccessTensorView` is a tensorial function view +which stores its components in non interleaved manner using the +following scheme: + +~~~~ +| <------- Component 1 ---------> |....| <----- Component Nc ---------> | ++-------++-------++------++-------+----+-------++------++------++-------+ +| Elt 1 || Elt 2 || .... || Elt N |....| Elt 1 ||Elt 2 || .... || Elt N | ++-------++-------++------++-------+----+-------++------++------++-------+ +~~~~ + +#### Example of usage + +~~~~{.cxx} +constexpr auto ne = size_type{2}; +auto space = BasicLinearSpace{ne}; +std::array values = {1, 10, 2, 20, 3, 30, 4, 40}; +const auto f = StridedCoalescedMemoryAccessTensorView< + BasicLinearSpace, tfel::math::stensor<2, real>, false>{space, values}; +const auto e1 = f(0); +// e1 = {1, 2, 3, 4} +const auto e2 = f(1); +// e2 = {10, 20, 30, 40} +~~~~ + +## `StridedCoalescedMemoryAccessCompositeTensorsView` + +`StridedCoalescedMemoryAccessCompositeTensorsView` allows retrieving +scalar or tensorial objects which are stored in a non interleaved +manner. + +#### Example of usage + +~~~~{.cxx} +using CompositeFunctionView = + StridedCoalescedMemoryAccessCompositeTensorsView; +constexpr auto ne = size_type{2}; +auto space = BasicLinearSpace{ne}; +std::array values = {1, 10, 2, 20, 3, 30, 4, 40}; +const auto f = CompositeFunctionView{space, values}; +const auto e1 = f.get<0, tfel::math::stensor<2, real>>(0); +// e1 = {1, 2, 3, 4} +const auto e2 = f.get<0, tfel::math::stensor<2, real>>(1); +// e2 = {10, 20, 30, 40} +~~~~ + +# Acknowledgements + +The authors are grateful to the many contributors to the `TFEL/MFront` +project. This research was conducted in the framework of the PLEIADES +project, which was supported financially by the CEA (Commissariat à +l’Énergie Atomique et aux Énergies Alternatives), EDF (Électricité de +France) and Framatome. Work on `MGIS/Function` was performed as part of +the EURATOM OperaHPC Project co-funded by the European Union. + +# Issues fixed diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt index 58c3405aa..a946b6b78 100644 --- a/include/CMakeLists.txt +++ b/include/CMakeLists.txt @@ -97,4 +97,10 @@ if(enable-mgis-function) mgis_header(MGIS/Function/Tensors CoalescedMemoryAccessTensorView.ixx) mgis_header(MGIS/Function/Tensors CoalescedMemoryAccessCompositeTensorsView.hxx) mgis_header(MGIS/Function/Tensors CoalescedMemoryAccessCompositeTensorsView.ixx) + mgis_header(MGIS/Function StridedCoalescedMemoryAccessFunctionViewBase.hxx) + mgis_header(MGIS/Function StridedCoalescedMemoryAccessFunctionViewBase.ixx) + mgis_header(MGIS/Function/Tensors StridedCoalescedMemoryAccessTensorView.hxx) + mgis_header(MGIS/Function/Tensors StridedCoalescedMemoryAccessTensorView.ixx) + mgis_header(MGIS/Function/Tensors StridedCoalescedMemoryAccessCompositeTensorsView.hxx) + mgis_header(MGIS/Function/Tensors StridedCoalescedMemoryAccessCompositeTensorsView.ixx) endif(enable-mgis-function) diff --git a/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx b/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx new file mode 100644 index 000000000..f31e5c271 --- /dev/null +++ b/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx @@ -0,0 +1,123 @@ +/*! + * \file MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx + * \brief + * \author Thomas Helfer + * \date 17/01/2026 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_HXX +#define LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_HXX + +#include +#include +#include "MGIS/Config.hxx" +#include "MGIS/Contract.hxx" +#include "MGIS/Function/SpaceConcept.hxx" +#include "MGIS/Function/FunctionConcept.hxx" +#include "MGIS/Function/Function.hxx" +#include "MGIS/Function/Evaluator.hxx" + +namespace mgis::function { + + /*! + * \brief a class meant to describe a function, each component of which is + * stored contiguously in non interleaved manner using the following scheme: + * + * ~~~~ + * | <------- Component 1 ---------> |....| <----- Component Nc ---------> | + * +-------++-------++------++-------+----+-------++------++------++-------+ + * | Elt 1 || Elt 2 || .... || Elt N |....| Elt 1 ||Elt 2 || .... || Elt N | + * +-------++-------++------++-------+----+-------++------++------++-------+ + * ~~~~ + */ + template + requires(N > 0) struct StridedCoalescedMemoryAccessFunctionViewBase + : private PreconditionsChecker< + StridedCoalescedMemoryAccessFunctionViewBase> { + /*! + * \brief check that the preconditions to build the view are met + * \param[in] eh: error handler. + * \param[in] space: space + * \param[in] values: values + */ + [[nodiscard]] static constexpr bool checkPreconditions( + AbstractErrorHandler&, + const Space& space, + std::span) requires(!is_mutable); + /*! + * \param[in] space: space + * \param[in] values: values + */ + constexpr StridedCoalescedMemoryAccessFunctionViewBase( + const Space&, std::span) requires(!is_mutable); + /*! + * \brief check that the preconditions to build the view are met + * \param[in] eh: error handler. + * \param[in] space: space + * \param[in] values: values + */ + [[nodiscard]] static constexpr bool checkPreconditions( + AbstractErrorHandler&, const Space&, std::span); + /*! + * \param[in] space: space + * \param[in] values: values + */ + constexpr StridedCoalescedMemoryAccessFunctionViewBase(const Space&, + std::span); + /*! + * \return the data associated with an integration point + * \param[in] o: offset associated with the integration point + */ + [[nodiscard]] constexpr std::array getValues(const size_type) const + requires(LinearElementSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] e: element index + * \param[in] i: quadrature point index + */ + [[nodiscard]] constexpr std::array getValues(const size_type, + const size_type) const + requires(LinearQuadratureSpaceConcept); + //! \return the underlying quadrature space + [[nodiscard]] constexpr const Space& getSpace() const noexcept; + + protected: + /*! + * \param[in] space: space + * \param[in] values: values + */ + template + constexpr StridedCoalescedMemoryAccessFunctionViewBase( + const PreconditionsCheck&, + const Space&, + std::span) requires(!is_mutable); + /*! + * \param[in] space: space + * \param[in] values: values + */ + template + constexpr StridedCoalescedMemoryAccessFunctionViewBase( + const PreconditionsCheck&, + const Space&, + std::span); + //! \brief underlying discretization space + const Space space; + //! \brief pointer to the first component + const std::conditional_t data_pointer; + }; + +} // namespace mgis::function + +#include "MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.ixx" + +#endif /* LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_HXX \ + */ diff --git a/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.ixx b/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.ixx new file mode 100644 index 000000000..57537ab15 --- /dev/null +++ b/include/MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.ixx @@ -0,0 +1,148 @@ +/*! + * \file MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.ixx + * \brief + * \author Thomas Helfer + * \date 17/01/2026 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_IXX +#define LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_IXX + +namespace mgis::function { + + template + requires(N > 0) // + constexpr bool StridedCoalescedMemoryAccessFunctionViewBase< + Space, + N, + is_mutable>::checkPreconditions(AbstractErrorHandler& eh, + const Space& s, + std::span values) // + requires(!is_mutable) { + const auto ne = getSpaceSize(s); + if (values.size() != N * ne) { + return eh.registerErrorMessage("invalid number of values"); + } + return true; + } // end of checkPreconditions + + template + requires(N > 0) // + constexpr StridedCoalescedMemoryAccessFunctionViewBase:: + StridedCoalescedMemoryAccessFunctionViewBase( + const Space& s, + std::span values) requires(!is_mutable) + : StridedCoalescedMemoryAccessFunctionViewBase( + preconditions_check, s, values) { + } // end of StridedCoalescedMemoryAccessFunctionViewBase + + template + requires(N > 0) // + template + constexpr StridedCoalescedMemoryAccessFunctionViewBase:: + StridedCoalescedMemoryAccessFunctionViewBase( + const PreconditionsCheck& pcheck, + const Space& s, + std::span values) requires(!is_mutable) + : PreconditionsChecker( + pcheck, s, values), + space(s), + data_pointer(values.data()) { + } // end of StridedCoalescedMemoryAccessFunctionViewBase + + template + requires(N > 0) // + constexpr bool StridedCoalescedMemoryAccessFunctionViewBase< + Space, + N, + is_mutable>::checkPreconditions(AbstractErrorHandler& eh, + const Space& s, + std::span values) { + const auto ne = getSpaceSize(s); + if (values.size() != N * ne) { + return eh.registerErrorMessage("invalid number of values"); + } + return true; + } // end of checkPreconditions + + template + requires(N > 0) // + constexpr StridedCoalescedMemoryAccessFunctionViewBase:: + StridedCoalescedMemoryAccessFunctionViewBase(const Space& s, + std::span values) + : StridedCoalescedMemoryAccessFunctionViewBase( + preconditions_check, s, values) { + } // end of StridedCoalescedMemoryAccessFunctionViewBase + + template + requires(N > 0) // + template + constexpr StridedCoalescedMemoryAccessFunctionViewBase:: + StridedCoalescedMemoryAccessFunctionViewBase( + const PreconditionsCheck& pcheck, + const Space& s, + std::span values) + : PreconditionsChecker( + pcheck, s, values), + space(s), + data_pointer(values.data()) { + } // end of StridedCoalescedMemoryAccessFunctionViewBase + + template + requires(N > 0) // + constexpr const Space& StridedCoalescedMemoryAccessFunctionViewBase< + Space, + N, + is_mutable>::getSpace() const noexcept { + return this->space; + } // end of getSpace + + template + requires(N > 0) // + constexpr std::array // + StridedCoalescedMemoryAccessFunctionViewBase:: + getValues(const size_type i) const + requires(LinearElementSpaceConcept) { + return [ this, i ](std::index_sequence) + ->std::array { + const auto ne = getSpaceSize(this->space); + return {this->data_pointer[i + ne * Is]...}; + } + (std::make_index_sequence()); + } // end of getValues + + template + requires(N > 0) // + constexpr std::array // + StridedCoalescedMemoryAccessFunctionViewBase:: + getValues(const size_type e, + const size_type q) const // + requires(LinearQuadratureSpaceConcept) { + return [ this, e, q ](std::index_sequence) + ->std::array { + const auto ne = getSpaceSize(this->space); + const auto o = getQuadraturePointOffset(this->space, e, q); + return {this->data_pointer[o + ne * Is]...}; + } + (std::make_index_sequence()); + } // end of getValues + +} // end of namespace mgis::function + +#endif /* LIB_MGIS_FUNCTION_STRIDEDCOALESCEDMEMORYACCESSFUNCTIONVIEWBASE_IXX \ + */ diff --git a/include/MGIS/Function/Tensors.hxx b/include/MGIS/Function/Tensors.hxx index a6ea8e06d..67edd201b 100644 --- a/include/MGIS/Function/Tensors.hxx +++ b/include/MGIS/Function/Tensors.hxx @@ -25,6 +25,8 @@ #include "MGIS/Function/Tensors/TensorModifier.hxx" #include "MGIS/Function/Tensors/CoalescedMemoryAccessTensorView.hxx" #include "MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.hxx" +#include "MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.hxx" +#include "MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx" namespace mgis::function::internals { diff --git a/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.hxx b/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.hxx index 86af2c0f2..9f8ceaa6e 100644 --- a/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.hxx +++ b/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.hxx @@ -28,12 +28,25 @@ namespace mgis::function { - /*! - * \brief a tensor which is true if the type is equal to real or matches the - * TensorConcept - */ - template - concept ScalarOrTensorConcept = std::same_as || TensorConcept; + template + struct CoalescedMemoryAccessCompositeTensorsViewMutableValue { + using type = tfel::math::CoalescedView; + }; + + template <> + struct CoalescedMemoryAccessCompositeTensorsViewMutableValue { + using type = real&; + }; + + template + struct CoalescedMemoryAccessCompositeTensorsViewConstValue { + using type = tfel::math::CoalescedView; + }; + + template <> + struct CoalescedMemoryAccessCompositeTensorsViewConstValue { + using type = const real&; + }; /*! * \brief a coalescence view which acts as a tensorial function @@ -49,15 +62,13 @@ namespace mgis::function { // template using MutableValues = - std::conditional_t, - real&, - tfel::math::CoalescedView>; + typename CoalescedMemoryAccessCompositeTensorsViewMutableValue< + ValueType>::type; // template using ConstValues = - std::conditional_t, - const real&, - tfel::math::CoalescedView>; + typename CoalescedMemoryAccessCompositeTensorsViewConstValue< + ValueType>::type; // inheriting constructor using CoalescedMemoryAccessFunctionViewBase:: CoalescedMemoryAccessFunctionViewBase; @@ -69,8 +80,7 @@ namespace mgis::function { [[nodiscard]] constexpr MutableValues get(const size_type) requires( (begin + internals::CompileTimeSize::value <= N) && - is_mutable && LinearElementSpaceConcept && - (!hasElementWorkspace)); + is_mutable && LinearElementSpaceConcept); /*! * \return the data associated with an integration point * \param[in] e: element index @@ -80,8 +90,7 @@ namespace mgis::function { [[nodiscard]] constexpr MutableValues get(const size_type, const size_type) requires( (begin + internals::CompileTimeSize::value <= N) && - is_mutable && LinearQuadratureSpaceConcept && - (!hasCellWorkspace)); + is_mutable && LinearQuadratureSpaceConcept); /*! * \return the data associated with an integration point * \param[in] o: offset associated with the integration point @@ -90,8 +99,7 @@ namespace mgis::function { [[nodiscard]] constexpr ConstValues get( const size_type) const // requires((begin + internals::CompileTimeSize::value <= N) && - LinearElementSpaceConcept && - (!hasElementWorkspace)); + LinearElementSpaceConcept); /*! * \return the data associated with an integration point * \param[in] e: element index @@ -101,8 +109,7 @@ namespace mgis::function { [[nodiscard]] constexpr ConstValues get(const size_type, const size_type) const requires((begin + internals::CompileTimeSize::value <= N) && - LinearQuadratureSpaceConcept && - (!hasCellWorkspace)); + LinearQuadratureSpaceConcept); }; // end of CoalescedMemoryAccessCompositeTensorsView diff --git a/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.ixx b/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.ixx index f754ed7d1..a861f5cf8 100644 --- a/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.ixx +++ b/include/MGIS/Function/Tensors/CoalescedMemoryAccessCompositeTensorsView.ixx @@ -22,16 +22,16 @@ namespace mgis::function { template constexpr typename CoalescedMemoryAccessCompositeTensorsView:: - template MutableValues CoalescedMemoryAccessCompositeTensorsView< - Space, - N, - is_mutable>::get(const size_type i) // + template MutableValues // + CoalescedMemoryAccessCompositeTensorsView::get(const size_type + i) // requires((begin + internals::CompileTimeSize::value <= N) && - is_mutable && LinearElementSpaceConcept && - (!hasElementWorkspace)) { + is_mutable && LinearElementSpaceConcept) { if constexpr (std::same_as) { const auto ptr = this->template getValuePointer(i); - return *(ptr[0]); + return ptr[0]; } else { return tfel::math::CoalescedView( this->template getValuesPointers< @@ -44,17 +44,15 @@ namespace mgis::function { template constexpr typename CoalescedMemoryAccessCompositeTensorsView:: - template MutableValues CoalescedMemoryAccessCompositeTensorsView< - Space, - N, - is_mutable>::get(const size_type e, - const size_type q) // + template MutableValues // + CoalescedMemoryAccessCompositeTensorsView::get( + const size_type e, + const size_type q) // requires((begin + internals::CompileTimeSize::value <= N) && - is_mutable && LinearQuadratureSpaceConcept && - (!hasCellWorkspace)) { + is_mutable && LinearQuadratureSpaceConcept) { if constexpr (std::same_as) { const auto ptr = this->template getValuePointer(e, q); - return *(ptr[0]); + return ptr[0]; } else { return tfel::math::CoalescedView( this->template getValuesPointers< @@ -67,16 +65,16 @@ namespace mgis::function { template constexpr typename CoalescedMemoryAccessCompositeTensorsView:: - template ConstValues CoalescedMemoryAccessCompositeTensorsView< - Space, - N, - is_mutable>::get(const size_type i) const // + template ConstValues // + CoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::get(const size_type i) const // requires((begin + internals::CompileTimeSize::value <= N) && - LinearElementSpaceConcept && - (!hasElementWorkspace)) { + LinearElementSpaceConcept) { if constexpr (std::same_as) { const auto ptr = this->template getValuePointer(i); - return *(ptr[0]); + return ptr[0]; } else { return tfel::math::CoalescedView( this->template getValuesPointers< @@ -89,17 +87,15 @@ namespace mgis::function { template constexpr typename CoalescedMemoryAccessCompositeTensorsView:: - template ConstValues CoalescedMemoryAccessCompositeTensorsView< - Space, - N, - is_mutable>::get(const size_type e, - const size_type q) const // + template ConstValues // + CoalescedMemoryAccessCompositeTensorsView::get( + const size_type e, + const size_type q) const // requires((begin + internals::CompileTimeSize::value <= N) && - LinearQuadratureSpaceConcept && - (!hasCellWorkspace)) { + LinearQuadratureSpaceConcept) { if constexpr (std::same_as) { const auto ptr = this->template getValuePointer(e, q); - return *(ptr[0]); + return ptr[0]; } else { return tfel::math::CoalescedView( this->template getValuesPointers< diff --git a/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx new file mode 100644 index 000000000..afaf7f8c5 --- /dev/null +++ b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx @@ -0,0 +1,122 @@ +/*! + * \file + * MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx + * \brief + * \author Thomas Helfer + * \date 27/10/2025 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef MGIS_HAVE_TFEL +#error "TFEL is required to use strided coalesced memory access tensor views" +#endif /* MGIS_HAVE_TFEL */ + +#ifndef LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_HXX +#define LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_HXX + +#include +#include +#include +#include "TFEL/Math/Array/StridedCoalescedView.hxx" +#include "MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx" +#include "MGIS/Function/Tensors/TensorConcept.hxx" + +namespace mgis::function { + + template + struct StridedCoalescedMemoryAccessCompositeTensorsViewMutableValue { + using type = tfel::math::StridedCoalescedView; + }; + + template <> + struct StridedCoalescedMemoryAccessCompositeTensorsViewMutableValue { + using type = real&; + }; + + template + struct StridedCoalescedMemoryAccessCompositeTensorsViewConstValue { + using type = tfel::math::StridedCoalescedView; + }; + + template <> + struct StridedCoalescedMemoryAccessCompositeTensorsViewConstValue { + using type = const real&; + }; + + /*! + * \brief a strided coalescence view which acts as a tensorial function + * + * \tparam Space: functional space + * \tparam N: number of components + * \tparam is_mutable: boolean stating if the view can return mutable values. + */ + template + requires(N > 0) // + struct StridedCoalescedMemoryAccessCompositeTensorsView + : StridedCoalescedMemoryAccessFunctionViewBase { + // + template + using MutableValues = + typename StridedCoalescedMemoryAccessCompositeTensorsViewMutableValue< + ValueType>::type; + // + template + using ConstValues = + typename StridedCoalescedMemoryAccessCompositeTensorsViewConstValue< + ValueType>::type; + // inheriting constructor + using StridedCoalescedMemoryAccessFunctionViewBase:: + StridedCoalescedMemoryAccessFunctionViewBase; + /*! + * \return the data associated with an integration point + * \param[in] o: offset associated with the integration point + */ + template + [[nodiscard]] constexpr MutableValues + get(const size_type) requires( + (begin + internals::CompileTimeSize::value <= N) && + is_mutable && LinearElementSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] e: element index + * \param[in] i: quadrature point index + */ + template + [[nodiscard]] constexpr MutableValues + get(const size_type, const size_type) requires( + (begin + internals::CompileTimeSize::value <= N) && + is_mutable && LinearQuadratureSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] o: offset associated with the integration point + */ + template + [[nodiscard]] constexpr ConstValues get( + const size_type) const // + requires((begin + internals::CompileTimeSize::value <= N) && + LinearElementSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] e: element index + * \param[in] i: quadrature point index + */ + template + [[nodiscard]] constexpr ConstValues get(const size_type, + const size_type) const + requires((begin + internals::CompileTimeSize::value <= N) && + LinearQuadratureSpaceConcept); + + }; // end of StridedCoalescedMemoryAccessCompositeTensorsView + +} // namespace mgis::function + +#include "MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.ixx" + +#endif /* LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_HXX \ + */ diff --git a/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.ixx b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.ixx new file mode 100644 index 000000000..0a1733fa5 --- /dev/null +++ b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.ixx @@ -0,0 +1,112 @@ +/*! + * \file + * MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.ixx + * \brief + * \author Thomas Helfer + * \date 27/10/2025 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_IXX +#define LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_IXX + +namespace mgis::function { + + template + requires(N > 0) // + template + constexpr typename StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::template MutableValues // + StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::get(const size_type i) // + requires((begin + internals::CompileTimeSize::value <= N) && + is_mutable && LinearElementSpaceConcept) { + const auto ne = getSpaceSize(this->space); + if constexpr (std::same_as) { + return this->data_pointer[begin * ne + i]; + } else { + return tfel::math::StridedCoalescedView( + this->data_pointer + begin * ne + i, ne); + } + } // end of get + + template + requires(N > 0) // + template + constexpr typename StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::template MutableValues // + StridedCoalescedMemoryAccessCompositeTensorsView:: + get(const size_type e, + const size_type q) // + requires((begin + internals::CompileTimeSize::value <= N) && + is_mutable && LinearQuadratureSpaceConcept) { + const auto ne = getSpaceSize(this->space); + const auto o = getQuadraturePointOffset(this->space, e, q); + if constexpr (std::same_as) { + return this->data_pointer[begin * ne + o]; + } else { + return tfel::math::StridedCoalescedView( + this->data_pointer + begin * ne + o, ne); + } + } // end of get + + template + requires(N > 0) // + template + constexpr typename StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::template ConstValues // + StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::get(const size_type i) const // + requires((begin + internals::CompileTimeSize::value <= N) && + LinearElementSpaceConcept) { + const auto ne = getSpaceSize(this->space); + if constexpr (std::same_as) { + return this->data_pointer[begin * ne + i]; + } else { + return tfel::math::StridedCoalescedView( + this->data_pointer + begin * ne + i, ne); + } + } // end of get + + template + requires(N > 0) // + template + constexpr typename StridedCoalescedMemoryAccessCompositeTensorsView< + Space, + N, + is_mutable>::template ConstValues // + StridedCoalescedMemoryAccessCompositeTensorsView:: + get(const size_type e, + const size_type q) const // + requires((begin + internals::CompileTimeSize::value <= N) && + LinearQuadratureSpaceConcept) { + const auto ne = getSpaceSize(this->space); + const auto o = getQuadraturePointOffset(this->space, e, q); + if constexpr (std::same_as) { + return this->data_pointer[begin * ne + o]; + } else { + return tfel::math::StridedCoalescedView( + this->data_pointer + begin * ne + o, ne); + } + } // end of get + +} // namespace mgis::function + +#endif /* LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSCOMPOSITETENSORSVIEW_IXX \ + */ diff --git a/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.hxx b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.hxx new file mode 100644 index 000000000..f420f2da1 --- /dev/null +++ b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.hxx @@ -0,0 +1,89 @@ +/*! + * \file MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.hxx + * \brief + * \author Thomas Helfer + * \date 27/10/2025 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef MGIS_HAVE_TFEL +#error "TFEL is required to use coalesced memory access tensor views" +#endif /* MGIS_HAVE_TFEL */ + +#ifndef LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_HXX +#define LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_HXX + +#include "TFEL/Math/Array/StridedCoalescedView.hxx" +#include "MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx" +#include "MGIS/Function/Tensors/TensorConcept.hxx" + +namespace mgis::function { + + /*! + * \brief a coalescence view which acts as a tensorial function + * + * \tparam Space: functional space + * \tparam TensorType: tensorial object mapped + * \tparam is_mutable: boolean stating if the view can return mutable values. + */ + template + struct StridedCoalescedMemoryAccessTensorView + : StridedCoalescedMemoryAccessFunctionViewBase< + Space, + internals::CompileTimeSize::value, + is_mutable> { + // + using MutableValues = tfel::math::StridedCoalescedView; + // + using ConstValues = tfel::math::StridedCoalescedView; + + // inheriting constructor + using StridedCoalescedMemoryAccessFunctionViewBase< + Space, + internals::CompileTimeSize::value, + is_mutable>::StridedCoalescedMemoryAccessFunctionViewBase; + /*! + * \return the data associated with an integration point + * \param[in] o: offset associated with the integration point + */ + [[nodiscard]] constexpr MutableValues operator()(const size_type) requires( + is_mutable&& LinearElementSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] e: element index + * \param[in] i: quadrature point index + */ + [[nodiscard]] constexpr MutableValues + operator()(const size_type, const size_type) requires( + is_mutable&& LinearQuadratureSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] o: offset associated with the integration point + */ + [[nodiscard]] constexpr ConstValues operator()(const size_type) const + requires(LinearElementSpaceConcept); + /*! + * \return the data associated with an integration point + * \param[in] e: element index + * \param[in] i: quadrature point index + */ + [[nodiscard]] constexpr ConstValues operator()(const size_type, + const size_type) const + requires(LinearQuadratureSpaceConcept); + + }; // end of StridedCoalescedMemoryAccessTensorView + +} // namespace mgis::function + +#include "MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.ixx" + +#endif /* LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_HXX \ + */ diff --git a/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.ixx b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.ixx new file mode 100644 index 000000000..7c233a41e --- /dev/null +++ b/include/MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.ixx @@ -0,0 +1,86 @@ +/*! + * \file MGIS/Function/Tensors/StridedCoalescedMemoryAccessTensorView.ixx + * \brief + * \author Thomas Helfer + * \date 17/01/2026 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#ifndef LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_IXX +#define LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_IXX + +namespace mgis::function { + + template + constexpr + typename StridedCoalescedMemoryAccessTensorView::MutableValues + StridedCoalescedMemoryAccessTensorView:: + operator()(const size_type i) requires( + is_mutable&& LinearElementSpaceConcept) { + const auto ne = getSpaceSize(this->space); + return tfel::math::StridedCoalescedView(this->data_pointer + i, + ne); + } // end of operator() + + template + constexpr + typename StridedCoalescedMemoryAccessTensorView::MutableValues + StridedCoalescedMemoryAccessTensorView:: + operator()(const size_type e, + const size_type q) // + requires(is_mutable&& LinearQuadratureSpaceConcept) { + const auto ne = getSpaceSize(this->space); + const auto o = getQuadraturePointOffset(this->space, e, q); + return tfel::math::StridedCoalescedView(this->data_pointer + o, + ne); + } // end of operator() + + template + constexpr + typename StridedCoalescedMemoryAccessTensorView::ConstValues + StridedCoalescedMemoryAccessTensorView:: + operator()(const size_type i) const // + requires(LinearElementSpaceConcept) { + const auto ne = getSpaceSize(this->space); + return tfel::math::StridedCoalescedView( + this->data_pointer + i, ne); + } // end of operator() + + template + constexpr + typename StridedCoalescedMemoryAccessTensorView::ConstValues + StridedCoalescedMemoryAccessTensorView:: + operator()(const size_type e, const size_type q) const // + requires(LinearQuadratureSpaceConcept) { + const auto ne = getSpaceSize(this->space); + const auto o = getQuadraturePointOffset(this->space, e, q); + return tfel::math::StridedCoalescedView( + this->data_pointer + o, ne); + } // end of operator() + +} // namespace mgis::function + +#endif /* LIB_MGIS_FUNCTION_TENSORS_STRIDEDCOALESCEDMEMORYACCESSTENSORVIEW_IXX \ + */ diff --git a/include/MGIS/Function/Tensors/TensorConcept.hxx b/include/MGIS/Function/Tensors/TensorConcept.hxx index 8dbd64d1a..e1cc9a950 100644 --- a/include/MGIS/Function/Tensors/TensorConcept.hxx +++ b/include/MGIS/Function/Tensors/TensorConcept.hxx @@ -145,6 +145,13 @@ namespace mgis::function { template concept TensorConcept = internals::IsTensor::value; + /*! + * \brief a tensor which is true if the type is equal to real or matches the + * TensorConcept + */ + template + concept ScalarOrTensorConcept = std::same_as || TensorConcept; + } // end of namespace mgis::function #endif /* LIB_MGIS_FUNCTION_TENSORCONCEPT_HXX */ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 066c6d3f5..e2f0c5134 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -40,6 +40,7 @@ if(enable-mgis-function) Evaluator.cxx UniformEvaluator.cxx CoalescedMemoryAccessFunctionView.cxx + StridedCoalescedMemoryAccessFunctionView.cxx MaterialFunctionManager.cxx) if(MGIS_HAVE_TFEL) list(APPEND MFrontGenericInterface_SOURCES diff --git a/src/StridedCoalescedMemoryAccessFunctionView.cxx b/src/StridedCoalescedMemoryAccessFunctionView.cxx new file mode 100644 index 000000000..cebe1670a --- /dev/null +++ b/src/StridedCoalescedMemoryAccessFunctionView.cxx @@ -0,0 +1,18 @@ +/*! + * \file StridedCoalescedMemoryAccessFunctionView.cxx + * \brief + * \author Thomas Helfer + * \date 17/01/2026 + * \copyright (C) Copyright Thomas Helfer 2018. + * Use, modification and distribution are subject + * to one of the following licences: + * - GNU Lesser General Public License (LGPL), Version 3.0. (See accompanying + * file LGPL-3.0.txt) + * - CECILL-C, Version 1.0 (See accompanying files + * CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt). + */ + +#include "MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx" +#ifdef MGIS_HAVE_TFEL +#include "MGIS/Function/Tensors/StridedCoalescedMemoryAccessCompositeTensorsView.hxx" +#endif /* MGIS_HAVE_TFEL */ diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 4e099397b..db6a8a709 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -545,6 +545,29 @@ if((CMAKE_HOST_WIN32) AND (NOT MSYS)) PROPERTY ENVIRONMENT "PATH=$\;${MGIS_PATH_STRING}") endif((CMAKE_HOST_WIN32) AND (NOT MSYS)) +add_executable(StridedCoalescedMemoryAccessFunctionViewTest + EXCLUDE_FROM_ALL + StridedCoalescedMemoryAccessFunctionViewTest.cxx) +target_link_libraries(StridedCoalescedMemoryAccessFunctionViewTest + PRIVATE MFrontGenericInterface tfel::TFELTests) +add_test(NAME StridedCoalescedMemoryAccessFunctionViewTest + COMMAND StridedCoalescedMemoryAccessFunctionViewTest) +add_dependencies(check StridedCoalescedMemoryAccessFunctionViewTest) +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.2.0) + target_compile_definitions(StridedCoalescedMemoryAccessFunctionViewTest + PRIVATE MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS) + endif(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 14.2.0) +endif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if(CMAKE_CXX_COMPILER_ID STREQUAL "NVHPC") + target_compile_definitions(StridedCoalescedMemoryAccessFunctionViewTest + PRIVATE MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS) +endif() +if((CMAKE_HOST_WIN32) AND (NOT MSYS)) + set_property(TEST StridedCoalescedMemoryAccessFunctionViewTest + PROPERTY ENVIRONMENT "PATH=$\;${MGIS_PATH_STRING}") +endif((CMAKE_HOST_WIN32) AND (NOT MSYS)) + add_executable(MechanicalEvaluatorsTest EXCLUDE_FROM_ALL MechanicalEvaluatorsTest.cxx) diff --git a/tests/CoalescedMemoryAccessFunctionViewTest.cxx b/tests/CoalescedMemoryAccessFunctionViewTest.cxx index e1eb986fd..ead15f533 100644 --- a/tests/CoalescedMemoryAccessFunctionViewTest.cxx +++ b/tests/CoalescedMemoryAccessFunctionViewTest.cxx @@ -88,6 +88,9 @@ struct CoalescedMemoryAccessTensorViewTest final std::array values = {1, 10, 2, 20, 3, 30, 4, 40}; const auto oscalar_functions = splitArrayIntoScalarFunctionViews<4>(ctx, space, values); + if (!oscalar_functions.has_value()) { + raise("splitArrayIntoScalarFunctionViews failed"); + } const auto f = CoalescedMemoryAccessTensorView, false>{ @@ -113,6 +116,7 @@ struct CoalescedMemoryAccessCompositeTensorsViewTest final this->test2(); this->test3(); this->test4(); + this->test5(); return this->result; } @@ -186,7 +190,8 @@ struct CoalescedMemoryAccessCompositeTensorsViewTest final auto ctx = Context{}; TFEL_TESTS_ASSERT( !CompositeView::checkPreconditions(ctx, space, out_values)); - TFEL_TESTS_CHECK_EQUAL(ctx.getRawErrorMessage(), "invalid number of values"); + TFEL_TESTS_CHECK_EQUAL(ctx.getRawErrorMessage(), + "invalid number of values"); if constexpr (config::contract_violation_policy == config::ContractViolationPolicy::RAISE) { bool has_thrown = false; @@ -255,6 +260,28 @@ struct CoalescedMemoryAccessCompositeTensorsViewTest final TFEL_TESTS_STATIC_ASSERT(local_abs(r[11]) < seps); #endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ } // end of test4 + void test5() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + using ImmutableCompositeView = + CoalescedMemoryAccessCompositeTensorsView; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + auto space = BasicLinearSpace{2}; + const auto values = std::array{2, 3, -1, 4}; + const auto view = ImmutableCompositeView{space, values}; + return std::array{view.get<0, real>(0), view.get<1, real>(0), + view.get<0, real>(1), view.get<1, real>(1)}; + }(); + constexpr auto eps = real{1e-14}; + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 2) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] + 1) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2] - 3) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[3] - 4) < eps); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } // end of test5 }; TFEL_TESTS_GENERATE_PROXY(CoalescedMemoryAccessFunctionViewBaseTest, diff --git a/tests/StridedCoalescedMemoryAccessFunctionViewTest.cxx b/tests/StridedCoalescedMemoryAccessFunctionViewTest.cxx new file mode 100644 index 000000000..2cef3db15 --- /dev/null +++ b/tests/StridedCoalescedMemoryAccessFunctionViewTest.cxx @@ -0,0 +1,294 @@ +/*! + * \file tests/StridedCoalescedMemoryAccessFunctionViewTest.cxx + * \brief + * \author Thomas Helfer + * \date 26/10/2025 + */ + +#include +#include +#include +#include +#include "TFEL/Tests/TestCase.hxx" +#include "TFEL/Tests/TestProxy.hxx" +#include "TFEL/Tests/TestManager.hxx" +#include "TFEL/Material/Lame.hxx" +#include "MGIS/Function/SharedSpace.hxx" +#include "MGIS/Function/BasicLinearSpace.hxx" +#include "MGIS/Function/BasicLinearQuadratureSpace.hxx" +#include "MGIS/Function/StridedCoalescedMemoryAccessFunctionViewBase.hxx" +#include "MGIS/Function/Tensors.hxx" + +namespace mgis::function {} // end of namespace mgis::function + +struct StridedCoalescedMemoryAccessFunctionViewBaseTest final + : public tfel::tests::TestCase { + StridedCoalescedMemoryAccessFunctionViewBaseTest() + : tfel::tests::TestCase( + "MGIS/Function", + "StridedCoalescedMemoryAccessFunctionViewBaseTests") { + } // end of StridedCoalescedMemoryAccessFunctionViewBaseTest + tfel::tests::TestResult execute() override { + this->test1(); + return this->result; + } + + private: + void test1() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = + []() -> std::tuple, std::array> { + auto space = BasicLinearSpace{2}; + auto values = std::vector{5, 12, -2, 3}; + auto coalesced_view = + StridedCoalescedMemoryAccessFunctionViewBase( + space, values); + auto ptr0 = coalesced_view.getValues(0); + auto ptr1 = coalesced_view.getValues(1); + return {std::array{ptr0[0], ptr0[1]}, // + std::array{ptr1[0], ptr1[1]}}; + }(); + TFEL_TESTS_STATIC_ASSERT(local_abs(std::get<0>(r)[0] - 5) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(std::get<0>(r)[1] + 2) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(std::get<1>(r)[0] - 12) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(std::get<1>(r)[1] - 3) < 1e-14); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } +}; + +struct StridedCoalescedMemoryAccessTensorViewTest final + : public tfel::tests::TestCase { + StridedCoalescedMemoryAccessTensorViewTest() + : tfel::tests::TestCase("MGIS/Function", + "StridedCoalescedMemoryAccessTensorViewTests") { + } // end of StridedCoalescedMemoryAccessTensorViewTest + tfel::tests::TestResult execute() override { + this->test1(); + return this->result; + } + + private: + void test1() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + constexpr auto ne = size_type{2}; + auto space = BasicLinearSpace{ne}; + std::array values = {1, 10, 2, 20, 3, 30, 4, 40}; + const auto f = StridedCoalescedMemoryAccessTensorView< + BasicLinearSpace, tfel::math::stensor<2, real>, false>{space, values}; + return std::array{tfel::math::trace(f(0)), tfel::math::trace(f(1)), + tfel::math::trace(f(1) - 3 * f(0))}; + }(); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 6) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] - 60) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2] - 42) < 1e-14); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } +}; + +struct StridedCoalescedMemoryAccessCompositeTensorsViewTest final + : public tfel::tests::TestCase { + StridedCoalescedMemoryAccessCompositeTensorsViewTest() + : tfel::tests::TestCase( + "MGIS/Function", + "StridedCoalescedMemoryAccessCompositeTensorsViewTests") { + } // end of StridedCoalescedMemoryAccessCompositeTensorsViewTest + tfel::tests::TestResult execute() override { + this->test1(); + this->test2(); + this->test3(); + this->test4(); + this->test5(); + return this->result; + } + + private: + void test1() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + constexpr auto ne = size_type{2}; + auto space = BasicLinearSpace{ne}; + std::array values = {1, 10, 2, 20, 3, 30, 4, 40}; + auto f = + StridedCoalescedMemoryAccessCompositeTensorsView{space, + values}; + return std::array{ + tfel::math::trace(f.get<0, tfel::math::stensor<2, real>>(0)), + tfel::math::trace(f.get<0, tfel::math::stensor<2, real>>(1)), + tfel::math::trace(f.get<0, tfel::math::stensor<2, real>>(1) - + 3 * f.get<0, tfel::math::stensor<2, real>>(0))}; + }(); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 6) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] - 60) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2] - 42) < 1e-14); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } + void test2() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + const auto ne = size_type{2}; + auto space = BasicLinearSpace{ne}; + std::array out_values = {0, 0, 0, 0, 0, 0, 0, 0}; + std::array in_values = {1, 10, 2, 20, 3, 30, 4, 40}; + auto out = + StridedCoalescedMemoryAccessCompositeTensorsView{ + space, out_values}; + const auto in = + StridedCoalescedMemoryAccessCompositeTensorsView{space, + in_values}; + for (size_type idx = 0; idx != ne; ++idx) { + auto o = out.get<0, tfel::math::stensor<2, real>>(idx); + const auto i = in.get<0, tfel::math::stensor<2, real>>(idx); + o = i; + } + return out_values; + }(); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 1) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] - 10) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2] - 2) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[3] - 20) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[4] - 3) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[5] - 30) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[6] - 4) < 1e-14); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[7] - 40) < 1e-14); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } + void test3() { + using namespace mgis; + using namespace mgis::function; + using CompositeView = + StridedCoalescedMemoryAccessCompositeTensorsView; + auto space = BasicLinearSpace{2}; + std::array out_values = {0, 0, 0, 0, 0, 0}; + auto ctx = Context{}; + TFEL_TESTS_ASSERT( + !CompositeView::checkPreconditions(ctx, space, out_values)); + TFEL_TESTS_CHECK_EQUAL(ctx.getRawErrorMessage(), + "invalid number of values"); + if constexpr (config::contract_violation_policy == + config::ContractViolationPolicy::RAISE) { + bool has_thrown = false; + try { + auto out = + StridedCoalescedMemoryAccessCompositeTensorsView{space, + out_values}; + } catch (std::exception&) { + has_thrown = true; + } + TFEL_TESTS_ASSERT(has_thrown); + } + } // end of test3 + void test4() { + // elasticity +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + using CompositeView = + StridedCoalescedMemoryAccessCompositeTensorsView; + using ImmutableCompositeView = + StridedCoalescedMemoryAccessCompositeTensorsView; + constexpr auto young = real{150e9}; + constexpr auto nu = real{1} / 3; + constexpr auto lambda = tfel::material::computeLambda(young, nu); + constexpr auto mu = tfel::material::computeMu(young, nu); + constexpr auto exx = 1e-3; + constexpr auto eyy = -real{1e-3} / 3; + constexpr auto seps = young * 1e-14; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + auto space = BasicLinearSpace{2}; + auto sig_values = std::array{0, 0, 0, 0, 0, 0, // + 0, 0, 0, 0, 0, 0}; + const auto eto_values = std::array{exx, -exx, // + eyy, -exx, // + eyy, -exx, // + 0, 0, // + 0, 0, // + 0, 0}; + auto eto_view = ImmutableCompositeView{space, eto_values}; + auto sig_view = CompositeView{space, sig_values}; + for (size_type idx = 0; idx != getSpaceSize(space); ++idx) { + using Stensor = tfel::math::stensor<3u, real>; + constexpr auto id = Stensor::Id(); + const auto eto = eto_view.get<0, Stensor>(idx); + auto sig = sig_view.get<0, Stensor>(idx); + sig = lambda * tfel::math::trace(eto) * id + 2 * mu * eto; + } + return sig_values; + }(); + constexpr auto K = (3 * lambda + 2 * mu) / 3; + constexpr auto pr = K * (-3 * exx); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 150e6) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[4]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[6]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[8]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[10]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] - pr) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[3] - pr) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[5] - pr) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[7]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[9]) < seps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[11]) < seps); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } // end of test4 + void test5() { +#ifndef MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS + using namespace mgis; + using namespace mgis::function; + using ImmutableCompositeView = + StridedCoalescedMemoryAccessCompositeTensorsView; + auto local_abs = [](const mgis::real r) { return r > 0 ? r : -r; }; + constexpr auto r = []() -> std::array { + auto ctx = ContractViolationHandler{}; + auto space = BasicLinearSpace{2}; + const auto values = std::array{2, 3, -1, 4}; + const auto view = ImmutableCompositeView{space, values}; + return std::array{view.get<0, real>(0), view.get<1, real>(0), + view.get<0, real>(1), view.get<1, real>(1)}; + }(); + constexpr auto eps = real{1e-14}; + TFEL_TESTS_STATIC_ASSERT(local_abs(r[0] - 2) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[1] + 1) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[2] - 3) < eps); + TFEL_TESTS_STATIC_ASSERT(local_abs(r[3] - 4) < eps); +#endif /* MGIS_DISABLE_CONSTEXPR_FUNCTION_TESTS */ + } // end of test5 +}; + +TFEL_TESTS_GENERATE_PROXY(StridedCoalescedMemoryAccessFunctionViewBaseTest, + "StridedCoalescedMemoryAccessFunctionViewBaseTest"); +TFEL_TESTS_GENERATE_PROXY(StridedCoalescedMemoryAccessTensorViewTest, + "StridedCoalescedMemoryAccessTensorViewTest"); +TFEL_TESTS_GENERATE_PROXY( + StridedCoalescedMemoryAccessCompositeTensorsViewTest, + "StridedCoalescedMemoryAccessCompositeTensorsViewTest"); + +/* coverity [UNCAUGHT_EXCEPT]*/ +int main() { + auto& m = tfel::tests::TestManager::getTestManager(); + m.addTestOutput(std::cout); + m.addXMLTestOutput("StridedCoalescedMemoryAccessFunctionTest.xml"); + return m.execute().success() ? EXIT_SUCCESS : EXIT_FAILURE; +}