Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
85 lines (67 sloc) 6.13 KB
#pragma once
#ifdef WOO_VTK
struct FlowAnalysis: public PeriodicEngine{
bool acceptsField(Field* f) override { return dynamic_cast<DemField*>(f); }
DemField* dem; // temp only
typedef boost::multi_array<Real,5> boost_multi_array_real_5;
typedef boost::multi_array<Vector3r,3> boost_multi_array_Vector3_3;
typedef boost::multi_array<Real,3> boost_multi_array_real_3;
// return grid point lower or equal to this spatial point
inline Vector3i xyz2ijk(const Vector3r& xyz) const {
// ((xyz-box.min())/cellSize).cast<int>() rounds towards zero, but we need to round down always, hence..
Vector3r t=(xyz-box.min())/cellSize;
return Vector3i(floor(t[0]),floor(t[1]),floor(t[2]));
// return lower grid point for this cell coordinate
inline Vector3r ijk2xyz(const Vector3i& ijk) const { return box.min()+ijk.cast<Real>()*cellSize; }
void setupGrid();
void addOneParticle(const shared_ptr<Particle>& par, const Vector3r& parPosLocal, const Real& radius, const Real& solidRatio);
void addCurrentData();
Real avgFlowNorm(const vector<size_t> &fractions);
string vtkExportFractions(const string& out, /*modifiable copy*/ vector<size_t> fractions);
vector<string> vtkExport(const string& out);
string vtkWriteGrid(const string& out, vtkSmartPointer<vtkUniformGrid>& grid);
vtkSmartPointer<vtkUniformGrid> vtkMakeGrid();
template<class vtkArrayType=vtkDoubleArray>
vtkSmartPointer<vtkArrayType> vtkMakeArray(const vtkSmartPointer<vtkUniformGrid>& grid, const string& name, size_t numComponents, bool fillZero=true);
// when fracA and/or fracB are not given, half/half is taken -- for convenience
string vtkExportVectorOps(const string& out, const vector<size_t>& fracA, const vector<size_t>& fracB);
void run() override;
void reset();
void render(const GLViewInfo&) override;
// number of floats to store for each point
#define woo_dem_FlowAnalysis__CLASS_BASE_DOC_ATTRS_PY \
FlowAnalysis,PeriodicEngine,"Collect particle flow data in rectangular grid, watching different particle groups (radius ranges via :obj:`dLim` or groups by mask via :obj:`masks` -- only one of them may be specified), and saving averages to as VTK uniform grid once finished.\n\n.. note:: Only particles returning meaningful :obj:`woo.dem.Shape.equivRad` are considered, all other are ignored.", \
((AlignedBox3r,box,,AttrTrait<>().buttons({"Open in Paraview","import woo.paraviewscript\nwith self.scene.paused(): woo.paraviewscript.fromFlowAnalysis(self,launch=True)",""},/*showBefore*/true),"Domain in which the flow is to be analyzed; the box may glow slightly to accomodate integer number of cells. Do not change once there is some data alread. Do not change once there is some data already.")) \
((shared_ptr<Node>,node,,,"Defines local coordinates system; it undefined, uses global coordinates.")) \
((boost_multi_array_real_5,data,boost_multi_array_real_5(boost::extents[0][0][0][0][0]),AttrTrait<Attr::hidden>(),"Grid data -- 5d since each 3d point contains multiple entries, and there are multiple grids.")) \
((vector<Real>,dLim,,,"Limiting diameter values, for defining fractions which are analyzed separately. Do not change when there is some data already.")) \
((vector<int>,masks,,,"Mask values for fractions; it is an error if a particle matches multiple masks. Do not change when there is some data already.")) \
((int,nFractions,-1,AttrTrait<Attr::readonly>(),"Number of fractions, defined via :obj:`dLim` or :obj:`masks`; set automatically.")) \
((Real,cellSize,NaN,,"Size of one cell in the box (in all directions); will be satisfied exactly at the expense of perhaps slightly growing :obj:`box`. Do not change once there is some data already.")) \
((Vector3i,boxCells,Vector3i::Zero(),AttrTrait<Attr::readonly>(),"Number of cells in the box (computed automatically)")) \
((int,mask,0,,"Particles to consider in the flow analysis (0 to consider everything).")) \
((bool,cellData,false,,"Write flow rate as cell data rather than point data.")) \
((bool,porosity,false,,"Compute (and export) solid ratio (1-porosity) for all spheroidal particles (requires triangulation of the domain at every step, hence slow and not enabled by default.")) \
((int,matStateScalar,-1,,"If non-negative, index of material state to analyze.")) \
((string,matStateName,"",,"If given, used for VTK-export of the scalar; if not given, is filled form the first instance encountered automatically.")) \
((Real,timeSpan,0.,,"Total time that the analysis has been running.")) \
((Vector3r,color,Vector3r(1,1,0),AttrTrait<>().rgbColor(),"Color for rendering the domain")) \
, /*py*/ \
.def("vtkExport",&FlowAnalysis::vtkExport,WOO_PY_ARGS(py::arg("out")),"Export all fractions separately, and also an overall flow (sum). *out* specifies prefix for all export filenames, the rest is created to describe the fraction or ``all`` for the sum. Exported file names are returned, the sum being at the very end. Internally calls :obj:`vtkExportFractions` for all fractions.") \
.def("vtkExportFractions",&FlowAnalysis::vtkExportFractions,WOO_PY_ARGS(py::arg("out"),py::arg("fractions")),"Export one single fraction to file named *out*. The extension ``.vti`` is added automatically. *fractions* specifies existing fraction numbers to export. If *fractions* are an empty list (``[]``), all fractions are exported at once.") \
.def("vtkExportVectorOps",&FlowAnalysis::vtkExportVectorOps,WOO_PY_ARGS(py::arg("out"),py::arg("fracA"),py::arg("fracB")),"Export operations on two fraction sets: cross-product, weighted differences and such, for segregation analysis. Appends ``.opt.vti`` to the output filename in *out*.") \
.def("reset",&FlowAnalysis::reset,"Reset all data so that next analysis will be run from virgin state.")
#endif /* WOO_VTK */
You can’t perform that action at this time.