Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F61207843
model_type.hh
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sun, May 5, 05:25
Size
9 KB
Mime Type
text/x-c++
Expires
Tue, May 7, 05:25 (2 d)
Engine
blob
Format
Raw Data
Handle
17480468
Attached To
rTAMAAS tamaas
model_type.hh
View Options
/*
* SPDX-License-Indentifier: AGPL-3.0-or-later
*
* Copyright (©) 2016-2023 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
* Copyright (©) 2020-2023 Lucas Frérot
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/* -------------------------------------------------------------------------- */
#ifndef MODEL_TYPE_HH
#define MODEL_TYPE_HH
/* -------------------------------------------------------------------------- */
#include "grid.hh"
#include "grid_base.hh"
#include "static_types.hh"
#include "tamaas.hh"
#include <algorithm>
#include <boost/preprocessor/cat.hpp>
#include <boost/preprocessor/seq.hpp>
#include <boost/preprocessor/stringize.hpp>
#include <memory>
/* -------------------------------------------------------------------------- */
namespace
tamaas
{
/// Types for grid dimensions and number of components
enum
class
model_type
{
basic_1d
,
///< one component line
basic_2d
,
///< one component surface
surface_1d
,
///< two components line
surface_2d
,
///< three components surface
volume_1d
,
///< two components volume
volume_2d
///< three components volume
};
/// Trait class to store physical dimension of domain, of boundary and
/// number of components
template
<
model_type
type
>
struct
model_type_traits
{};
#define MODEL_TYPE_TRAITS_MACRO(type, dim, comp, bdim) \
template <> \
struct model_type_traits<model_type::type> { \
static constexpr char repr[]{#type}; \
static constexpr UInt dimension = dim; \
static constexpr UInt components = comp; \
static constexpr UInt boundary_dimension = bdim; \
static constexpr UInt voigt = voigt_size<comp>::value; \
static const std::vector<UInt> indices; \
}
MODEL_TYPE_TRAITS_MACRO
(
basic_1d
,
1
,
1
,
1
);
MODEL_TYPE_TRAITS_MACRO
(
basic_2d
,
2
,
1
,
2
);
MODEL_TYPE_TRAITS_MACRO
(
surface_1d
,
1
,
2
,
1
);
MODEL_TYPE_TRAITS_MACRO
(
surface_2d
,
2
,
3
,
2
);
MODEL_TYPE_TRAITS_MACRO
(
volume_1d
,
2
,
2
,
1
);
MODEL_TYPE_TRAITS_MACRO
(
volume_2d
,
3
,
3
,
2
);
#undef MODEL_TYPE_TRAITS_MACRO
// clang-format off
#ifdef TAMAAS_MODEL_TYPES
#undef TAMAAS_MODEL_TYPES
#endif
#define TAMAAS_MODEL_TYPES \
(model_type::basic_1d) \
(model_type::basic_2d) \
(model_type::surface_1d) \
(model_type::surface_2d) \
(model_type::volume_1d) \
(model_type::volume_2d)
// clang-format on
namespace
detail
{
/// Convert enum value to a type
template
<
model_type
type
>
using
model_type_t
=
std
::
integral_constant
<
model_type
,
type
>
;
/// Convert dim value to a type
template
<
UInt
dim
>
using
dim_t
=
std
::
integral_constant
<
UInt
,
dim
>
;
#define MAKE_MODEL_TYPE(r, x, type) (model_type_t<type>)
/// Enumeration of model types
using
model_types_t
=
std
::
tuple
<
BOOST_PP_SEQ_ENUM
(
BOOST_PP_SEQ_FOR_EACH
(
MAKE_MODEL_TYPE
,
~
,
TAMAAS_MODEL_TYPES
))
>
;
#undef MAKE_MODEL_TYPE
#define MAKE_DIM_TYPE(r, x, dim) (dim_t<dim>)
/// Enumeration of dimension types
using
dims_t
=
std
::
tuple
<
BOOST_PP_SEQ_ENUM
(
BOOST_PP_SEQ_FOR_EACH
(
MAKE_DIM_TYPE
,
~
,
(
1
)(
2
)(
3
)))
>
;
#undef MAKE_DIM_TYPE
}
// namespace detail
/// Print function for model_type
inline
std
::
ostream
&
operator
<<
(
std
::
ostream
&
o
,
const
model_type
&
val
)
{
switch
(
val
)
{
#define PRINT_MODEL_TYPE(r, data, type) \
case type: \
o << model_type_traits<type>::repr; \
break;
BOOST_PP_SEQ_FOR_EACH
(
PRINT_MODEL_TYPE
,
model_type
,
TAMAAS_MODEL_TYPES
);
#undef PRINT_MODEL_TYPE
}
return
o
;
}
#undef ALLOC_GRID_CASE_MACRO
// Implementing a static dispatch mechanism
// References for a generic static dispatch:
// https://stackoverflow.com/questions/39915986/solutions-for-dynamic-dispatch-on-unrelated-types
// constexpr map: Jason Turner C++ Weekly ep 233
// C++14 limited dispatch (Nicolas Richart):
// akantu/features/eigen::src/common/aka_element_classes_info_inline_impl.hh
// TODO when switching C++17, implement with constexpr map
namespace
detail
{
/// Specialized static dispatch for all model types
template
<
class
Function
,
class
DynamicType
,
class
DefaultFunction
,
std
::
size_t
...
Is
>
constexpr
decltype
(
auto
)
static_switch_dispatch
(
const
model_types_t
&
,
Function
&&
function
,
const
DynamicType
&
type
,
DefaultFunction
&&
default_function
,
std
::
index_sequence
<
Is
...
>
)
{
#define SWITCH_DISPATCH_CASE(r, data, type) \
case type: { \
return function(model_type_t<type>{}); \
}
switch
(
type
)
{
BOOST_PP_SEQ_FOR_EACH
(
SWITCH_DISPATCH_CASE
,
~
,
TAMAAS_MODEL_TYPES
);
default
:
return
default_function
(
type
);
}
#undef SWITCH_DISPATCH_CASE
}
/// Specialized static dispatch for all dimensions
template
<
class
Function
,
class
DynamicType
,
class
DefaultFunction
,
std
::
size_t
...
Is
>
constexpr
decltype
(
auto
)
static_switch_dispatch
(
const
dims_t
&
,
Function
&&
function
,
const
DynamicType
&
dim
,
DefaultFunction
&&
default_function
,
std
::
index_sequence
<
Is
...
>
)
{
#define SWITCH_DISPATCH_CASE(r, data, dim) \
case dim: { \
return function(dim_t<dim>{}); \
}
switch
(
dim
)
{
BOOST_PP_SEQ_FOR_EACH
(
SWITCH_DISPATCH_CASE
,
~
,
(
1
)(
2
)(
3
));
default
:
return
default_function
(
dim
);
}
#undef SWITCH_DISPATCH_CASE
}
/// Dispatch to tuple of types with a default case
template
<
class
TypeTuple
,
class
Function
,
class
DefaultFunction
,
class
DynamicType
>
constexpr
decltype
(
auto
)
tuple_dispatch_with_default
(
Function
&&
function
,
DefaultFunction
&&
default_function
,
const
DynamicType
&
type
)
{
return
detail
::
static_switch_dispatch
(
TypeTuple
{},
std
::
forward
<
Function
>
(
function
),
type
,
std
::
forward
<
DefaultFunction
>
(
default_function
),
std
::
make_index_sequence
<
std
::
tuple_size
<
TypeTuple
>::
value
>
{});
}
/// Dispatch to tuple of types, error on default
template
<
class
TypeTuple
,
class
Function
,
class
DynamicType
>
constexpr
decltype
(
auto
)
tuple_dispatch
(
Function
&&
function
,
const
DynamicType
&
type
)
{
return
tuple_dispatch_with_default
<
TypeTuple
>
(
std
::
forward
<
Function
>
(
function
),
[](
auto
&&
type
)
->
decltype
(
function
(
std
::
tuple_element_t
<
0
,
TypeTuple
>
{}))
{
throw
model_type_error
{
TAMAAS_MSG
(
"Unknown type in static dispatch"
,
type
)};
},
type
);
}
}
// namespace detail
/// Static dispatch lambda to model types
template
<
class
Function
>
constexpr
decltype
(
auto
)
model_type_dispatch
(
Function
&&
function
,
model_type
type
)
{
return
detail
::
tuple_dispatch
<
detail
::
model_types_t
>
(
std
::
forward
<
Function
>
(
function
),
type
);
}
/// Static dispatch lambda to dimensions
template
<
class
Function
>
constexpr
decltype
(
auto
)
dimension_dispatch
(
Function
&&
function
,
UInt
dim
)
{
return
detail
::
tuple_dispatch
<
detail
::
dims_t
>
(
std
::
forward
<
Function
>
(
function
),
dim
);
}
/// \cond DO_NOT_DOCUMENT
namespace
detail
{
template
<
model_type
type
,
bool
boundary
>
using
dim_choice
=
std
::
integral_constant
<
UInt
,
(
boundary
)
?
model_type_traits
<
type
>::
boundary_dimension
:
model_type_traits
<
type
>::
dimension
>
;
}
// namespace detail
/// \endcond
/// Allocate a Grid unique_ptr
template
<
model_type
type
,
bool
boundary
,
typename
T
,
template
<
typename
,
UInt
>
class
GridType
=
Grid
,
class
Container
=
void
>
std
::
unique_ptr
<
GridType
<
T
,
detail
::
dim_choice
<
type
,
boundary
>::
value
>>
allocateGrid
(
Container
&&
n
,
UInt
nc
)
{
return
std
::
make_unique
<
GridType
<
T
,
detail
::
dim_choice
<
type
,
boundary
>::
value
>>
(
std
::
begin
(
n
),
std
::
end
(
n
),
nc
);
}
/// Helper function for grid allocation with model type
template
<
bool
boundary
,
typename
T
,
typename
Container
>
decltype
(
auto
)
allocateGrid
(
model_type
type
,
Container
&&
n
)
{
return
model_type_dispatch
(
[
&
n
](
auto
&&
type
)
->
std
::
unique_ptr
<
GridBase
<
T
>>
{
constexpr
auto
mtype
=
std
::
decay_t
<
decltype
(
type
)
>::
value
;
return
allocateGrid
<
mtype
,
boundary
,
T
>
(
std
::
forward
<
Container
>
(
n
),
model_type_traits
<
mtype
>::
components
);
},
type
);
}
/// Helper function for grid allocation with non-standard components
template
<
bool
boundary
,
typename
T
,
typename
Container
>
decltype
(
auto
)
allocateGrid
(
model_type
type
,
Container
&&
n
,
UInt
nc
)
{
return
model_type_dispatch
(
[
&
n
,
nc
](
auto
&&
type
)
->
std
::
unique_ptr
<
GridBase
<
T
>>
{
constexpr
auto
mtype
=
std
::
decay_t
<
decltype
(
type
)
>::
value
;
return
allocateGrid
<
mtype
,
boundary
,
T
>
(
std
::
forward
<
Container
>
(
n
),
nc
);
},
type
);
}
}
// namespace tamaas
/* -------------------------------------------------------------------------- */
#endif
// MODEL_TYPE_HH
Event Timeline
Log In to Comment