Skip to content
Snippets Groups Projects
Commit 7b17a5b0 authored by Christoph Lehmann's avatar Christoph Lehmann
Browse files

[PL] Reflection support for setting IP data

parent 8a0f3b66
No related branches found
No related tags found
No related merge requests found
/**
* \file
* \copyright
* Copyright (c) 2012-2022, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include <Eigen/Core>
#include <vector>
#include "MathLib/KelvinVector.h"
#include "ReflectionIPData.h"
namespace ProcessLib::Reflection
{
namespace detail
{
template <int dim, typename IPData, typename Accessor>
void setIPData(double const* values,
std::vector<IPData>& ip_data_vector,
Accessor const& accessor)
{
using AccessorResult = std::invoke_result_t<Accessor, IPData&>;
using AccessorResultStripped = std::remove_cvref_t<AccessorResult>;
constexpr auto num_comp = NumberOfComponents<AccessorResultStripped>::value;
auto constexpr kv_size =
MathLib::KelvinVector::kelvin_vector_dimensions(dim);
auto const num_int_pts = ip_data_vector.size();
if constexpr (num_comp == 1)
{
for (unsigned ip = 0; ip < num_int_pts; ++ip)
{
accessor(ip_data_vector[ip]) = values[ip];
}
}
else
{
auto const values_mat =
Eigen::Map<Eigen::Matrix<double, num_comp, Eigen::Dynamic,
Eigen::ColMajor> const>(values, num_comp,
num_int_pts);
for (unsigned ip = 0; ip < num_int_pts; ++ip)
{
if constexpr (num_comp == kv_size)
{
accessor(ip_data_vector[ip]) =
MathLib::KelvinVector::symmetricTensorToKelvinVector(
values_mat.col(ip));
}
else
{
accessor(ip_data_vector[ip]) = values_mat.col(ip);
}
}
}
}
// Sets IP data if the passed name equals the one in refl_data.
// Returns true if IP have been set, false otherwise.
template <int dim, typename IPData, typename Accessor_CurrentLevelFromIPData,
typename Class, typename Member>
bool setIPDataIfNameMatches(std::string const& name, double const* values,
std::vector<IPData>& ip_data_vector,
Accessor_CurrentLevelFromIPData const& accessor,
ReflectionData<Class, Member> const& refl_data)
{
auto const field = refl_data.field;
auto const accessor_field_from_ip_data = [accessor,
field](IPData& ip_data) -> Member&
{ return accessor(ip_data).*field; };
if constexpr (detail::has_reflect<Member>)
{
return 0 != reflectSetIPData<dim>(name, values, ip_data_vector,
accessor_field_from_ip_data,
Member::reflect());
}
else
{
if (refl_data.name != name)
{
return false;
}
setIPData<dim>(values, ip_data_vector, accessor_field_from_ip_data);
return true;
}
}
template <int dim, typename IPData, typename Accessor_CurrentLevelFromIPData,
typename... Class, typename... Member, std::size_t... Idcs>
std::size_t reflectSetIPData(
std::string const& name, double const* values,
std::vector<IPData>& ip_data_vector,
Accessor_CurrentLevelFromIPData const& accessor,
std::tuple<ReflectionData<Class, Member>...> const& refl_data,
std::index_sequence<Idcs...>)
{
// uses short-circuit evaluation of the fold || ... to stop after the first
// match
bool have_consumed_data =
((setIPDataIfNameMatches<dim>(name, values, ip_data_vector, accessor,
std::get<Idcs>(refl_data))) ||
...);
if (have_consumed_data)
{
return ip_data_vector.size();
}
return 0;
}
template <int dim, typename IPData, typename Accessor_CurrentLevelFromIPData,
typename... Class, typename... Member>
std::size_t reflectSetIPData(
std::string const& name, double const* values,
std::vector<IPData>& ip_data_vector,
Accessor_CurrentLevelFromIPData const& accessor,
std::tuple<ReflectionData<Class, Member>...> const& refl_data)
{
return reflectSetIPData<dim>(name, values, ip_data_vector, accessor,
refl_data,
std::make_index_sequence<sizeof...(Class)>{});
}
} // namespace detail
/**
* Sets integration point data for the property with the given \c name to the
* passed \c values.
*
* Possible candidate properties are obtained from \c IPData via some sort of
* reflection.
*
* \return The number of integration points if data has been set, zero
* if no property with the given \c name has been found.
*/
template <int dim, typename IPData>
std::size_t reflectSetIPData(std::string const& name, double const* values,
std::vector<IPData>& ip_data_vector)
{
return detail::reflectSetIPData<dim>(name, values, ip_data_vector,
std::identity{}, IPData::reflect());
}
} // namespace ProcessLib::Reflection
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment