https://mooseframework.inl.gov
DependencyResolverInterface.h
Go to the documentation of this file.
1 //* This file is part of the MOOSE framework
2 //* https://mooseframework.inl.gov
3 //*
4 //* All rights reserved, see COPYRIGHT for full restrictions
5 //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6 //*
7 //* Licensed under LGPL 2.1, please see LICENSE for details
8 //* https://www.gnu.org/licenses/lgpl-2.1.html
9 
10 #pragma once
11 
12 // STL includes
13 #include <string>
14 #include <set>
15 #include <iostream>
16 #include <algorithm>
17 
18 // MOOSE includes
19 #include "DependencyResolver.h"
20 #include "MooseUtils.h"
21 
26 {
27 public:
32 
33 #ifdef MOOSE_KOKKOS_ENABLED
34 
39  {
40  }
41 #endif
42 
46  virtual const std::set<std::string> & getRequestedItems() = 0;
47 
51  virtual const std::set<std::string> & getSuppliedItems() = 0;
52 
56  template <typename T>
57  static void sort(typename std::vector<T> & vector);
58 
62  template <typename T>
63  static void sortDFS(typename std::vector<T> & vector);
64 
68  template <typename T, typename T2>
69  static void cyclicDependencyError(CyclicDependencyException<T2> & e, const std::string & header);
70 };
71 
72 template <typename T>
73 void
74 DependencyResolverInterface::sort(typename std::vector<T> & vector)
75 {
76  sortDFS(vector);
77 }
78 
79 template <typename T>
80 void
81 DependencyResolverInterface::sortDFS(typename std::vector<T> & vector)
82 {
83  if (vector.size() <= 1)
84  return;
85 
90 
91  // Map of suppliers: what is supplied -> by what object
92  std::multimap<std::string, T> suppliers_map;
93  for (auto & v : vector)
94  {
95  // Whether or not this object supplies something, we will always
96  // add it as a node because we want to make sure that it gets returned
97  graph.addNode(v);
98 
99  for (const auto & supplied_item : v->getSuppliedItems())
100  suppliers_map.emplace(supplied_item, v);
101  }
102 
103  // build the dependency graph
104  for (auto & v : vector)
105  for (const auto & requested_item : v->getRequestedItems())
106  {
107  const auto & [begin_it, end_it] = suppliers_map.equal_range(requested_item);
108  for (const auto & [supplier_name, supplier_object] : as_range(begin_it, end_it))
109  {
110  libmesh_ignore(supplier_name);
111 
112  // We allow an object to have a circular dependency within itself; e.g. we choose to
113  // trust a developer knows what they are doing within a single object
114  if (supplier_object != v)
115  graph.addEdge(supplier_object, v);
116  }
117  }
118 
119  const auto & sorted = graph.dfs();
120 
121  // The set here gets unique objects, as it's valid to pass in duplicates
122  mooseAssert(sorted.size() == std::set<T>(vector.begin(), vector.end()).size(), "Size mismatch");
123 
124  vector = sorted;
125 }
126 
127 template <typename T, typename T2>
128 void
130  const std::string & header)
131 {
132  std::ostringstream oss;
133 
134  oss << header << ":\n";
135  const auto cycle = e.getCyclicDependencies();
136  std::vector<std::string> names(cycle.size());
137  for (const auto i : index_range(cycle))
138  names[i] = static_cast<T>(cycle[i])->name();
139  oss << MooseUtils::join(names, " <- ");
140  mooseError(oss.str());
141 }
std::string join(Iterator begin, Iterator end, const std::string &delimiter)
Python-like join function for strings over an iterator range.
Definition: MooseUtils.h:142
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:323
static void sortDFS(typename std::vector< T > &vector)
Given a vector, sort using the depth-first search.
virtual const std::set< std::string > & getRequestedItems()=0
Return a set containing the names of items requested by the object.
void addEdge(const T &a, const T &b)
Add an edge between nodes &#39;a&#39; and &#39;b&#39;.
void libmesh_ignore(const Args &...)
DependencyResolverInterface(const DependencyResolverInterface &, const Moose::Kokkos::FunctorCopy &)
Special constructor used for Kokkos functor copy during parallel dispatch.
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
virtual const std::set< std::string > & getSuppliedItems()=0
Return a set containing the names of items owned by the object.
static void sort(typename std::vector< T > &vector)
Given a vector, sort using the getRequested/SuppliedItems sets.
void addNode(const T &a)
Add a node &#39;a&#39; to the graph.
const std::vector< T > & getCyclicDependencies() const
Interface for sorting dependent vectors of objects.
const std::vector< T > & dfs()
Do depth-first search from root nodes to obtain order in which graph nodes should be "executed"...
static void cyclicDependencyError(CyclicDependencyException< T2 > &e, const std::string &header)
A helper method for cyclic errors.
Class that represents the dependecy as a graph.
auto index_range(const T &sizable)