Solver graph nodes#
A solver graph is a DAG of nodes connected by edges. Nodes read and write
edge data in _impl_evaluate_internal(). Edges carry typed values (fields,
scalars, indexes, …). Most nodes can be found under the shamrock::solvergraph namespace.
Nodes inherit
INode.edges can be wired with
set_edges()evaluation of the node from edges input and in-out is done using
evaluate().
Node layout#
// 1. declare inputs (X_RO) and outputs (X_RW)
#define NODE_EDGES(X_RO, X_RW) \
X_RO(shamrock::solvergraph::IDataEdge<T>, in) \
X_RW(shamrock::solvergraph::IDataEdge<T>, out)
// 2. Create the class and inherit from INode
class MyNode : public shamrock::solvergraph::INode {
public:
// 3. generate set_edges() / get_edges()
EXPAND_NODE_EDGES(NODE_EDGES)
// 4. evaluation logic
void _impl_evaluate_internal() override {
auto edges = get_edges();
// ... do stuff ...
}
// 5. labels for graph display and TeX output
std::string _impl_get_label() const override { return "MyNode"; }
std::string _impl_get_tex() const override { return ""; }
};
#undef NODE_EDGES
EXPAND_NODE_EDGES generates:
struct Edges—const T&for read-only edges,T&for read-write edgesset_edges(shared_ptr...)— wire beforeevaluate()get_edges()— typed access in_impl_evaluate_internal()
Edge macros#
Macro |
Role in |
|
|
|---|---|---|---|
|
required read-only input |
|
|
|
required read-write output |
|
|
List inputs first, outputs last.
Optional edges#
An optional input may be absent at wiring time for nodes having multiple evaluation modes.
To use optional edges use EXPAND_NODE_EDGES_OPTIONAL when NODE_EDGES
contains any X_*_OPTIONAL macro.
The following changes for those :
// Now we have to add X_RO_OPTIONAL, X_RW_OPTIONAL too
#define NODE_EDGES(X_RO, X_RW, X_RO_OPTIONAL, X_RW_OPTIONAL) \
X_RO_OPTIONAL(shamrock::solvergraph::IDataEdge<u32>, opt_a) \
X_RO_OPTIONAL(shamrock::solvergraph::IDataEdge<u32>, opt_b) \
X_RW(shamrock::solvergraph::IDataEdge<u32>, out)
class OptionalEdgeProbeNode : public shamrock::solvergraph::INode {
public:
// Use EXPAND_NODE_EDGES_OPTIONAL instead of EXPAND_NODE_EDGES
EXPAND_NODE_EDGES_OPTIONAL(NODE_EDGES)
void _impl_evaluate_internal() override {
auto edges = get_edges();
// optional inputs: edges.opt_a.has_value(), edges.opt_b.has_value()
// ...
}
std::string _impl_get_label() const override { return "OptionalEdgeProbe"; }
std::string _impl_get_tex() const override { return ""; }
};
#undef NODE_EDGES
Optional edge macros#
Macro |
|
|
|---|---|---|
|
|
|
|
|
|
Wiring#
Pass std::nullopt for absent optional inputs:
node.set_edges(std::nullopt, std::nullopt, out); // neither optional present
node.set_edges(a, std::nullopt, out); // only opt_a
node.set_edges(a, b, out); // both present
node.evaluate();
Absent optionals are stored as
INullOptEdge
placeholders so slot indices stay stable. get_ro_edge_optional returns
std::nullopt for those slots.