Page MenuHomec4science

field_container.hh
No OneTemporary

File Metadata

Created
Wed, May 8, 03:21

field_container.hh

/*
* SPDX-License-Indentifier: AGPL-3.0-or-later
*
* Copyright (©) 2016-2022 EPFL (École Polytechnique Fédérale de Lausanne),
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
* Copyright (©) 2020-2022 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 FIELD_CONTAINER_HH
#define FIELD_CONTAINER_HH
/* -------------------------------------------------------------------------- */
#include "grid.hh"
#include "model_type.hh"
#include <algorithm>
#include <boost/variant.hpp>
#include <memory>
#include <string>
#include <unordered_map>
/* -------------------------------------------------------------------------- */
namespace tamaas {
/* -------------------------------------------------------------------------- */
struct FieldContainer {
// Useful type names
using Key = std::string;
template <class T>
using GridBasePtr = std::shared_ptr<GridBase<T>>;
// TODO C++17: switch to std::variant
using Value =
boost::variant<GridBasePtr<Real>, GridBasePtr<UInt>, GridBasePtr<Int>,
GridBasePtr<Complex>, GridBasePtr<bool>>;
using FieldsMap = std::unordered_map<Key, Value>;
/// Destructor
virtual ~FieldContainer() = default;
/// Access field pointer in const context
const Value& at(const Key& name) const { return fields_.at(name); }
/// Access/insert new pointer
Value& operator[](const Key& name) { return fields_[name]; }
/// Access field of given type (non-const)
template <class T>
auto& field(const Key& name) {
return *boost::get<GridBasePtr<T>>(at(name));
}
/// Access field of given type (const)
template <class T>
const auto& field(const Key& name) const {
return *boost::get<GridBasePtr<T>>(at(name));
}
/// Return field keys
decltype(auto) fields() const {
std::vector<Key> keys;
std::transform(fields_.cbegin(), fields_.cend(), std::back_inserter(keys),
[](auto&& pair) { return pair.first; });
return keys;
}
/// Return pointer map to fields
const auto& fields_map() const { return fields_; }
/// Return a field with given dimension, create if not in container
template <model_type type, bool boundary, typename T,
template <typename, UInt> class GridType = Grid,
class Container = void>
std::shared_ptr<GridType<T, detail::dim_choice<type, boundary>::value>>
request(const Key& name, Container&& n, UInt nc) {
constexpr auto dim = detail::dim_choice<type, boundary>::value;
using U = typename GridType<T, dim>::value_type;
auto has_right_dims = [&n, nc](const GridBase<U>& grid) {
if (grid.getDimension() != dim)
return false;
auto& grid_d = dynamic_cast<const GridType<T, dim>&>(grid);
return std::equal(n.begin(), n.end(), grid_d.sizes().begin()) and
grid.getNbComponents() == nc;
};
auto ptr_cast = [](auto&& ptr) {
return std::dynamic_pointer_cast<GridType<T, dim>>(
boost::get<GridBasePtr<U>>(ptr));
};
// If field in container + has requested dims
if (fields_.find(name) != fields_.end() and has_right_dims(field<U>(name)))
return ptr_cast(at(name));
// Field not found or invalid, make new one
(*this)[name] = allocateGrid<type, boundary, T, GridType>(
std::forward<Container>(n), nc);
return ptr_cast(at(name));
}
/// Return a field with given dimension, create if not in container
template <bool boundary, typename T, typename Container>
decltype(auto) request(const Key& name, model_type type, Container&& n,
UInt nc) {
return model_type_dispatch(
[this, &name, &n, nc](auto&& type) -> GridBasePtr<T> {
constexpr auto mtype = std::decay_t<decltype(type)>::value;
return this->request<mtype, boundary, T>(
name, std::forward<Container>(n), nc);
},
type);
}
private:
FieldsMap fields_;
};
} // namespace tamaas
#endif

Event Timeline