v2206: New and improved post-processing
The very old writer class has been replaced with a new coordSetWriter class that uses similar concepts to the previously updated surface writers. Changes are largely transparent for the end-user, except that in some cases the output filenames for raw format will be slightly different.
Changes include:
-
Sample/write a field in a single step; this allows use of the writers for streaming operations.
-
Collect multiple field types, e.g. scalar, vector etc. into a single output. This is especially noticeable for VTK and Ensight formats where the number of generated files is reduced.
-
Direct writing of the raw format as unbuffered output, with a file layout consistent with the raw format for surface writers.
-
Support for sampleOnExecute to obtain values at execution intervals without writing. This allows internal sampling for use in functionObject controls without thrashing the disk with unnecessary IO operations.
-
Support sets input as a dictionary entry (as well as a list), similar to the changes for sampled-surface, and permits use of changeDictionary to modify content.
-
sampleSet results (properties) are now qualified with the name of the set, allowing multiple subsets to be addressed.
This potentially represents a breaking change for some workflows, but corrects deficiencies in the the previous version. For example:
sample1 { scalar { average(line,T) 349.96521; min(line,T) 349.9544281; max(line,T) 350; average(cells,T) 349.9854619; min(cells,T) 349.6589286; max(cells,T) 350.4967271; average(line,epsilon) 0.04947733869; min(line,epsilon) 0.04449639927; max(line,epsilon) 0.06452856475; } label { size(line,T) 79; size(cells,T) 1720; size(line,epsilon) 79; } }
Note: since values are scoped by the name of the set itself, e.g. average(line,T) for the average temperature of the 'line' set, existing workflows will break.
Unqualified names now correspond to ensemble values of all the sub-sets. This means that if the existing workflow only had a single sub-set the net change will be non-breaking. It is, however, advisable to use the more precise specification to future-proof your workflow.
average(p) // Ensemble average of all listed sets
-
sampledSets have an additional special-purpose probes setFormat that collects all of the specified sampled location points into a single, aggregate ensemble output with a raw probed format.
This can be useful when it is more convenient to specify probe locations in terms of arrays/lines instead of individual points.
Source code
Probes have an additional sampleOnExecute option which supports sampling/probing of values to obtain min/max/average/size at execution intervals without writing any output or generating output directories.
Source code
Sampled surfaces have received multiple updates, including:
-
Removed support for sampling onto an internal surfMesh. This was a rarely used feature that was a stop-gap measure before the more flexible polySurface sample/storage was added (FEB-2019);
-
enhanced output for sampled surfaces; and
-
improved point merging.
The surface writers now support field scaling and geometric transformations. The fieldLevel is useful to add or remove a uniform shift prior to applying any fieldScale, e.g.:
fieldLevel
{
"p.*" 1e5; // Absolute -> gauge [Pa]
T 273.15; // [K] -> [C]
U #eval{ 10/sqrt(3) }; // Uniform mag(U)=10
}
After the fieldLevel has been removed, any fieldScale is applied, e.g.:
fieldScale
{
"p.*" 0.01; // [Pa] -> [mbar]
}
This is particularly useful to gain more output precision for pressure fields, e.g. when using EnSight-format which is intrinsically limited to single-precision.
The new optional transform entry allows the "relocation" of sampled surfaces. For example, to reposition into a different coordinate system for importing into CAD, e.g.:
formatOptions
{
vtk
{
scale 1000; // m -> mm
transform
{
origin (0.05 0 0);
rotation axisAngle;
axis (0 0 1);
angle -45;
}
}
}
This will transform vector or tensor fields according to the geometric rotation.
The runTimeControl function object activates further function objects using triggers. Previously the trigger index could only advance; this change set allows users to set smaller values to enable function object recycling, e.g.
Repeat for N cycles:
- average the pressure at a point in space
- when the average stabilises, run for a further 100 iterations
- set a new patch inlet velocity
- back to (1)
This release also includes a none condition that acts as a pass-through/no-op with the option to set a new trigger value.
Tutorials
Source code
The multiFieldValue function object now operates on any function object that generates result entries, removing the restriction of only using fieldValue-type function objects.
For example, it is now possible to average the results of surfaceFieldValue and valueAverage function objects as follows:
averagePressure
{
type multiFieldValue;
libs (fieldFunctionObjects);
operation average;
functions
{
inlet
{
type surfaceFieldValue;
operation areaAverage;
regionType patch;
name inlet;
fields (p);
writeFields no;
writeToFile no;
log no;
}
outlet
{
type surfaceFieldValue;
operation areaAverage;
regionType patch;
name outlet;
fields (p);
writeFields no;
writeToFile no;
log no;
}
average
{
type valueAverage;
functionObject testSample1;
fields (average(p));
writeToFile no;
log no;
}
}
}
The output has also been updated for clarity:
1 # Group0
2 # - averagePressure:inlet:areaAverage(inlet,p)
3 # - averagePressure:outlet:areaAverage(outlet,p)
4 # - averagePressure:average:average(p)Mean
5 # Operation : add
6 # Time Group0
7 0.00120482 3.4483824485e+05
8 0.00265769 3.0352523946e+05
9 0.00439595 3.0338969991e+05
Additional groups are labelled Group1, Group2 ... GroupN etc.
Tutorials
- $FOAM_TUTORIALS/lagrangian/reactingParcelFoam/filter
- $FOAM_TUTORIALS/incompressible/pisoFoam/RAS/cavity
Source code
The force and forces function objects have been refactored, to reduce code complexity and improve code maintenance. The binning functionality has been removed, and now available as a separate binField function object.
Users have more control when requesting force coefficients; previously, all contributions were written - these can now be selected using the optional 'coefficients' entry:
coefficients (Cd Cl(f) Cl(r));
The full list of coefficients comprise:
- Cd, Cd(f), Cd(r) : drag force, (front and rear)
- Cs, Cs(f), Cs(r) : side force, (front and rear)
- Cl, Cl(f), Cl(r) : lift force, (front and rear)
- CmRoll : roll moment
- CmPitch : pitch moment
- CmYaw : yaw moment
If omitted, all coefficients will be written.
Tutorials
- $FOAM_TUTORIALS/incompressible/simpleFoam/motorBike/system/forceCoeffs
- $FOAM_TUTORIALS/incompressible/simpleFoam/simpleCar/system/forceCoeffs
Source code
The new binField function object calculates binned data, where specified patches and cell zones are divided into segments to enable spatially-localised information to be output for each segment.
Two bin models are available:
- singleDirectionUniformBin: calculates binned data in a specified direction; and
- uniformBin: calculates binned data in multiple segments according to a specified Cartesian or cylindrical coordinate system.
Output variables include:
- total: the sum of patch and internal
- patch: patch data
- internal: e.g. porous data from specified cell zones
- normal and tangential: orthogonal components of the patch data
As an example, to recover the previous binning behaviour of the forceCoeffs function object:
forceCoeffs1
{
type forceCoeffs;
libs (forces);
writeControl writeTime;
writeFields true;
patches (body);
p p;
U U;
rho rhoInf; // Indicates incompressible
log true;
rhoInf 1; // Required when rho = rhoInf
liftDir (0 1 0);
dragDir (1 0 0);
CofR (3.5 0 0); // Axle midpoint on ground
pitchAxis (0 0 1);
magUInf 10;
lRef 4; // Wheelbase length
Aref 1; // Estimated
porosity on;
}
binField1
{
type binField;
libs (fieldFunctionObjects);
binModel singleDirectionUniformBin;
fields (forceCoeff);
patches (body);
decomposePatchValues yes;
CofR ${..forceCoeffs1.CofR};
cellZones (porousZone);
binData
{
nBin 20; // output data into 20 bins
direction (1 0 0); // bin direction
cumulative yes;
}
writeControl writeTime;
}
Tutorials
Source code
The Dynamic Mode Decomposition function object has been extended to enable users to specify multiple patches in DMD calculations:
DMD1
{
// Optional entries
// Option-1
patch <word>;
// Option-2
patches (<wordRes>);
}
Performance has also been improved, whereby the most expensive parts of the STDMD implementation were identified and refactored, resulting in reduced run-times. For example, the timing of the standard "cylinder2D" tutorial, i.e. where all STDMD function objects are active, the duration of the parallel, 12-processor simulation, reduced by approximately 60%.
Source code
Tutorial
Merge request
The new particleZoneInfo cloud function object generates statistics for particles crossing a cellZone. It is specified in the cloudFunctions sub-dictionary of the cloud properties file, e.g.:
cloudFunctions
{
particleZoneInfo1
{
type particleZoneInfo;
cellZone leftFluid;
// Optional entries
writer vtk; // vtk, raw, none
}
}
If the optional writer entry is supplied, cloud data is written in the specified format. Statistics generated include the particle:
- index and its originating processor
- time, diameter and mass when first entering the cellZone
- current position, diameter and mass
- time spent in the cellZone
During the run, the object writes after the cloud solution, e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 257
Here, Contributions refers to the number of incremental particle-move contributions recorded during this time step. At write times, the output is extended, e.g.:
particleZoneInfo:
Cell zone = leftFluid
Contributions = 822
Number of particles = 199
Written data to "postProcessing/lagrangian/reactingCloud1/particleZoneInfo1/0.7/particles.dat"
The particles.dat file contains the particle statistics, e.g.:
# cellZone : leftFluid
# time : 1.0000000000e+00
#
# origID origProc (x y z) time0 age d0 d mass0 mass
2 0 (1.2403730063e+00 6.3907929681e-01 5.0000000000e-02) 5.0400000000e-01 5.0400000000e-01 1.0000000000e-03 9.9733169015e-04 5.2359877560e-07 5.1941857822e-07
3 0 (1.2294005030e+00 7.1626530229e-01 5.0000000000e-02) 5.0400000000e-01 5.0225000000e-01 1.0000000000e-03 9.9733162350e-04 5.2359877560e-07 5.1941847408e-07
4 0 (1.2265565036e+00 6.5308628366e-01 5.0000000000e-02) 5.0400000000e-01 5.0100000000e-01 1.0000000000e-03 9.9733541220e-04 5.2359877560e-07 5.1942439366e-07
Tutorials
Source code
The cloudInfo is a simple cloud function object that reports some basic parcel information such as
- number of parcels
- mass in system
- maximum diameter
- D10 diameter
- D32 diameter
It is now extended to support a restricted selection of parcels to analyse. The selection mechanism is identical to the vtkCloud function object, e.g.
selection
{
all
{
action all;
}
T
{
action subset;
source field;
field T;
accept (greater 280) and (less 300);
}
Umin
{
action subtract;
source field;
field U;
accept (less 0.1);
}
}
Tutorials
Source code
The new doses cloud function object calculates the dose absorbed by a particle as the time integral of the particle track along the radiation field G [w/m2].
The function object is specified as:
cloudFunctions
{
ParticleDose1
{
type ParticleDose;
GName G;
}
}
Tutorials
Source code
The new norm function object normalises an input field with a chosen norm, and writes a new normalised field.
A minimal example usage follows:
norm1
{
// Mandatory entries
type norm;
libs (fieldFunctionObjects);
field <word>;
norm <word>;
// Conditional entries
// when norm == Lp
p <scalar>;
// when norm == composite
divisor <Function1<scalar>>;
// when norm == divisorField
divisorField <word>;
// Inherited entries
...
}
for which the following norm entries are available:
- L1 : L1/Taxicab norm
- L2 : L2/Euclidean norm
- Lp : p norm
- max : Maximum norm
- composite : Composite norm comprising Function1 divisor
- divisorField : Normalise by a given field
Source code
Tutorial
Merge request
Finite-area fields are now detected and converted in both foamToEnsight and foamToVTK by default. If required, this can be suppressed with the -no-finite-area option; the old -finite-area option is now ignored.
The foamToEnsight and foamToVTK utilities have additional -exclude-fields and -no-fields options for more precise control over conversions.