v0.16.0
Loading...
Searching...
No Matches
PipelineGraph.cpp
Go to the documentation of this file.
1/**
2 * @file PipelineGraph.cpp
3 * @brief Plot pipeline graph
4 * @version 0.1
5 * @date 2025-12-26
6 *
7 * @copyright Copyright (c) 2025
8 *
9 */
10
11#include <MoFEM.hpp>
12
13#include <boost/graph/adjacency_list.hpp>
14#include <boost/graph/graphviz.hpp>
15#include <tuple>
16
17struct VertexData {
18 std::string label;
19 std::string shape;
20 std::string style;
21 std::string color;
22};
23
24using Graph =
25 boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
26 boost::property<boost::vertex_name_t, VertexData>,
27 boost::property<boost::edge_name_t, std::string>>;
28
29namespace MoFEM {
30
32using VertexDescriptor = boost::graph_traits<Graph>::vertex_descriptor;
33
35plot_pipeline_graph_impl(const boost::ptr_deque<UserDataOperator> &pip,
36 std::string pip_name, boost::shared_ptr<Graph> g_ptr,
37 VertexDescriptor root_vertex) {
38
39 auto get_fe_name = [](const auto &fe) {
40 std::ostringstream ss;
41 ss << "FE:" << boost::typeindex::type_id_runtime(fe).pretty_name();
42 return ss;
43 };
44
45 auto get_name_short = [](const auto &op) {
46 std::ostringstream ss;
47 ss << "OP:" << boost::typeindex::type_id_runtime(op).pretty_name();
48 return ss;
49 };
50
51 auto get_name_long = [get_name_short](const auto &op) {
52 auto ss = get_name_short(op);
53 switch (op.getOpType()) {
55 ss << ":r:" << op.rowFieldName;
56 break;
58 ss << ":c:" << op.colFieldName;
59 break;
61 ss << ":r:" << op.rowFieldName << ":c:" << op.colFieldName;
62 break;
64 ss << ":s:" << FieldSpaceNames[op.sPace];
65 break;
66 default:
67 CHK_THROW_MESSAGE(MOFEM_DATA_INCONSISTENCY, "Impossible operator type");
68 };
69 return ss;
70 };
71
72 auto &g = *g_ptr;
73
74 auto vname = get(boost::vertex_name, g);
75 auto ename = get(boost::edge_name, g);
76
77
78 std::function<VertexDescriptor(VertexDescriptor &,
79 const boost::ptr_deque<UserDataOperator> &)>
80 add_tree = [&](VertexDescriptor &root_vertex,
81 const boost::ptr_deque<UserDataOperator> &pip) {
82 auto prev_vertex = root_vertex;
83
84 for (auto &op : pip) {
85
86 auto op_vertex = boost::add_vertex(g);
87 vname[op_vertex] = {get_name_long(op).str(), "box", "solid",
88 "black"};
89
90 auto fe_weak_ptr = op.getSubPipelinePtr();
91
92 if (auto fe = fe_weak_ptr.lock()) {
93
94 auto fe_vertex = boost::add_vertex(g);
95 vname[fe_vertex] = {get_fe_name(*fe).str(), "box3d", "filled", "lightgrey"};
96
97 auto last_vertex = add_tree(fe_vertex, fe->getOpPtrVector());
98
99 // add edges back and from loop
100 auto [e_loop_start, ok1_start] =
101 add_edge(op_vertex, fe_vertex, g);
102 ename[e_loop_start] = "go to loop";
103 auto [e_loop_end, ok1_end] = add_edge(last_vertex, op_vertex, g);
104 ename[e_loop_end] = "back from loop";
105 }
106
107 std::ignore = add_edge(prev_vertex, op_vertex, g);
108
109 prev_vertex = op_vertex;
110 }
111
112 return prev_vertex;
113 };
114
115 auto pip_vertex = boost::add_vertex(g);
116 vname[pip_vertex] = {pip_name, "box3d", "filled", "lightgrey"};
117 auto [e_root_pip, ok] = add_edge(root_vertex, pip_vertex, g);
118 ename[e_root_pip] = "pipeline";
119
120 auto last_vertex = add_tree(pip_vertex, pip);
121
122 return last_vertex;
123}
124
125static void write_graphviz_impl(std::string file_name,
126 boost::shared_ptr<Graph> g_ptr) {
127
128 auto &g = *g_ptr;
129 std::ofstream ofs(file_name);
130
131 // Use a custom vertex writer
132 auto vertex_writer = [&g](std::ostream& out, const VertexDescriptor& v) {
133 auto vdata = get(boost::vertex_name, g)[v];
134 out << "[label=\"" << vdata.label << "\", shape=" << vdata.shape
135 << ", style=" << vdata.style << ", color=" << vdata.color << "]";
136 };
137
138 // Use the existing edge name property
139 auto edge_writer = boost::make_label_writer(get(boost::edge_name, g));
140
141 boost::write_graphviz(ofs, g, vertex_writer, edge_writer);
142
143
144}
145
147 std::string file_name, std::string pip_name,
148 const boost::ptr_deque<UserDataOperator> &pip) {
150 boost::shared_ptr<Graph> g_ptr(new Graph());
151 auto vname = get(boost::vertex_name, *g_ptr);
152 auto root_vertex = boost::add_vertex(*g_ptr);
153 vname[root_vertex] = {"Finite Element Pipeline Graph", "ellipse", "solid",
154 "black"};
155 plot_pipeline_graph_impl(pip, pip_name, g_ptr, root_vertex);
156 write_graphviz_impl(file_name, g_ptr);
158};
159
162 VertexDescriptor start_vertex,
163 boost::shared_ptr<Graph> g_ptr) {
164 boost::ptr_deque<UserDataOperator> null_pip;
165 auto vname = get(boost::vertex_name, *g_ptr);
166
167 auto get_fe_name = [](const auto &fe) {
168 std::ostringstream ss;
169 ss << "FE:" << boost::typeindex::type_id_runtime(fe).pretty_name();
170 return ss;
171 };
172
173 auto pre_vertex = boost::add_vertex(*g_ptr);
174 vname[pre_vertex] = {"Stage PreProcess", "ellipse", "solid", "black"};
175 std::ignore = add_edge(start_vertex, pre_vertex, *g_ptr);
176
177 auto prev_vertex = pre_vertex;
178 for (auto &bit : pre) {
179 auto name = "BM:" + get_fe_name(bit.get()).str();
180 prev_vertex = plot_pipeline_graph_impl(null_pip, name, g_ptr, prev_vertex);
181 }
182
183 auto pro_vertex = boost::add_vertex(*g_ptr);
184 vname[pro_vertex] = {"Stage Processs", "ellipse", "solid", "black"};
185 std::ignore = add_edge(prev_vertex, pro_vertex, *g_ptr);
186
187 prev_vertex = pro_vertex;
188 for (auto &lit : op) {
189 auto name = lit.first + ":" + get_fe_name(*(lit.second)).str();
190 if (auto fe_ptr =
191 boost::dynamic_pointer_cast<ForcesAndSourcesCore>(lit.second)) {
192 prev_vertex = plot_pipeline_graph_impl(fe_ptr->getOpPtrVector(), name, g_ptr,
193 prev_vertex);
194 } else {
195 prev_vertex = plot_pipeline_graph_impl(null_pip, name, g_ptr, prev_vertex);
196 }
197 }
198
199 auto post_vertex = boost::add_vertex(*g_ptr);
200 vname[post_vertex] = {"Stage PostProcesss", "ellipse", "solid", "black"};
201 std::ignore = add_edge(prev_vertex, post_vertex, *g_ptr);
202
203 prev_vertex = post_vertex;
204 for (auto &bit : post) {
205 auto name = "BM:" + get_fe_name(bit.get()).str();
206 prev_vertex = plot_pipeline_graph_impl(null_pip, name, g_ptr, prev_vertex);
207 }
208}
209
212 std::string file_name) {
214 boost::shared_ptr<Graph> g_ptr(new Graph());
215 auto &g = *g_ptr;
216
217 auto vname = get(boost::vertex_name, g);
218
219 auto root_vertex = boost::add_vertex(g);
220 vname[root_vertex] = {"KSP Graph", "ellipse", "solid", "black"};
221
222 auto lhs_vertex = boost::add_vertex(g);
223 vname[lhs_vertex] = {"Lhs", "box3d", "filled", "lightgrey"};
224 add_edge(root_vertex, lhs_vertex, g);
226 ksp_ctx->getPostProcSetOperators(), lhs_vertex, g_ptr);
227
228 auto rhs_vertex = boost::add_vertex(g);
229 vname[rhs_vertex] = {"Rhs", "box3d", "filled", "lightgrey"};
230 add_edge(root_vertex, rhs_vertex, g);
231 add_stages(ksp_ctx->getPreProcComputeRhs(), ksp_ctx->getComputeRhs(),
232 ksp_ctx->getPostProcComputeRhs(), rhs_vertex, g_ptr);
233
234 write_graphviz_impl(file_name, g_ptr);
236}
237
240 std::string file_name) {
242 boost::shared_ptr<Graph> g_ptr(new Graph());
243 auto &g = *g_ptr;
244
245 auto vname = get(boost::vertex_name, g);
246
247 auto root_vertex = boost::add_vertex(g);
248 vname[root_vertex] = {"SNES Graph", "ellipse", "solid", "black"};
249
250 auto lhs_vertex = boost::add_vertex(g);
251 vname[lhs_vertex] = {"Lhs", "box3d", "filled", "lightgrey"};
252 add_edge(root_vertex, lhs_vertex, g);
253 add_stages(snes_ctx->getPreProcSetOperators(), snes_ctx->getSetOperators(),
254 snes_ctx->getPostProcSetOperators(), lhs_vertex, g_ptr);
255
256 auto rhs_vertex = boost::add_vertex(g);
257 vname[rhs_vertex] = {"Rhs", "box3d", "filled", "lightgrey"};
258 add_edge(root_vertex, rhs_vertex, g);
259 add_stages(snes_ctx->getPreProcComputeRhs(), snes_ctx->getComputeRhs(),
260 snes_ctx->getPostProcComputeRhs(), rhs_vertex, g_ptr);
261
262 auto load_vertex = boost::add_vertex(g);
263 vname[load_vertex] = {"LoadTangent", "box3d", "filled", "lightgrey"};
264 add_edge(root_vertex, load_vertex, g);
265 add_stages(snes_ctx->getPreProcLoadTangent(), snes_ctx->getLoadTangent(),
266 snes_ctx->getPostProcLoadTangent(), load_vertex, g_ptr);
267
268 write_graphviz_impl(file_name, g_ptr);
269
271}
272
275 std::string file_name) {
277 boost::shared_ptr<Graph> g_ptr(new Graph());
278 auto &g = *g_ptr;
279
280 auto vname = get(boost::vertex_name, g);
281
282 auto root_vertex = boost::add_vertex(g);
283 vname[root_vertex] = {"TS Graph", "ellipse", "solid", "black"};
284
285 auto ifunction_vertex = boost::add_vertex(g);
286 vname[ifunction_vertex] = {"IFunction", "box3d", "filled", "lightgrey"};
287 add_edge(root_vertex, ifunction_vertex, g);
289 ts_ctx->getPostProcessIFunction(), ifunction_vertex, g_ptr);
290
291 auto rhsfunction_vertex = boost::add_vertex(g);
292 vname[rhsfunction_vertex] = {"RHSFunction", "box3d", "filled", "lightgrey"};
293 add_edge(root_vertex, rhsfunction_vertex, g);
295 ts_ctx->getPostProcessRHSFunction(), rhsfunction_vertex, g_ptr);
296
297 auto ijjacobian_vertex = boost::add_vertex(g);
298 vname[ijjacobian_vertex] = {"IJacobian", "box3d", "filled", "lightgrey"};
299 add_edge(root_vertex, ijjacobian_vertex, g);
301 ts_ctx->getPostProcessIJacobian(), ijjacobian_vertex, g_ptr);
302
303 auto rhsjacobian_vertex = boost::add_vertex(g);
304 vname[rhsjacobian_vertex] = {"RHSJacobian", "box3d", "filled", "lightgrey"};
305 add_edge(root_vertex, rhsjacobian_vertex, g);
307 ts_ctx->getPostProcessRHSJacobian(), rhsjacobian_vertex, g_ptr);
308
309 auto monitor_vertex = boost::add_vertex(g);
310 vname[monitor_vertex] = {"Monitor", "box3d", "filled", "lightgrey"};
311 add_edge(root_vertex, monitor_vertex, g);
313 ts_ctx->getPostProcessMonitor(), monitor_vertex, g_ptr);
314
315 write_graphviz_impl(file_name, g_ptr);
317}
318
321 PipelineManager *pip_mng) {
323 boost::shared_ptr<Graph> g_ptr(new Graph());
324 auto vname = get(boost::vertex_name, *g_ptr);
325 auto root_vertex = boost::add_vertex(*g_ptr);
326 vname[root_vertex] = {"Pipeline Manager Graph", "ellipse", "solid", "black"};
327
328 // lhs
329 if (pip_mng->getDomainLhsFE())
331 "DomainLhsPipeline", g_ptr, root_vertex);
332 if (pip_mng->getBoundaryLhsFE())
334 "BoundaryLhsPipeline", g_ptr, root_vertex);
335 if (pip_mng->getSkeletonLhsFE())
337 "SkeletonLhsPipeline", g_ptr, root_vertex);
338
339 // rhs
340 if (pip_mng->getDomainRhsFE())
342 "DomainRhsPipeline", g_ptr, root_vertex);
343 if (pip_mng->getBoundaryRhsFE())
345 "BoundaryRhsPipeline", g_ptr, root_vertex);
346
347 if (pip_mng->getSkeletonRhsFE())
349 "SkeletonRhsPipeline", g_ptr, root_vertex);
350 // rhs explict
351 if (pip_mng->getDomainExplicitRhsFE())
353 "DomainRhsExplicitPipeline", g_ptr,
354 root_vertex);
355 if (pip_mng->getBoundaryExplicitRhsFE())
357 "BoundaryRhsExplicitPipeline", g_ptr,
358 root_vertex);
359 if (pip_mng->getSkeletonExplicitRhsFE())
361 "SkeletonRhsExplicitPipeline", g_ptr,
362 root_vertex);
363
364 // meshset
365 if (pip_mng->getMeshsetLhsFE())
367 "MeshsetLhsPipeline", g_ptr, root_vertex);
368 if (pip_mng->getMeshsetRhsFE())
370 "MeshsetRhsPipeline", g_ptr, root_vertex);
371 if (pip_mng->getMeshsetExplicitRhsFE())
373 "MeshsetRhsExplicitPipeline", g_ptr,
374 root_vertex);
375
376 write_graphviz_impl(file_name, g_ptr);
377
379}
380
382PipelineGraph::query_interface(boost::typeindex::type_index type_index,
383 UnknownInterface **iface) const {
384 *iface = const_cast<PipelineGraph *>(this);
385 return 0;
386}
387
389 : cOre(const_cast<Core &>(core)) {}
390
391} // namespace MoFEM
boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS, boost::property< boost::vertex_name_t, VertexData >, boost::property< boost::edge_name_t, std::string > > Graph
#define CHK_THROW_MESSAGE(err, msg)
Check and throw MoFEM exception.
static const char *const FieldSpaceNames[]
Definition definitions.h:92
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
Definition definitions.h:31
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
boost::ptr_deque< UserDataOperator > & getOpBoundaryExplicitRhsPipeline()
Get the Op Boundary Rhs Pipeline object for implicit-explicit G term.
boost::ptr_deque< UserDataOperator > & getOpDomainExplicitRhsPipeline()
Get the Op Domain Rhs Pipeline object for implicit-explicit G term.
boost::ptr_deque< UserDataOperator > & getOpSkeletonExplicitRhsPipeline()
Get the Op Skeleton Rhs Pipeline object for implicit-explicit G term.
boost::ptr_deque< UserDataOperator > & getOpDomainLhsPipeline()
Get the Op Domain Lhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpSkeletonLhsPipeline()
Get the Op Skeleton Lhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpBoundaryLhsPipeline()
Get the Op Boundary Lhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpBoundaryRhsPipeline()
Get the Op Boundary Rhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpSkeletonRhsPipeline()
Get the Op Skeleton Rhs Pipeline object.
boost::ptr_deque< UserDataOperator > & getOpDomainRhsPipeline()
Get the Op Domain Rhs Pipeline object.
auto bit
set bit
const double v
phase velocity of light in medium (cm/ns)
MoFEM::TsCtx * ts_ctx
PetscErrorCode MoFEMErrorCode
MoFEM/PETSc error code.
implementation of Data Operators for Forces and Sources
Definition Common.hpp:10
static void write_graphviz_impl(std::string file_name, boost::shared_ptr< Graph > g_ptr)
boost::graph_traits< Graph >::vertex_descriptor VertexDescriptor
static VertexDescriptor plot_pipeline_graph_impl(const boost::ptr_deque< UserDataOperator > &pip, std::string pip_name, boost::shared_ptr< Graph > g_ptr, VertexDescriptor root_vertex)
std::deque< BasicMethodPtr > BasicMethodsSequence
Definition AuxPETSc.hpp:58
std::deque< PairNameFEMethodPtr > FEMethodsSequence
Definition AuxPETSc.hpp:57
static void add_stages(BasicMethodsSequence &pre, FEMethodsSequence &op, BasicMethodsSequence &post, VertexDescriptor start_vertex, boost::shared_ptr< Graph > g_ptr)
constexpr double g
Core (interface) class.
Definition Core.hpp:83
@ OPCOL
operator doWork function is executed on FE columns
@ OPROW
operator doWork function is executed on FE rows
@ OPROWCOL
operator doWork is executed on FE rows &columns
@ OPSPACE
operator do Work is execute on space data
Interface for linear (KSP) solver.
Definition KspCtx.hpp:14
BasicMethodsSequence & getPostProcComputeRhs()
Definition KspCtx.cpp:114
BasicMethodsSequence & getPreProcComputeRhs()
Definition KspCtx.cpp:110
BasicMethodsSequence & getPreProcSetOperators()
Definition KspCtx.cpp:118
FEMethodsSequence & getSetOperators()
Definition KspCtx.cpp:102
FEMethodsSequence & getComputeRhs()
Definition KspCtx.cpp:106
BasicMethodsSequence & getPostProcSetOperators()
Definition KspCtx.cpp:122
static MoFEMErrorCode writeTSGraphGraphviz(TsCtx *ts_ctx, std::string file_name)
TS graph to Graphviz file.
static MoFEMErrorCode writeKSPGraphGraphviz(KspCtx *ksp_ctx, std::string filename)
KSP graph to Graphviz file.
static MoFEMErrorCode writeGraphGraphviz(std::string filename, std::string pip_name, const boost::ptr_deque< ForcesAndSourcesCore::UserDataOperator > &pip)
Pipeline graph to Graphviz file.
static MoFEMErrorCode writePiplineManagerGraphGraphviz(std::string filename, PipelineManager *pip_mng)
Write pipeline manager graph to Graphviz file.
static MoFEMErrorCode writeSNESGraphGraphviz(SnesCtx *snes_ctx, std::string file_name)
SNES graph to Graphviz file.
MoFEMErrorCode query_interface(boost::typeindex::type_index type_index, UnknownInterface **iface) const
Query interface for type-safe casting.
PipelineGraph(const MoFEM::Core &core)
PipelineManager interface.
boost::shared_ptr< FEMethod > & getDomainRhsFE()
Get domain right-hand side finite element.
boost::ptr_deque< UserDataOperator > & getOpMeshsetRhsPipeline()
Get the Op Meshset Rhs Pipeline object.
boost::shared_ptr< FEMethod > & getDomainLhsFE()
Get domain left-hand side finite element.
boost::ptr_deque< UserDataOperator > & getOpMeshsetExplicitRhsPipeline()
Get the Op Meshset Explicit Rhs Pipeline object.
boost::shared_ptr< FEMethod > & getSkeletonRhsFE()
Get skeleton right-hand side finite element.
boost::shared_ptr< FEMethod > & getMeshsetLhsFE()
Get meshset left-hand side finite element.
boost::shared_ptr< FEMethod > & getBoundaryLhsFE()
Get boundary left-hand side finite element.
boost::shared_ptr< FEMethod > & getSkeletonLhsFE()
Get skeleton left-hand side finite element.
boost::shared_ptr< FEMethod > & getMeshsetRhsFE()
Get meshset right-hand side finite element.
boost::shared_ptr< FEMethod > & getDomainExplicitRhsFE()
Get domain explicit right-hand side finite element.
boost::shared_ptr< FEMethod > & getBoundaryRhsFE()
Get boundary right-hand side finite element.
boost::ptr_deque< UserDataOperator > & getOpMeshsetLhsPipeline()
Get the Op Meshset Lhs Pipeline object.
boost::shared_ptr< FEMethod > & getSkeletonExplicitRhsFE()
Get skeleton explicit right-hand side finite element.
boost::shared_ptr< FEMethod > & getBoundaryExplicitRhsFE()
Get boundary explicit right-hand side finite element.
boost::shared_ptr< FEMethod > & getMeshsetExplicitRhsFE()
Get meshset explicit right-hand side finite element.
Interface for nonlinear (SNES) solver.
Definition SnesCtx.hpp:15
FEMethodsSequence & getSetOperators()
Definition SnesCtx.cpp:133
BasicMethodsSequence & getPreProcLoadTangent()
Get the BasicMethod sequence for preprocessing of FunctionFn.
Definition SnesCtx.cpp:161
BasicMethodsSequence & getPreProcSetOperators()
Definition SnesCtx.cpp:149
BasicMethodsSequence & getPostProcLoadTangent()
Get the BasicMethod sequence for postprocessing of FunctionFn.
Definition SnesCtx.cpp:165
BasicMethodsSequence & getPostProcComputeRhs()
Definition SnesCtx.cpp:145
BasicMethodsSequence & getPostProcSetOperators()
Definition SnesCtx.cpp:153
BasicMethodsSequence & getPreProcComputeRhs()
Definition SnesCtx.cpp:141
FEMethodsSequence & getLoadTangent()
Get the finite element pipeline for FunctionFn, that calculate tangent of function load for arc lengt...
Definition SnesCtx.cpp:157
FEMethodsSequence & getComputeRhs()
Definition SnesCtx.cpp:137
Interface for Time Stepping (TS) solver.
Definition TsCtx.hpp:17
BasicMethodsSequence & getPostProcessRHSFunction()
Get the postProcess to do RHSFunction object.
Definition TsCtx.hpp:182
BasicMethodsSequence & getPostProcessIJacobian()
Get the postProcess to do IJacobian object.
Definition TsCtx.hpp:132
FEMethodsSequence & getLoopsMonitor()
Get the loops to do Monitor object.
Definition TsCtx.hpp:102
BasicMethodsSequence & getPreProcessMonitor()
Get the preProcess to do Monitor object.
Definition TsCtx.hpp:141
BasicMethodsSequence & getPostProcessRHSJacobian()
Get the postProcess to do RHSJacobian object.
Definition TsCtx.hpp:164
BasicMethodsSequence & getPostProcessIFunction()
Get the postProcess to do IFunction object.
Definition TsCtx.hpp:116
BasicMethodsSequence & getPreProcessRHSFunction()
Get the preProcess to do RHSFunction object.
Definition TsCtx.hpp:173
FEMethodsSequence & getLoopsIFunction()
Get the loops to do IFunction object.
Definition TsCtx.hpp:63
FEMethodsSequence & getLoopsRHSJacobian()
Get the loops to do RHSJacobian object.
Definition TsCtx.hpp:93
BasicMethodsSequence & getPreProcessIFunction()
Get the preProcess to do IFunction object.
Definition TsCtx.hpp:109
FEMethodsSequence & getLoopsRHSFunction()
Get the loops to do RHSFunction object.
Definition TsCtx.hpp:73
FEMethodsSequence & getLoopsIJacobian()
Get the loops to do IJacobian object.
Definition TsCtx.hpp:83
BasicMethodsSequence & getPreProcessRHSJacobian()
Get the preProcess to do RHSJacobian object.
Definition TsCtx.hpp:155
BasicMethodsSequence & getPostProcessMonitor()
Get the postProcess to do Monitor object.
Definition TsCtx.hpp:148
BasicMethodsSequence & getPreProcessIJacobian()
Get the preProcess to do IJacobian object.
Definition TsCtx.hpp:125
base class for all interface classes
std::string shape
std::string color
std::string label
std::string style