22 #ifndef _aspect_plugins_h
23 #define _aspect_plugins_h
31 #include <boost/core/demangle.hpp>
40 #include <type_traits>
47 template <
int dim>
class SimulatorAccess;
69 template <
typename TestType,
typename PluginType,
70 typename =
typename std::enable_if_t<std::is_base_of<PluginType,TestType>::value>>
75 return (
dynamic_cast<const TestType *
> (&
object) !=
nullptr);
95 template <
typename TestType,
typename PluginType,
96 typename =
typename std::enable_if_t<std::is_base_of<PluginType,TestType>::value>>
102 ExcMessage(
"You have requested to convert a plugin of type <"
103 + boost::core::demangle(
typeid(PluginType).name())
105 + boost::core::demangle(
typeid(TestType).name()) +
106 ">, but this cast cannot be performed."));
111 return *
dynamic_cast<TestType *
> (&object);
210 void save (std::map<std::string, std::string> &status_strings)
const;
224 void load (
const std::map<std::string, std::string> &status_strings);
247 template <
typename InterfaceType>
272 template <
typename PluginType,
273 typename =
typename std::enable_if_t<std::is_base_of<InterfaceType,PluginType>::value>>
291 template <
typename PluginType,
292 typename =
typename std::enable_if_t<std::is_base_of<InterfaceType,PluginType>::value>>
301 const std::list<std::unique_ptr<InterfaceType>> &
310 const std::vector<std::string> &
317 template <
class Archive>
319 const unsigned int version)
const;
333 template <
class Archive>
335 const unsigned int version);
345 BOOST_SERIALIZATION_SPLIT_MEMBER()
363 template <typename InterfaceType>
368 #ifdef DEAL_II_HAVE_CXX17
369 if (std::uncaught_exceptions() == 0)
371 if (std::uncaught_exception() ==
false)
379 template <
typename InterfaceType>
396 catch (std::exception &exc)
398 std::cerr << std::endl << std::endl
399 <<
"----------------------------------------------------"
401 std::cerr <<
"Exception on MPI process <"
402 << ::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)
403 <<
"> while running plugin <"
405 <<
">: " << std::endl
406 << exc.what() << std::endl
407 <<
"Aborting!" << std::endl
408 <<
"----------------------------------------------------"
412 MPI_Abort (MPI_COMM_WORLD, 1);
416 std::cerr << std::endl << std::endl
417 <<
"----------------------------------------------------"
419 std::cerr <<
"Exception on MPI process <"
420 << ::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD)
421 <<
"> while running plugin <"
423 <<
">: " << std::endl;
424 std::cerr <<
"Unknown exception!" << std::endl
425 <<
"Aborting!" << std::endl
426 <<
"----------------------------------------------------"
430 MPI_Abort (MPI_COMM_WORLD, 1);
437 template <
typename InterfaceType>
438 template <
class Archive>
440 const unsigned int)
const
444 std::map<std::string,std::string> saved_text;
446 p->save (saved_text);
452 template <
typename InterfaceType>
453 template <
class Archive>
461 std::map<std::string,std::string> saved_text;
465 p->load (saved_text);
470 template <
typename InterfaceType>
471 template <
typename PluginType,
typename>
477 if (Plugins::plugin_type_matches<PluginType>(*p))
483 template <
typename InterfaceType>
484 template <
typename PluginType,
typename>
489 AssertThrow(has_matching_active_plugin<PluginType> (),
490 ExcMessage(
"You asked the object managing a collection of plugins for a "
491 "plugin object of type <" + boost::core::demangle(
typeid(PluginType).name()) +
"> "
492 "that could not be found in the current model. You need to "
493 "activate this plugin in the input file for it to be "
497 if (Plugins::plugin_type_matches<PluginType>(*p))
498 return Plugins::get_plugin_as_type<PluginType>(*p);
501 return Plugins::get_plugin_as_type<PluginType>(**(
plugin_objects.begin()));
506 template <
typename InterfaceType>
507 const std::list<std::unique_ptr<InterfaceType>> &
515 template <
typename InterfaceType>
516 const std::vector<std::string> &
542 template <
typename InterfaceClass,
554 std::unique_ptr<InterfaceClass> ( *)()),
556 const char *description)
558 register_function (name,
571 return std::make_unique<ModelClass>();
580 template <
typename InterfaceClass>
595 = std::tuple<std::string,
598 std::unique_ptr<InterfaceClass>( *) ()>;
625 void register_plugin (
const std::string &name,
626 const std::string &description,
628 std::unique_ptr<InterfaceClass> (*factory_function) ());
638 std::string get_pattern_of_names ();
648 std::string get_description_string ();
666 std::unique_ptr<InterfaceClass>
667 create_plugin (
const std::string &name,
668 const std::string &documentation);
681 std::unique_ptr<InterfaceClass>
682 create_plugin (
const std::string &name,
683 const std::string &documentation,
710 std::ostream &output_stream,
711 const std::string &attachment_point =
"Simulator");
718 <<
"Can't create a plugin of name <" << arg1
719 <<
"> because such a plugin hasn't been declared.");
725 template <
typename InterfaceClass>
731 if (plugins !=
nullptr)
738 template <
typename InterfaceClass>
742 const std::string &description,
744 std::unique_ptr<InterfaceClass> (*factory_function) ())
748 if (plugins ==
nullptr)
749 plugins =
new std::list<PluginInfo>();
754 for (
const auto &p : *plugins)
756 Assert (std::get<0>(p) != name,
757 ExcMessage (
"A plugin with name <" + name +
"> has "
758 "already been registered!"));
764 plugins->emplace_back (name,
766 declare_parameters_function,
772 template <
typename InterfaceClass>
777 Assert (plugins !=
nullptr,
782 std::set<std::string> names;
783 for (
typename std::list<PluginInfo>::const_iterator
784 p = plugins->begin();
785 p != plugins->end(); ++p)
786 names.insert (std::get<0>(*p));
789 std::string pattern_of_names;
790 for (
const auto &name : names)
792 if (pattern_of_names.size() > 0)
793 pattern_of_names +=
"|";
794 pattern_of_names += name;
797 return pattern_of_names;
802 template <
typename InterfaceClass>
807 std::string description;
811 std::map<std::string,std::string> names_and_descriptions;
812 for (
typename std::list<PluginInfo>::const_iterator
813 p = plugins->begin();
814 p != plugins->end(); ++p)
815 names_and_descriptions[std::get<0>(*p)] = std::get<1>(*p);
818 std::map<std::string,std::string>::const_iterator
819 p = names_and_descriptions.begin();
826 description += p->first;
827 description +=
"': ";
828 description += p->second;
835 if (p != names_and_descriptions.end())
836 description +=
"\n\n";
847 template <
typename InterfaceClass>
852 Assert (plugins !=
nullptr,
853 ExcMessage (
"No postprocessors registered!?"));
855 for (
typename std::list<PluginInfo>::const_iterator
856 p = plugins->begin();
857 p != plugins->end(); ++p)
858 (std::get<2>(*p))(prm);
863 template <
typename InterfaceClass>
864 std::unique_ptr<InterfaceClass>
867 const std::string &documentation)
870 Assert (plugins !=
nullptr,
871 ExcMessage (
"No postprocessors registered!?"));
873 ExcMessage(std::string(
"A plugin must have a name!\n\n"
874 "This function was asked to create a plugin but no name for the "
875 "plugin was provided. This may be due to the fact that you did not "
876 "explicitly specify a name for this plugin in your input file and "
877 "ASPECT does not provide a default for this kind of plugin, for "
878 "example because no generally useful plugin exists. An example "
879 "is that there is no default geometry: You need to explicitly "
880 "provide one in the input file, and it seems like you have not "
882 "To find out which kind of plugin this function tries to create, "
883 "take a look at the backtrace of this error message.\n\n"
884 "The place that called this function also provided as "
885 "additional information this:\n\n"
887 + documentation +
">"));
889 for (
typename std::list<PluginInfo>::const_iterator p = plugins->begin();
890 p != plugins->end(); ++p)
891 if (std::get<0>(*p) == name)
893 std::unique_ptr<InterfaceClass> i = std::get<3>(*p)();
903 template <
typename InterfaceClass>
904 std::unique_ptr<InterfaceClass>
907 const std::string &documentation,
910 std::unique_ptr<InterfaceClass> i = create_plugin(name, documentation);
911 i->parse_parameters (prm);
917 template <
typename InterfaceClass>
921 std::ostream &output_stream,
922 const std::string &attachment_point)
930 output_stream << std::string(
typeid(InterfaceClass).name())
932 << plugin_system_name
933 <<
"\", height=.8,width=.8,shape=\"rect\",fillcolor=\"lightgreen\"]"
945 std::map<std::string, typename std::list<PluginInfo>::const_iterator>
947 for (
typename std::list<PluginInfo>::const_iterator p = plugins->begin();
948 p != plugins->end(); ++p)
949 plugin_map[std::get<0>(*p)] = p;
952 for (
typename std::map<std::string,
typename std::list<PluginInfo>::const_iterator>::
const_iterator
953 p = plugin_map.begin();
954 p != plugin_map.end(); ++p)
960 const std::vector<std::string> plugin_label_parts
961 = ::Utilities::break_text_into_lines(p->first, 15);
963 std::string plugin_name = plugin_label_parts[0];
964 for (
unsigned int i=1; i<plugin_label_parts.size(); ++i)
965 plugin_name +=
"\\n" + plugin_label_parts[i];
970 std::unique_ptr<InterfaceClass> instance (create_plugin (p->first,
""));
971 const std::string node_name =
typeid(*instance).name();
974 output_stream << node_name
977 <<
"\", height=.8,width=.8,shape=\"circle\",fillcolor=\"lightblue\"];"
982 output_stream << node_name
984 << std::string(
typeid(InterfaceClass).name())
985 <<
" [len=3, weight=50]"
995 output_stream <<
"SimulatorAccess"
998 <<
" [style=\"dotted\", arrowhead=\"empty\", constraint=false, color=\"gray\", len=20, weight=0.1];"
1005 output_stream << std::string(
typeid(InterfaceClass).name())
1008 <<
" [len=15, weight=50]"
1014 output_stream << std::endl;
1020 template <
typename InterfaceClass>
* * const_iterator()=default
virtual void initialize()
virtual ~InterfaceBase()=default
static void declare_parameters(ParameterHandler &prm)
virtual void load(const std::map< std::string, std::string > &status_strings)
virtual void parse_parameters(ParameterHandler &prm)
virtual void save(std::map< std::string, std::string > &status_strings) const
void save(Archive &ar, const unsigned int version) const
void load(Archive &ar, const unsigned int version)
const PluginType & get_matching_active_plugin() const
bool has_matching_active_plugin() const
const std::vector< std::string > & get_active_plugin_names() const
const std::list< std::unique_ptr< InterfaceType > > & get_active_plugins() const
virtual void load(const std::map< std::string, std::string > &status_strings)
std::vector< std::string > plugin_names
virtual void save(std::map< std::string, std::string > &status_strings) const
std::list< std::unique_ptr< InterfaceType > > plugin_objects
void declare_parameters(ParameterHandler &prm)
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
void write_plugin_graph(std::ostream &output_stream)
TestType & get_plugin_as_type(PluginType &object)
bool plugin_type_matches(const PluginType &object)
std::tuple< std::string, std::string, void(*)(ParameterHandler &), std::unique_ptr< InterfaceClass >(*)()> PluginInfo
DeclException1(ExcUnknownPlugin, std::string,<< "Can't create a plugin of name <"<< arg1<< "> because such a plugin hasn't been declared.")
static std::list< PluginInfo > * plugins
RegisterHelper(void(*register_function)(const std::string &, const std::string &, void(*)(ParameterHandler &), std::unique_ptr< InterfaceClass >(*)()), const char *name, const char *description)
static std::unique_ptr< InterfaceClass > factory()