From 347b81e4eb5ea54a51c7335a0f406b6d365066ee Mon Sep 17 00:00:00 2001 From: Daniel Schwen Date: Sat, 18 Nov 2023 16:34:44 -0700 Subject: [PATCH] New approach (#26053) --- .../ProjectedStatefulMaterialStorageAction.h | 156 +++++++++++--- .../auxkernels/NodalPatchRecoveryAux.h | 13 +- .../auxkernels/NodalPatchRecoveryAuxBase.h | 36 ++++ ...tedMaterialPropertyNodalPatchRecoveryAux.h | 30 +++ .../auxkernels/ProjectedStatefulMaterialAux.h | 23 +- framework/include/base/Registry.h | 6 +- .../materials/InterpolatedStatefulMaterial.h | 47 ++--- ...jectedStatefulMaterialNodalPatchRecovery.h | 104 +++++++++- framework/include/utils/SerialAccess.h | 110 ++++++---- .../include/utils_nonunity/RankFourTensor.h | 12 -- .../include/utils_nonunity/RankTwoTensor.h | 15 -- .../ProjectedStatefulMaterialStorageAction.C | 164 +-------------- .../src/auxkernels/NodalPatchRecoveryAux.C | 63 +----- .../auxkernels/NodalPatchRecoveryAuxBase.C | 79 +++++++ ...tedMaterialPropertyNodalPatchRecoveryAux.C | 40 ++++ .../auxkernels/ProjectedStatefulMaterialAux.C | 51 +++-- .../materials/InterpolatedStatefulMaterial.C | 112 +++------- ...jectedStatefulMaterialNodalPatchRecovery.C | 196 +++++++++++++++++- .../projected_stateful_materials/test.i | 4 + unit/src/MooseServerTest.C | 3 +- unit/src/SerialAccessTest.C | 36 +++- 21 files changed, 812 insertions(+), 488 deletions(-) create mode 100644 framework/include/auxkernels/NodalPatchRecoveryAuxBase.h create mode 100644 framework/include/auxkernels/ProjectedMaterialPropertyNodalPatchRecoveryAux.h create mode 100644 framework/src/auxkernels/NodalPatchRecoveryAuxBase.C create mode 100644 framework/src/auxkernels/ProjectedMaterialPropertyNodalPatchRecoveryAux.C diff --git a/framework/include/actions/ProjectedStatefulMaterialStorageAction.h b/framework/include/actions/ProjectedStatefulMaterialStorageAction.h index 753cdc37fa5e..21e658f1ad0d 100644 --- a/framework/include/actions/ProjectedStatefulMaterialStorageAction.h +++ b/framework/include/actions/ProjectedStatefulMaterialStorageAction.h @@ -10,8 +10,18 @@ #pragma once #include "Action.h" +#include "Registry.h" +#include "Conversion.h" +#include "SerialAccess.h" +#include "RankTwoTensorForward.h" +#include "RankFourTensorForward.h" #include "libmesh/fe_type.h" +// created types +#include +#include +#include + /** * Set up AuxKernels and AuxVariables for projected material property storage (PoMPS). */ @@ -30,38 +40,26 @@ class ProjectedStatefulMaterialStorageAction : public Action /// List of supported types typedef Moose::TypeList SupportedTypes; + /// get an enum with all supported types + static MooseEnum getTypeEnum(); + + template + void processProperty(const MaterialPropertyName & prop_name); + protected: - /** - * Perform setup for a single scalar component of the material property prop_name, and gather the - * names of teh AuxVariables used to represent each component in `vars`. - */ - void processComponent(const std::string & prop_name, - std::vector idx, - std::vector & vars, - bool is_ad); - - /** - * Add the material object to obtain the interpolated old state (for use with - * InterpolatedStatefulMaterialPropertyInterface) - */ - void addMaterial(const std::string & prop_type, - const std::string & prop_name, - std::vector & vars); - - enum class PropertyType + template + struct ProcessProperty { - REAL, - REALVECTORVALUE, - RANKTWOTENSOR, - RANKFOURTENSOR + static void apply(ProjectedStatefulMaterialStorageAction * self, + const MaterialPropertyName & prop_name) + { + self->processProperty(prop_name); + self->processProperty(prop_name); + } }; - typedef std::pair PropertyInfo; - /** - * Return the property type and whether to use AD or not. If no property with a supported type is - * found, throw an error. - */ - PropertyInfo checkProperty(const std::string & prop_name); + template + static MooseEnum getTypeEnum(typename Moose::TypeList); const std::vector & _prop_names; @@ -70,3 +68,105 @@ class ProjectedStatefulMaterialStorageAction : public Action const std::string _var_type; const std::string _pomps_prefix; }; + +template +MooseEnum +ProjectedStatefulMaterialStorageAction::getTypeEnum(Moose::TypeList) +{ + return MooseEnum(Moose::stringify(std::vector{typeid(Ts).name()...}, " ")); +} + +template +void +ProjectedStatefulMaterialStorageAction::processProperty(const MaterialPropertyName & prop_name) +{ + // check if a property of type T exists + const auto & data = _problem->getMaterialData(Moose::BLOCK_MATERIAL_DATA); + if (!data.haveGenericProperty(prop_name)) + return; + + // number of scalar components + const auto size = Moose::SerialAccess::size(); + + // generate variable names + std::vector vars; + for (const auto i : make_range(size)) + vars.push_back("_var_" + prop_name + '_' + Moose::stringify(i)); + + if (_current_task == "setup_projected_properties") + { + // add the AuxVars for storage + for (const auto & var : vars) + { + auto params = _factory.getValidParams(_var_type); + params.applyParameters(parameters()); + params.set>("outputs") = {"none"}; + _problem->addAuxVariable(_var_type, var, params); + } + + // add material + { + const auto type = Registry::getClassName>(); + auto params = _factory.getValidParams(type); + params.applySpecificParameters(parameters(), {"block"}); + params.template set>("old_state") = vars; + params.template set("prop_name") = prop_name; + _problem->addMaterial(type, "_mat_" + prop_name, params); + } + + // use nodal patch recovery for lagrange + if (_fe_type.family == LAGRANGE) + { + // nodal variables require patch recovery (add user object) + const auto & type = + Registry::getClassName>(); + auto params = _factory.getValidParams(type); + params.applySpecificParameters(parameters(), {"block"}); + params.template set("property") = prop_name; + params.template set("patch_polynomial_order") = _order; + params.template set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + params.template set("force_preaux") = true; + _problem->addUserObject(type, "_npruo_" + prop_name, params); + } + } + + if (_current_task == "add_aux_kernel") + { + // create variables + std::vector auxnames; + for (const auto i : make_range(size)) + auxnames.push_back("_aux_" + prop_name + '_' + Moose::stringify(i)); + + // use nodal patch recovery for lagrange + if (_fe_type.family == LAGRANGE) + { + // nodal variables require patch recovery (add aux kernel) + const auto & type = "ProjectedMaterialPropertyNodalPatchRecoveryAux"; + for (const auto i : make_range(size)) + { + auto params = _factory.getValidParams(type); + params.applySpecificParameters(parameters(), {"block"}); + params.template set("variable") = vars[i]; + params.template set("component") = i; + params.template set("nodal_patch_recovery_uo") = "_npruo_" + prop_name; + params.template set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + _problem->addAuxKernel(type, auxnames[i], params); + } + } + else + { + // elemental variables + const auto & type = Registry::getClassName>(); + for (const auto i : make_range(size)) + { + auto params = _factory.getValidParams(type); + params.applySpecificParameters(parameters(), {"block"}); + params.template set("variable") = vars[i]; + params.template set("component") = i; + params.template set("prop") = prop_name; + params.template set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + _problem->addAuxKernel(type, auxnames[i], params); + } + } + } +} diff --git a/framework/include/auxkernels/NodalPatchRecoveryAux.h b/framework/include/auxkernels/NodalPatchRecoveryAux.h index 4a99886e784f..5d089d2d8c84 100644 --- a/framework/include/auxkernels/NodalPatchRecoveryAux.h +++ b/framework/include/auxkernels/NodalPatchRecoveryAux.h @@ -9,25 +9,20 @@ #pragma once -#include "AuxKernel.h" +#include "NodalPatchRecoveryAuxBase.h" +/// Forward declare user object class NodalPatchRecoveryBase; -class NodalPatchRecoveryAux : public AuxKernel +class NodalPatchRecoveryAux : public NodalPatchRecoveryAuxBase { public: static InputParameters validParams(); NodalPatchRecoveryAux(const InputParameters & parameters); - /** - * Block restrict elements on which to perform the variable/property nodal recovery. - */ - void blockRestrictElements(std::vector & elem_ids, - const std::vector & node_to_elem_pair_elems) const; - protected: - virtual Real computeValue() override; + virtual Real nodalPatchRecovery() override; private: const NodalPatchRecoveryBase & _npr; diff --git a/framework/include/auxkernels/NodalPatchRecoveryAuxBase.h b/framework/include/auxkernels/NodalPatchRecoveryAuxBase.h new file mode 100644 index 000000000000..f24e1f12cf2b --- /dev/null +++ b/framework/include/auxkernels/NodalPatchRecoveryAuxBase.h @@ -0,0 +1,36 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "AuxKernel.h" + +class NodalPatchRecoveryBase; + +class NodalPatchRecoveryAuxBase : public AuxKernel +{ +public: + static InputParameters validParams(); + + NodalPatchRecoveryAuxBase(const InputParameters & parameters); + + /** + * Block restrict elements on which to perform the variable/property nodal recovery. + */ + void blockRestrictElements(std::vector & elem_ids, + const std::vector & node_to_elem_pair_elems) const; + +protected: + virtual Real computeValue() override; + + /// Override this to get the fitted value form a Nodal Patch Recovery User Object + virtual Real nodalPatchRecovery() = 0; + + std::vector _elem_ids; +}; diff --git a/framework/include/auxkernels/ProjectedMaterialPropertyNodalPatchRecoveryAux.h b/framework/include/auxkernels/ProjectedMaterialPropertyNodalPatchRecoveryAux.h new file mode 100644 index 000000000000..3e3fa25f1fdc --- /dev/null +++ b/framework/include/auxkernels/ProjectedMaterialPropertyNodalPatchRecoveryAux.h @@ -0,0 +1,30 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "NodalPatchRecoveryAuxBase.h" + +/// Forward declare user object +class ProjectedStatefulMaterialNodalPatchRecoveryBase; + +class ProjectedMaterialPropertyNodalPatchRecoveryAux : public NodalPatchRecoveryAuxBase +{ +public: + static InputParameters validParams(); + + ProjectedMaterialPropertyNodalPatchRecoveryAux(const InputParameters & parameters); + +protected: + virtual Real nodalPatchRecovery() override; + +private: + const ProjectedStatefulMaterialNodalPatchRecoveryBase & _npr; + const unsigned int _component; +}; diff --git a/framework/include/auxkernels/ProjectedStatefulMaterialAux.h b/framework/include/auxkernels/ProjectedStatefulMaterialAux.h index 5e4c56de9e8d..66b321208f3a 100644 --- a/framework/include/auxkernels/ProjectedStatefulMaterialAux.h +++ b/framework/include/auxkernels/ProjectedStatefulMaterialAux.h @@ -16,7 +16,7 @@ class MaterialBase; -template +template class ProjectedStatefulMaterialAuxTempl : public AuxKernel { public: @@ -29,11 +29,26 @@ class ProjectedStatefulMaterialAuxTempl : public AuxKernel protected: virtual Real computeValue() override; - const IndexableProperty _prop; const SubdomainID & _current_subdomain_id; std::map> _required_materials; + + const GenericMaterialProperty & _prop; + + const unsigned int _component; }; -typedef ProjectedStatefulMaterialAuxTempl ProjectedStatefulMaterialAux; -typedef ProjectedStatefulMaterialAuxTempl ADProjectedStatefulMaterialAux; +typedef ProjectedStatefulMaterialAuxTempl ProjectedStatefulMaterialRealAux; +typedef ProjectedStatefulMaterialAuxTempl ADProjectedStatefulMaterialRealAux; +typedef ProjectedStatefulMaterialAuxTempl + ProjectedStatefulMaterialRealVectorValueAux; +typedef ProjectedStatefulMaterialAuxTempl + ADProjectedStatefulMaterialRealVectorValueAux; +typedef ProjectedStatefulMaterialAuxTempl + ProjectedStatefulMaterialRankTwoTensorAux; +typedef ProjectedStatefulMaterialAuxTempl + ADProjectedStatefulMaterialRankTwoTensorAux; +typedef ProjectedStatefulMaterialAuxTempl + ProjectedStatefulMaterialRankFourTensorAux; +typedef ProjectedStatefulMaterialAuxTempl + ADProjectedStatefulMaterialRankFourTensorAux; diff --git a/framework/include/base/Registry.h b/framework/include/base/Registry.h index 5ea0027c31a3..c8143ee04179 100644 --- a/framework/include/base/Registry.h +++ b/framework/include/base/Registry.h @@ -253,10 +253,8 @@ template std::string Registry::getRegisteredName() { - for (const auto & [name, reg_ptr] : getRegistry()._name_to_entry) - if (std::dynamic_pointer_cast(reg_ptr)) - return name; - mooseError("The object of C++ type '", demangle(typeid(T).name()), "' has not registered."); + mooseDeprecated("Use Registry::getClassName() instead."); + return getClassName(); } template diff --git a/framework/include/materials/InterpolatedStatefulMaterial.h b/framework/include/materials/InterpolatedStatefulMaterial.h index f67749ef00a7..dee50c281e81 100644 --- a/framework/include/materials/InterpolatedStatefulMaterial.h +++ b/framework/include/materials/InterpolatedStatefulMaterial.h @@ -14,16 +14,16 @@ #include "RankFourTensorForward.h" /** - * PowerLawSoftening is a smeared crack softening model that - * uses a power law equation to soften the tensile response. - * It is for use with ComputeSmearedCrackingStress. + * Reconstitute a materal property from the old and older states of projected AuxVariables. Use + * though the ProjectedStatefulMaterialStorageAction. */ -class InterpolatedStatefulMaterial : public Material +template +class InterpolatedStatefulMaterialTempl : public Material { public: static InputParameters validParams(); - InterpolatedStatefulMaterial(const InputParameters & parameters); + InterpolatedStatefulMaterialTempl(const InputParameters & parameters); virtual void computeQpProperties() override; @@ -34,29 +34,22 @@ class InterpolatedStatefulMaterial : public Material /// Older projected state const std::vector _older_state; + /// total number of components + const std::size_t _size; + /// emitted property name const MaterialPropertyName _prop_name; - /// Property type - enum class PropType - { - REAL, - REALVECTORVALUE, - RANKTWOTENSOR, - RANKFOURTENSOR - } _prop_type; - - ///@{ Old interpolated properties - MaterialProperty * _prop_old_real; - MaterialProperty * _prop_old_realvectorvalue; - MaterialProperty * _prop_old_ranktwotensor; - MaterialProperty * _prop_old_rankfourtensor; - ///@} - - ///@{ Older interpolated properties - MaterialProperty * _prop_older_real; - MaterialProperty * _prop_older_realvectorvalue; - MaterialProperty * _prop_older_ranktwotensor; - MaterialProperty * _prop_older_rankfourtensor; - ///@} + /// Old interpolated property + MaterialProperty & _prop_old; + + /// Older interpolated properties + MaterialProperty & _prop_older; }; + +typedef InterpolatedStatefulMaterialTempl InterpolatedStatefulMaterialReal; +typedef InterpolatedStatefulMaterialTempl + InterpolatedStatefulMaterialRealVectorValue; +typedef InterpolatedStatefulMaterialTempl InterpolatedStatefulMaterialRankTwoTensor; +typedef InterpolatedStatefulMaterialTempl + InterpolatedStatefulMaterialRankFourTensor; diff --git a/framework/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h b/framework/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h index 6e6688ac1c09..483c11bc4440 100644 --- a/framework/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h +++ b/framework/include/userobjects/ProjectedStatefulMaterialNodalPatchRecovery.h @@ -10,28 +10,112 @@ #pragma once // MOOSE includes -#include "NodalPatchRecoveryMaterialProperty.h" +#include "ElementUserObject.h" +#include "SerialAccess.h" -#include +class ProjectedStatefulMaterialNodalPatchRecoveryBase : public ElementUserObject +{ +public: + static InputParameters validParams(); + + ProjectedStatefulMaterialNodalPatchRecoveryBase(const InputParameters & parameters) + : ElementUserObject(parameters) + { + } -class MaterialBase; + virtual Real nodalPatchRecovery(const Point & p, + const std::vector & elem_ids, + std::size_t component) const = 0; +}; -/** - * Nodal patch recovery for material property components for projected stateful properties - */ -class ProjectedStatefulMaterialNodalPatchRecovery : public NodalPatchRecoveryMaterialProperty +template +class ProjectedStatefulMaterialNodalPatchRecoveryTempl + : public ProjectedStatefulMaterialNodalPatchRecoveryBase { public: static InputParameters validParams(); - ProjectedStatefulMaterialNodalPatchRecovery(const InputParameters & parameters); + ProjectedStatefulMaterialNodalPatchRecoveryTempl(const InputParameters & parameters); + + /** + * Solve the least-squares problem. Use the fitted coefficients to calculate the value at the + * requested point. + * + * @param p Point at which to compute the fitted value + * @param elem_ids Ids of the elements in the patch + * @param component Index of the component to compute the fitted value of + * @return The fitted value + */ + virtual Real nodalPatchRecovery(const Point & p, + const std::vector & elem_ids, + std::size_t component) const override; virtual void initialSetup() override; -protected: - virtual Real computeValue() override; + virtual void initialize() override; + virtual void execute() override; + virtual void threadJoin(const UserObject &) override; + virtual void finalize() override; + +private: + /** + * Compute the P vector at a given point + * i.e. given dim = 2, order = 2, polynomial P has the following terms: + * 1 + * x + * y + * x^2 + * xy + * y^2 + * + * @param q_point point at which to evaluate the polynomial basis + */ + RealEigenVector evaluateBasisFunctions(const Point & q_point) const; + + /// data type stored for each element + typedef std::pair> ElementData; + /// current quadrature point + unsigned int _qp; + + /// number of scalar components in the recovered type + std::size_t _n_components; + + /// The polynomial order, default is variable order + const unsigned int _patch_polynomial_order; + + /// The multi-index table + const std::vector> _multi_index; + + /// Number of basis functions + const unsigned int _q; + + /// stored property + const GenericMaterialProperty & _prop; + + /// The element-level A matrix and the element-level b vectors for each component + std::map _abs; + + /// Current subdomain const SubdomainID & _current_subdomain_id; + /// list of require materials that need to be explicityly initialized at step zero std::map> _required_materials; }; + +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ProjectedStatefulMaterialNodalPatchRecoveryReal; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ADProjectedStatefulMaterialNodalPatchRecoveryReal; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ProjectedStatefulMaterialNodalPatchRecoveryRealVectorValue; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ADProjectedStatefulMaterialNodalPatchRecoveryRealVectorValue; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ProjectedStatefulMaterialNodalPatchRecoveryRankTwoTensor; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ADProjectedStatefulMaterialNodalPatchRecoveryRankTwoTensor; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ProjectedStatefulMaterialNodalPatchRecoveryRankFourTensor; +typedef ProjectedStatefulMaterialNodalPatchRecoveryTempl + ADProjectedStatefulMaterialNodalPatchRecoveryRankFourTensor; diff --git a/framework/include/utils/SerialAccess.h b/framework/include/utils/SerialAccess.h index 3f4d81561c86..c8a7241b9ca5 100644 --- a/framework/include/utils/SerialAccess.h +++ b/framework/include/utils/SerialAccess.h @@ -12,6 +12,10 @@ // MOOSE includes #include "Moose.h" #include "MooseTypes.h" +#include "RankTwoTensorForward.h" +#include "RankFourTensorForward.h" + +#include namespace Moose { @@ -23,48 +27,53 @@ namespace Moose template struct SerialAccess { - static typename T::value_type * data(T & obj) - { - static_assert(always_false, - "Specialize SerialAccess for this type and implement the data() method."); - } - constexpr std::size_t * size(T &) - { - static_assert(always_false, - "Specialize SerialAccess for this type and implement the size() method."); - return 0; - } + static_assert(always_false, "Specialize SerialAccess for this type."); }; -/// simple Real specialization -template <> -struct SerialAccess -{ - static Real * data(Real & obj) { return &obj; } - static constexpr std::size_t size(Real &) { return 1u; } -}; -template <> -struct SerialAccess -{ - static ADReal * data(ADReal & obj) { return &obj; } - static constexpr std::size_t size(ADReal &) { return 1u; } -}; +// Specializations for scalar types +#define SERIAL_ACCESS_SCALAR(type) \ + template <> \ + struct SerialAccess \ + { \ + static type * data(type & obj) { return &obj; } \ + static constexpr std::size_t size(type &) { return 1u; } \ + static constexpr std::size_t size() { return 1u; } \ + } -/// (AD)RealVectorValue etc. specialization -template -struct SerialAccess> -{ - static T * data(VectorValue & obj) { return &obj(0u); } - static constexpr std::size_t size(VectorValue &) { return Moose::dim; } -}; +SERIAL_ACCESS_SCALAR(Real); +SERIAL_ACCESS_SCALAR(const Real); +SERIAL_ACCESS_SCALAR(ADReal); +SERIAL_ACCESS_SCALAR(const ADReal); + +// constant size containers +#define SERIAL_ACCESS_CONST_SIZE(type, dataptr, sizeval) \ + template \ + struct SerialAccess> \ + { \ + static auto * data(type & obj) { return dataptr; } \ + static constexpr std::size_t size(type &) { return sizeval; } \ + static constexpr std::size_t size() { return sizeval; } \ + } -/// DenseVector specialization -template -struct SerialAccess> -{ - static T * data(DenseVector & obj) { return &obj(0u); } - static std::size_t size(DenseVector & obj) { return obj.size(); } -}; +SERIAL_ACCESS_CONST_SIZE(VectorValue, &obj(0u), Moose::dim); +SERIAL_ACCESS_CONST_SIZE(const VectorValue, &obj(0u), Moose::dim); +SERIAL_ACCESS_CONST_SIZE(RankTwoTensorTempl, &obj(0u, 0u), RankTwoTensorTempl::N2); +SERIAL_ACCESS_CONST_SIZE(const RankTwoTensorTempl, &obj(0u, 0u), RankTwoTensorTempl::N2); +SERIAL_ACCESS_CONST_SIZE(RankFourTensorTempl, &obj(0u, 0u, 0u, 0u), RankFourTensorTempl::N4); +SERIAL_ACCESS_CONST_SIZE(const RankFourTensorTempl, + &obj(0u, 0u, 0u, 0u), + RankFourTensorTempl::N4); + +// dynamic size containers (determining size requires an object instance) +#define SERIAL_ACCESS_DYNAMIC_SIZE(type, dataptr, sizeval) \ + template \ + struct SerialAccess> \ + { \ + static auto * data(type & obj) { return dataptr; } \ + static constexpr std::size_t size(type & obj) { return sizeval; } \ + } + +SERIAL_ACCESS_DYNAMIC_SIZE(DenseVector, &obj(0u), obj.size()); /** * Value type helper (necessary for any type that does not have a value_type @@ -89,7 +98,8 @@ struct SerialAccessVlaueTypeHelper template class SerialAccessRange { - typedef typename SerialAccessVlaueTypeHelper::value_type V; + typedef typename SerialAccessVlaueTypeHelper::type>::value_type R; + typedef typename std::conditional, const R, R>::type V; public: class iterator @@ -126,9 +136,10 @@ class SerialAccessRange } iterator begin() const { return _begin; } - iterator end() const { return _end; } + V & operator[](int i) { return *(&*_begin + i); } + private: iterator _begin, _end; }; @@ -144,16 +155,27 @@ serialAccess(T & obj) template struct TypeList { + typedef std::tuple Tuple; + typedef std::tuple PointerTuple; + static constexpr std::size_t size = sizeof...(Ts); }; /// Type loop -template