39 namespace functionObjects
52 Foam::wordList Foam::functionObjects::graphFunctionObject::defaultColours
69 bool Foam::functionObjects::graphFunctionObject::getValue
75 const word&
object = objects_[objecti];
76 const word& entry = entries_[objecti];
84 auto& cols = objectToCol_[objecti];
90 values_.push_back(DynamicList<scalar>());
100 v = (v < SMALL) ? 1 :
log10(v);
103 values_[cols[d]].push_back(v);
110 Foam::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);
187 Foam::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))
218 objects_.
setSize(functions.size());
219 entries_.
setSize(functions.size());
220 titles_.
setSize(functions.size());
221 colours_.
setSize(functions.size());
222 dashes_.
setSize(functions.size());
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;
void size(const label n)
Older name for setAddressableSize.
defineTypeNameAndDebug(ObukhovLength, 0)
errorManipArg< error, int > exit(error &err, const int errNo=1)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
constexpr char nl
The newline '\n' character (0x0a)
Ostream & endl(Ostream &os)
Add newline and flush stream.
dimensionedScalar y0(const dimensionedScalar &ds)
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
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.
void push_back(const T &val)
Append an element at the end of the list.
Class to control time during OpenFOAM simulations that is also the top-level objectRegistry.
Macros for easy insertion into run-time selection tables.
#define forAll(list, i)
Loop across all elements in list.
Foam::string str() const
Get the string. As Foam::string instead of std::string (may change in future)
autoPtr< OFstream > filePtr
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
const dimensionedScalar e
Elementary charge.
void setSize(const label n)
Alias for resize()
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
A class for handling words, derived from Foam::string.
Type getObjectResult(const word &objectName, const word &entryName, const Type &defaultValue=Type(Zero)) const
Retrieve result from named object.
virtual bool execute()
Execute.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
dimensionedScalar y1(const dimensionedScalar &ds)
virtual bool write()
Write.
#define DebugInfo
Report an information message using Foam::Info.
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...
OBJstream os(runTime.globalPath()/outputName)
addToRunTimeSelectionTable(functionObject, ObukhovLength, dictionary)
const dimensionedScalar h
Planck constant.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Surround with '(' and ')' separate with ','.
const dimensionedScalar c
Speed of light in a vacuum.
static bool master(const label communicator=worldComm)
True if process corresponds to the master rank in the communicator.
Base class for function objects, adding functionality to read/write state information (data required ...
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...
List< label > labelList
A List of labels.
Base class for writing single files from the function objects.
A class for handling character strings derived from std::string.
void component(FieldField< Field, typename FieldField< Field, Type >::cmptType > &sf, const FieldField< Field, Type > &f, const direction d)
Output to string buffer, using a OSstream. Always UNCOMPRESSED.
dimensionedScalar log10(const dimensionedScalar &ds)
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 ...