52Foam::wordList Foam::functionObjects::graphFunctionObject::defaultColours
69bool Foam::functionObjects::graphFunctionObject::getValue
75 const word&
object = objects_[objecti];
76 const word& entry = entries_[objecti];
84 auto& cols = objectToCol_[objecti];
87 for (
direction d = 0; d < pTraits<Type>::nComponents; ++d)
89 cols.push_back(valuei++);
90 values_.push_back(DynamicList<scalar>());
94 for (
direction d = 0; d < pTraits<Type>::nComponents; ++d)
100 v = (v < SMALL) ? 1 :
log10(v);
103 values_[cols[d]].push_back(v);
110Foam::label Foam::functionObjects::graphFunctionObject::setAxisProps
119 <<
"1 -- xmin:" << xmin <<
" xmax:" << xmax
120 <<
" xtick:" << xtick <<
endl;
127 const scalar
range = xmax - xmin;
128 const scalar eps = 0.01*
range;
131 if (
mag(xmin) < SMALL)
137 xmin = (xmin > 0) ?
max(0, xmin - eps) : xmin - eps;
140 if (
mag(xmax) < SMALL)
142 xmax =
mag(xmin) < SMALL ? 1 : 0;
146 xmax = (xmax < 0) ?
min(0, xmax + eps) : xmax + eps;
150 <<
"2 -- xmin:" << xmin <<
" xmax:" << xmax
151 <<
" xtick:" << xtick <<
endl;
153 auto lookup = [](
const scalar
x) -> scalar
155 if (
x < 2.5) {
return 0.2; }
156 if (
x < 5.0) {
return 0.5; }
157 if (
x < 10.0) {
return 2.0; }
162 const scalar factor =
pow(10, power - floor(power));
164 xtick = lookup(factor)*
pow(10, floor(power));
165 xmin = xtick*floor(xmin/xtick);
166 xmax = xtick*(floor(xmax/xtick) + 1);
177 <<
"power:" << power <<
" factor:" << factor
178 <<
" xmin:" << xmin <<
" xmax:" << xmax
179 <<
" xtick:" << xtick <<
endl;
181 return round((xmax - xmin)/xtick);
187Foam::functionObjects::graphFunctionObject::graphFunctionObject
204 xMin_(
dict.getOrDefault<scalar>(
"xMin", GREAT)),
205 xMax_(
dict.getOrDefault<scalar>(
"xMax", GREAT)),
206 yMin_(
dict.getOrDefault<scalar>(
"yMin", GREAT)),
207 yMax_(
dict.getOrDefault<scalar>(
"yMax", GREAT)),
208 xlabel_(
dict.getOrDefault<
string>(
"xlabel",
"Iteration/Time")),
209 ylabel_(
dict.getOrDefault<
string>(
"ylabel",
"Property")),
210 width_(
dict.getOrDefault<label>(
"width", 800)),
211 height_(
dict.getOrDefault<label>(
"height", 600)),
212 strokeWidth_(
dict.getOrDefault<label>(
"strokeWidth", 2)),
213 logScaleX_(
dict.getOrDefault<bool>(
"logScaleX", false)),
214 logScaleY_(
dict.getOrDefault<bool>(
"logScaleY", false)),
215 drawGrid_(
dict.getOrDefault<bool>(
"drawGrid", true))
223 objectToCol_.setSize(functions.
size());
225 label defaultColouri = 0;
228 for (
const auto&
e : functions)
233 <<
"Functions must be provided in dictionary format"
238 objects_[entryi] = d.
get<
word>(
"object");
239 entries_[entryi] = d.
get<
word>(
"entry");
240 titles_[entryi] = d.
getOrDefault<
string>(
"title",
e.keyword());
246 colour[0] =
min(255,
max(0, colour[0]));
247 colour[1] =
min(255,
max(0, colour[1]));
248 colour[2] =
min(255,
max(0, colour[2]));
252 colours_[entryi] = oss.
str();
256 colours_[entryi] = defaultColours[defaultColouri++];
257 if (defaultColouri == defaultColours.size())
270 oss <<
flatOutput(dashes, FlatOutput::BareSpace{});
271 dashes_[entryi] = oss.
str();
276 dashes_[entryi] =
"0";
291 scalar& graphTime = times_.emplace_back(time_.timeOutputValue());
295 graphTime =
log10(
max(graphTime, SMALL));
302 getValue<label>(objecti, valuei)
303 || getValue<scalar>(objecti, valuei)
304 || getValue<vector>(objecti, valuei)
305 || getValue<sphericalTensor>(objecti, valuei)
306 || getValue<symmTensor>(objecti, valuei)
307 || getValue<tensor>(objecti, valuei);
313 <<
"Unable to get value for object:" << objects_[objecti]
314 <<
" entry:" << entries_[objecti] <<
endl;
327 auto filePtr = newFileAtTime(
name(), time().value());
331 scalar ymax = -GREAT;
334 for (
const auto& data : values_)
336 for (
const auto& value : data)
338 ymin =
min(ymin, value);
339 ymax =
max(ymax, value);
348 <<
" No data to plot - skipping" <<
nl;
356 auto applyLimits = [](
const scalar val,
const scalar lim,
const bool lg)
358 if (lim < 0.99*GREAT)
360 return lg ?
log10(lim) : lim;
368 ymin = applyLimits(ymin, yMin_, logScaleY_);
369 ymax = applyLimits(ymax, yMax_, logScaleY_);
373 const label ny = setAxisProps(logScaleY_, ymin, ymax, ytick);
375 const scalar border = 0.1;
376 const scalar w = width_*(1.0 - 2*border);
377 const scalar
h = height_*(1.0 - 2*border);
380 scalar xmin = applyLimits(0, xMin_, logScaleX_);
381 scalar xmax = applyLimits(
max(times_), xMax_, logScaleX_);
385 const label nx = setAxisProps(logScaleX_, xmin, xmax, xtick);
388 auto top = [=](
const scalar
y)
390 const scalar ratio = (
y - ymin)/(ymax - ymin + ROOTVSMALL);
391 return round(height_ - ratio*
h - border*height_);
395 auto left = [=](
const scalar
x)
397 return round(
x/(xmax - xmin + ROOTVSMALL)*w + border*width_);
400 const scalar fontpx =
min(20,
h/(2*values_.size()));
401 const scalar fontdy = 1.5*fontpx;
404 const label legendLineRight = border*width_ + w - fontpx;
405 const label legendLineLeft = legendLineRight - 0.5*border*width_;
406 const label legendLabelRight = legendLineLeft - 0.5*fontpx;
409 const word colour =
"rgb(105,105,105)";
411 os << SVG::header(width_, height_) <<
nl;
414 SVG::element bounds(
"rect", {{
"fill",
"none"}, {
"stroke", colour}});
415 bounds.addAttr(
"x", round(border*width_));
416 bounds.addAttr(
"y", round(border*height_));
417 bounds.addAttr(
"width", round(w));
418 bounds.addAttr(
"height", round(
h));
419 os << bounds << bounds.end <<
nl;
427 height_ - 0.5*(border*height_) + fontpx,
442 ytext.addAttr(
"alignment-baseline",
"middle");
446 "translate(" +
Foam::name(left(xmin) - 3*fontpx) +
","
451 const label dTick = 0.2*fontpx;
456 const word colourGrid =
"rgb(200,200,200)";
458 for (label i = 1; i < nx; ++i)
460 const label
x = left(xmin + i*xtick);
461 const label
y1 = top(ymin);
462 const label y2 = top(ymax);
472 {
"stroke", colourGrid},
473 {
"stroke-width",
"1"},
474 {
"stroke-dasharray",
"4"}
479 for (label i = 1; i < ny; ++i)
481 const label
y = top(ymin + i*ytick);
482 const label x1 = left(xmin);
483 const label x2 = left(xmax);
493 {
"stroke", colourGrid},
494 {
"stroke-width",
"1"},
495 {
"stroke-dasharray",
"4"}
502 for (label i = 0; i <= nx; ++i)
504 const scalar v = xmin + i*xtick;
505 const label
x = left(v);
506 const scalar
y0 = ymin;
507 const label
y1 = top(
y0);
508 const label y2 =
y1 + dTick;
509 const string tickLabel = logScaleX_
510 ?
"<tspan>10<tspan style=\"font-size:"
512 +
"px\" dy=\"" +
Foam::name(-0.4*fontpx) +
"\">"
540 for (label i = 0; i <= ny; ++i)
542 const scalar v = ymin + i*ytick;
543 const label
y = top(v);
544 const label y2 =
y + 0.4*fontpx;
545 const scalar x0 = xmin;
546 const label x1 = left(x0);
547 const label x2 = x1 - dTick;
548 const string tickLabel = logScaleY_
549 ?
"<tspan>10<tspan style=\"font-size:"
551 +
"px\" dy=\"" +
Foam::name(-0.4*fontpx) +
"\">"
563 {{
"stroke", colour},{
"stroke-width",
"1"}}
580 const word& colour = colours_[objecti];
582 const auto& cols = objectToCol_[objecti];
583 for (
const label c : cols)
585 const word cmpt = cols.size() > 1 ?
Foam::name(c) :
"";
587 label legendTop = border*height_ + fontdy*(
c+1);
590 titles_[objecti] + cmpt,
600 legendTop - 0.5*fontpx,
602 legendTop - 0.5*fontpx,
603 {{
"stroke", colour},{
"stroke-width",
"2"}},
604 {{
"stroke-dasharray", dashes_[objecti]}}
609 const auto& data = values_[
c];
610 bool firstPoint =
true;
613 const scalar t = times_[i];
614 const scalar v = data[i];
616 if ((v > ymin) && (v < ymax))
627 os << left(t) <<
' ' << top(v);
638 <<
" style=\"stroke:" << colour <<
";"
639 <<
" fill:none; stroke-width:2;\""
640 <<
" stroke-dasharray=\"" << dashes_[objecti].c_str() <<
"\" />"
648 <<
" Written file " <<
os.name() <<
nl <<
endl;
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
for(const label curEdgei :curPointEdges)
label size() const noexcept
The number of elements in list.
void setSize(label n)
Alias for resize().
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
Foam::string str() const
Get the string. As Foam::string instead of std::string (may change in future).
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
T get(const word &keyword, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T. FatalIOError if not found, or if the number of tokens is incorrect.
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
Find and return a T, or return the given default value. FatalIOError if it is found and the number of...
bool readIfPresent(const word &keyword, T &val, enum keyType::option matchOpt=keyType::REGEX) const
Find an entry if present, and assign to T val. FatalIOError if it is found and the number of tokens i...
Abstract base-class for Time/database function objects.
const word & name() const noexcept
Return the name of this functionObject.
Accumulates function object result values and renders into a graph in SVG format.
virtual bool execute()
Execute the function-object operations.
virtual bool write()
Write the function-object results.
Base class for function objects, adding functionality to read/write state information (data required ...
stateFunctionObject(const stateFunctionObject &)=delete
No copy construct.
Type getObjectResult(const word &objectName, const word &entryName, const Type &defaultValue=Type(Zero)) const
Retrieve result from named object.
const Time & time_
Reference to the time database.
const Time & time() const
Return time database.
Base class for writing single files from the function objects.
writeFile(const objectRegistry &obr, const fileName &prefix, const word &name="undefined", const bool writeToFile=true, const string &ext=".dat")
Construct from objectRegistry, prefix, fileName.
virtual autoPtr< OFstream > newFileAtTime(const word &name, scalar timeValue) const
Return autoPtr to a new file for a given time.
A class for handling character strings derived from std::string.
A class for handling words, derived from Foam::string.
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
OBJstream os(runTime.globalPath()/outputName)
#define DebugInfo
Report an information message using Foam::Info.
Namespace for bounding specifications. At the moment, mostly for tables.
const dimensionedScalar c
Speed of light in a vacuum.
Function objects are OpenFOAM utilities to ease workflow configurations and enhance workflows.
List< word > wordList
List of word.
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
List< label > labelList
A List of labels.
Vector< label > labelVector
Vector of labels.
dimensionedScalar y0(const dimensionedScalar &ds)
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
dimensionedScalar log10(const dimensionedScalar &ds)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
const word GlobalIOList< Tuple2< scalar, vector > >::typeName("scalarVectorTable")
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar y1(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
FlatOutput::OutputAdaptor< Container, Delimiters > flatOutput(const Container &obj, Delimiters delim)
Global flatOutput() function with specified output delimiters.
IOerror FatalIOError
Error stream (stdout output on all processes), with additional 'FOAM FATAL IO ERROR' header text and ...
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
errorManipArg< error, int > exit(error &err, const int errNo=1)
constexpr char nl
The newline '\n' character (0x0a).
#define forAll(list, i)
Loop across all elements in list.
Surround with '\0' and '\0' separate with ' '.
Surround with '(' and ')' separate with ','.
void addAttr(const char *key, const Type &value)
autoPtr< OFstream > filePtr