Page MenuHomec4science

component_libmultiscale.hh
No OneTemporary

File Metadata

Created
Wed, May 29, 01:56

component_libmultiscale.hh

/**
* @file component_libmultiscale.hh
*
* @author Guillaume Anciaux <guillaume.anciaux@epfl.ch>
*
* @date Mon Sep 08 23:40:22 2014
*
* @brief This describe the root objects to be combined into valid LM
* components
*
* @section LICENSE
*
* Copyright (©) 2010-2011 EPFL (Ecole Polytechnique Fédérale de Lausanne)
* Laboratory (LSMS - Laboratoire de Simulation en Mécanique des Solides)
*
* LibMultiScale is free software: you can redistribute it and/or modify it
* under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* LibMultiScale 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 Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with LibMultiScale. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_HH__
#define __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_HH__
/* -------------------------------------------------------------------------- */
#include "auto_arguments.hh"
#include "container.hh"
#include "lm_common.hh"
#include "lm_object.hh"
/* -------------------------------------------------------------------------- */
#include <cmath>
#include <limits>
#include <map>
#include <memory>
#include <stdexcept>
#include <tuple>
#include <typeindex>
#include <typeinfo>
/* -------------------------------------------------------------------------- */
__BEGIN_LIBMULTISCALE__
/* -------------------------------------------------------------------------- */
class Component;
/* -------------------------------------------------------------------------- */
/* -------------------------------------------------------------------------- */
// Output Container
/* -------------------------------------------------------------------------- */
class OutputContainer : public AutoDispatch::ArgumentAny {
public:
OutputContainer() : component(nullptr){};
OutputContainer(Component &component, const std::string &name)
: component(&component), name(name){};
OutputContainer(OutputContainer &&other) = default;
OutputContainer(const OutputContainer &other) = default;
inline OutputContainer &operator=(OutputContainer &&arg) = default;
inline OutputContainer &operator=(OutputContainer &arg) = default;
template <typename T = LMObject &> decltype(auto) get() {
return AutoDispatch::ArgumentAny::get<T>();
}
template <typename T = const LMObject &> decltype(auto) get() const {
return AutoDispatch::ArgumentAny::get<T>();
}
using AutoDispatch::ArgumentAny::is_type;
inline LMObject *operator->() { return &this->get(); }
inline LMObject &operator*() { return this->get(); }
inline const LMObject *operator->() const { return &this->get(); }
inline const LMObject &operator*() const { return this->get(); }
OutputContainer &operator=(Component &v);
template <typename T> inline OutputContainer &operator=(T &&v);
template <typename type, typename... T>
decltype(auto) alloc(T &&... construction_parameters);
friend class InputContainer;
UInt getRelease() const;
UInt evalRelease() const;
protected:
Component *component;
std::string name;
};
/* --------------------------------------------------------------------- */
// InputContainer
/* --------------------------------------------------------------------- */
class InputContainer {
public:
inline InputContainer() = default;
inline InputContainer(InputContainer &&v) = default;
inline InputContainer(const InputContainer &v) = default;
inline InputContainer &operator=(InputContainer &&v) = default;
InputContainer &operator=(OutputContainer &v);
InputContainer &operator=(OutputContainer &&v);
template <typename T> inline InputContainer &operator=(T &&v);
inline bool has_value() const { return output_reference.has_value(); }
UInt getRelease() const;
UInt evalRelease() const;
OutputContainer &get() const;
OutputContainer &eval() const;
template <typename T> inline decltype(auto) get();
template <typename T> inline decltype(auto) get() const;
protected:
private:
std::any output_reference;
};
struct InputConnection {
inline InputConnection(const std::string name) : name(name) {}
template <typename T> inline InputConnection &operator=(T &&t) {
val = std::forward<T>(t);
return *this;
}
std::string name;
OutputContainer val;
};
inline InputConnection operator"" _input(const char *name, size_t) {
return InputConnection(name);
}
/* --------------------------------------------------------------------- */
// Component
/* --------------------------------------------------------------------- */
class Component : public virtual LMObject,
public std::enable_shared_from_this<Component> {
public:
Component();
virtual ~Component(){};
////////////////////////////////////////////////////////////////
// meta-data of component
////////////////////////////////////////////////////////////////
public:
template <typename T = Real> void setCommGroup(CommGroup &group);
void printself(std::ostream &os) const override;
friend UInt _parse(Component &comp, std::stringstream &line, UInt);
friend class OutputContainer;
friend class InputContainer;
//! increment the release
void changeRelease() override;
protected:
struct UnconnectedInput : public std::runtime_error {
using std::runtime_error::runtime_error;
};
struct NotInCommGroup : public std::runtime_error {
using std::runtime_error::runtime_error;
};
//! evaluate all the inputs
void evalInputs();
//! acquire the context fom all the inputs
void acquireInputsContext();
//! returns true if the dependencies are recent => need recompute
bool evalDependencies();
//! propagate the context to all the outputs
void propagateContextToOutputs();
//! evaluate the current release (consult all chain of inputs)
UInt evalRelease();
////////////////////////////////////////////////////////////////
// input management
////////////////////////////////////////////////////////////////
public:
template <typename T> void connect(const std::string &input, T &&arg);
void connect(const std::string &input, Component &comp,
const std::string &output = "");
protected:
inline const auto &getInputs() const { return inputs; }
void clear_inputs() { inputs.clear(); }
OutputContainer &getInput(const std::string &requested_input = "");
InputContainer &createInput(const std::string &input);
private:
InputContainer &getInternalInput(const std::string &requested_input = "");
////////////////////////////////////////////////////////////////
// output management
////////////////////////////////////////////////////////////////
public:
template <typename T = Real>
inline decltype(auto) evalArrayOutput(const std::string &output_name = "");
template <typename T>
inline decltype(auto) evalOutput(const std::string &output_name = "");
OutputContainer &evalOutput(const std::string &output_name = "");
const std::map<std::string, OutputContainer> &evalOutputs();
protected:
const std::map<std::string, OutputContainer> &getOutputs();
template <typename T = Real>
ContainerArray<T> &getOutputAsArray(const std::string &output_name = "");
OutputContainer &createOutput(const std::string &output);
template <typename T>
inline decltype(auto) getOutput(const std::string &output_name = "");
OutputContainer &getOutput(const std::string &output_name = "");
template <typename Names> void createArrayOutputs(Names &&output_names);
template <typename T = Real> void createArrayOutput(const std::string &name);
template <typename Cont, typename... T>
auto &allocOutput(const std::string &output_name,
T &&... construction_parameters);
void removeInput(const std::string &input);
void removeOutput(const std::string &output);
////////////////////////////////////////////////////////////////
// compute management
////////////////////////////////////////////////////////////////
public:
virtual void compute_make_call() = 0;
virtual void compute(bool allow_unconnected_failure = false);
template <typename T, typename... Ts>
std::enable_if_t<std::is_same_v<std::decay_t<T>, InputConnection>>
compute(T &&arg, Ts &&... args);
template <typename T>
std::enable_if_t<not std::is_same_v<std::decay_t<T>, InputConnection>>
compute(T &&arg);
private:
template <typename ContMap>
decltype(auto) getContainer(const std::string &name, ContMap &cont);
////////////////////////////////////////////////////////////////
// array output management
////////////////////////////////////////////////////////////////
public:
void clear();
UInt size(const std::string &name = "");
private:
template <typename F>
inline void applyArrayOutput(F &&f, const std::string &name = "");
protected:
std::map<std::string, InputContainer> inputs;
std::map<std::string, OutputContainer> outputs;
std::string default_output = "";
bool calculated_once;
};
/* --------------------------------------------------------------------- */
template <typename Output, typename Component>
class SingleOutputComponent : public Component {
public:
using Component::Component;
SingleOutputComponent(const LMID &name) : LMObject(name), Component(name) {}
operator Output &() {
return this->getOutputs().begin()->second.get().template cast<Output>();
}
auto begin() { return (*this)->begin(); }
auto end() { return (*this)->end(); }
Output *operator->() { return &static_cast<Output &>(*this); }
Output &operator*() { return *this; }
};
template <typename T> struct casted_component {
template <typename CastT> using cast = SingleOutputComponent<CastT, T>;
};
/* --------------------------------------------------------------------- */
__END_LIBMULTISCALE__
/* --------------------------------------------------------------------- */
#include "component_libmultiscale_inline_impl.hh"
#include "possible_types.hh"
/* --------------------------------------------------------------------- */
#endif /* __LIBMULTISCALE_COMPONENT_LIBMULTISCALE_HH__ */

Event Timeline