https://mooseframework.inl.gov
Loading...
Searching...
No Matches
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{
27public:
32
33#ifdef MOOSE_KOKKOS_ENABLED
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, typename NameFunc>
70 const std::string & header,
71 NameFunc && name_func);
72
73 template <typename T, typename T2>
74 static void cyclicDependencyError(CyclicDependencyException<T2> & e, const std::string & header);
75};
76
77template <typename T>
78void
79DependencyResolverInterface::sort(typename std::vector<T> & vector)
80{
81 sortDFS(vector);
82}
83
84template <typename T>
85void
86DependencyResolverInterface::sortDFS(typename std::vector<T> & vector)
87{
88 if (vector.size() <= 1)
89 return;
90
95
96 // Map of suppliers: what is supplied -> by what object
97 std::multimap<std::string, T> suppliers_map;
98 for (auto & v : vector)
99 {
100 // Whether or not this object supplies something, we will always
101 // add it as a node because we want to make sure that it gets returned
102 graph.addNode(v);
103
104 for (const auto & supplied_item : v->getSuppliedItems())
105 suppliers_map.emplace(supplied_item, v);
106 }
107
108 // build the dependency graph
109 for (auto & v : vector)
110 for (const auto & requested_item : v->getRequestedItems())
111 {
112 const auto & [begin_it, end_it] = suppliers_map.equal_range(requested_item);
113 for (const auto & [supplier_name, supplier_object] : as_range(begin_it, end_it))
114 {
115 libmesh_ignore(supplier_name);
116
117 // We allow an object to have a circular dependency within itself; e.g. we choose to
118 // trust a developer knows what they are doing within a single object
119 if (supplier_object != v)
120 graph.addEdge(supplier_object, v);
121 }
122 }
123
124 const auto & sorted = graph.dfs();
125
126 // The set here gets unique objects, as it's valid to pass in duplicates
127 mooseAssert(sorted.size() == std::set<T>(vector.begin(), vector.end()).size(), "Size mismatch");
128
129 vector = sorted;
130}
131
132template <typename T, typename T2, typename NameFunc>
133void
135 const std::string & header,
136 NameFunc && name_func)
137{
138 std::ostringstream oss;
139
140 oss << header << ":\n";
141 const auto cycle = e.getCyclicDependencies();
142 std::vector<std::string> names(cycle.size());
143 for (const auto i : index_range(cycle))
144 names[i] = name_func(cycle[i]);
145 oss << MooseUtils::join(names, " <- ");
146 mooseError(oss.str());
147}
148
149template <typename T, typename T2>
150void
152 const std::string & header)
153{
154 cyclicDependencyError<T>(e, header, [](const auto & obj) { return static_cast<T>(obj)->name(); });
155}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
const std::vector< T > & getCyclicDependencies() const
Interface for sorting dependent vectors of objects.
static void sort(typename std::vector< T > &vector)
Given a vector, sort using the getRequested/SuppliedItems sets.
DependencyResolverInterface(const DependencyResolverInterface &, const Moose::Kokkos::FunctorCopy &)
Special constructor used for Kokkos functor copy during parallel dispatch.
virtual const std::set< std::string > & getRequestedItems()=0
Return a set containing the names of items requested by the object.
static void sortDFS(typename std::vector< T > &vector)
Given a vector, sort using the depth-first search.
static void cyclicDependencyError(CyclicDependencyException< T2 > &e, const std::string &header, NameFunc &&name_func)
A helper method for cyclic errors.
virtual const std::set< std::string > & getSuppliedItems()=0
Return a set containing the names of items owned by the object.
Class that represents the dependecy as a graph.
void addNode(const T &a)
Add a node 'a' to the graph.
const std::vector< T > & dfs()
Do depth-first search from root nodes to obtain order in which graph nodes should be "executed".
void addEdge(const T &a, const T &b)
Add an edge between nodes 'a' and 'b'.