Skip to content

Commit

Permalink
Provide an advanced option in flow advection to use a fixed, user pro…
Browse files Browse the repository at this point in the history
…vided step size. (#3505)

* WIP: creating widgets

* GUI should be working now

* minor adjustment

* fixed step size rendering parameter is passed in. Need a cache mechanism too

* Renderer honors fixed steps too!

* fix typo

---------

Co-authored-by: Samuel Li <shaomeng@cisl-vapor>
Co-authored-by: Samuel Li <Sam@Navada>
  • Loading branch information
3 people authored Dec 18, 2023
1 parent d74cb27 commit 8ceaa4f
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 20 deletions.
4 changes: 3 additions & 1 deletion apps/vaporgui/FlowEventRouter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ FlowEventRouter::FlowEventRouter(QWidget *parent, ControlExec *ce) : RenderEvent

new PSection("Advanced Options", {
(new PDoubleInput(FP::_velocityMultiplierTag, "Vector Field Multiplier"))->SetTooltip( "Apply a multiplier to the velocity field."),
(new PDoubleInput(FP::_firstStepSizeMultiplierTag, "First Step Size Multiplier"))->SetTooltip( "Apply a multiplier to the auto-calculated first step size. Very occasionally a value bigger than 1.0 is needed here.")
(new PDoubleInput(FP::_firstStepSizeMultiplierTag, "First Step Size Multiplier"))->SetTooltip( "Apply a multiplier to the auto-calculated first step size. Very occasionally a value bigger than 1.0 is needed here."),
(new PCheckbox(FP::_fixedAdvectionStepTag, "Use Fixed Advection Steps"))->SetTooltip( "The user may provide an advection step size, so that VAPOR disables dynamic step size adjustments and always uses the fixed step size."),
(new PShowIf(FP::_fixedAdvectionStepTag))->Then(new PDoubleInput(FP::_fixedAdvectionStepSizeTag, " |--- Fixed Advection Step Size"))->SetTooltip( "Use this specific value as the fixed advection step size."),
}),
}));

Expand Down
8 changes: 4 additions & 4 deletions include/vapor/Advection.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,10 @@ class FLOW_API Advection final {
//
// Advect all particles as long as they are within spatial and temporal boundary
// for a specified number if steps.
int AdvectSteps(Field *velocityField, double deltaT, size_t maxSteps, ADVECTION_METHOD method = ADVECTION_METHOD::RK4);
int AdvectSteps(Field *velocityField, double deltaT, size_t maxSteps, bool fixedStepSize, ADVECTION_METHOD method = ADVECTION_METHOD::RK4);
// Advect as many steps as necessary to reach a certain time: targetT.
// Note: it only considers particles that have already passed startT.
int AdvectTillTime(Field *velocityField, double startT, double deltaT, double targetT, ADVECTION_METHOD method = ADVECTION_METHOD::RK4);
int AdvectTillTime(Field *velocityField, double startT, double deltaT, double targetT, bool fixedStepSize, ADVECTION_METHOD method = ADVECTION_METHOD::RK4);

// Retrieve field values of a particle based on its location, and put the result in
// the "value" field or the "properties" field of a particle
Expand Down Expand Up @@ -109,8 +109,8 @@ class FLOW_API Advection final {
// Print return code if it's non-zero and compiled in debug mode.
void _printNonZero(int rtn, const char *file, const char *func, int line) const;

void _calculateParticleIntegratedValue(Particle &p, const Particle &prev, const Field *scalarField, const bool skipNonZero, const float distScale,
const std::vector<double> &integrateWithinVolumeMin, const std::vector<double> &integrateWithinVolumeMax) const;
void _calculateParticleIntegratedValue(Particle &p, const Particle &prev, const Field *scalarField, const bool skipNonZero, const float distScale,
const std::vector<double> &integrateWithinVolumeMin, const std::vector<double> &integrateWithinVolumeMax) const;
static bool _isParticleInsideVolume(const Particle &p, const std::vector<double> &min, const std::vector<double> &max);
};
}; // namespace flow
Expand Down
23 changes: 23 additions & 0 deletions include/vapor/FlowParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,17 @@ class PARAMS_API FlowParams : public RenderParams {
//! In such cases, users may manually apply a multiplier to the first step size.
//! \retval double - First step size multiplier for flow rendering.
double GetFirstStepSizeMultiplier() const;

//! Get the boolean that indicates if the flow advection uses fixed step sizes.
//! \details VAPOR adjusts its advection step sizes automatically based on the curvature of the past few steps.\n
//! This behavior, however, can be disabled, in which case the user-provided step size will be used.\n
//! \retval bool - If VAPOR uses fixed advection steps.
bool GetUseFixedAdvectionSteps() const;

//! Get the fixed advection step size to be used.
//! \copydetails FlowParams::GetUseFixedAdvectionSteps()
//! \retval double - Fixed advection step size to be used.
double GetFixedAdvectionStepSize() const;

//! Set the multiplier being applied to the flow advection algorithm.
//! \copydetails FlowParams::GetVelocityMultiplier()
Expand All @@ -92,6 +103,16 @@ class PARAMS_API FlowParams : public RenderParams {
//! \param[in] double - Velocity field multiplier for flow rendering
void SetFirstStepSizeMultiplier(double);

//! Set the boolean that indicates if the flow advection uses fixed step sizes.
//! \copydetails FlowParams::GetUseFixedAdvectionSteps()
//! \param[in] bool - If VAPOR uses fixed advection steps.
void SetUseFixedAdvectionSteps(bool);

//! Set the fixed advection step size to be used.
//! \copydetails FlowParams::GetUseFixedAdvectionSteps()
//! \param[in] bool - User-specified value to be used for fixed step advection.
void SetFixedAdvectionStepSize(double);

//! Get the target number of steps to advect a steady flow line (aka a streamline).
//! \copydetails FlowParams::SetSteadyNumOfSteps()
//! \retval long - The number of steps a steady flow line targets to advect.
Expand Down Expand Up @@ -374,6 +395,8 @@ class PARAMS_API FlowParams : public RenderParams {
static const std::string _isSteadyTag;
static const std::string _velocityMultiplierTag;
static const std::string _firstStepSizeMultiplierTag;
static const std::string _fixedAdvectionStepTag;
static const std::string _fixedAdvectionStepSizeTag;
static const std::string _steadyNumOfStepsTag;
static const std::string _seedGenModeTag;
static const std::string _seedInputFilenameTag;
Expand Down
2 changes: 2 additions & 0 deletions include/vapor/FlowRenderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ class RENDER_API FlowRenderer final : public Renderer {
bool _cache_integrationSetAllToFinalValue;
float _cache_integrationDistScalar;
std::vector<double> _cache_integrationVolume;
bool _cache_useFixedAdvectionSteps = false;
double _cache_fixedAdvectionStepSize = 0.0;

// This Advection class is only used in bi-directional advection mode
std::unique_ptr<flow::Advection> _2ndAdvection;
Expand Down
12 changes: 6 additions & 6 deletions lib/flow/Advection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ int Advection::CheckReady() const
return 0;
}

int Advection::AdvectSteps(Field *velocity, double deltaT, size_t maxSteps, ADVECTION_METHOD method)
int Advection::AdvectSteps(Field *velocity, double deltaT, size_t maxSteps, bool fixedStepSize, ADVECTION_METHOD method)
{
int ready = CheckReady();
if (ready != 0) return ready;
Expand All @@ -57,8 +57,8 @@ int Advection::AdvectSteps(Field *velocity, double deltaT, size_t maxSteps, ADVE
break; // terminate stream immediately.

double dt = deltaT;
if (s.size() > 2) // If there are at least 3 particles in the stream and
{ // neither is a separator, we also adjust *dt*
if (!fixedStepSize && s.size() > 2) // When not using fixed step sizes and there are at least 3 particles in the stream,
{ // none is a separator, we adjust *dt*.
const auto &past1 = s[s.size() - 2];
const auto &past2 = s[s.size() - 3];
if ((!past1.IsSpecial()) && (!past2.IsSpecial())) {
Expand Down Expand Up @@ -186,7 +186,7 @@ int Advection::AdvectSteps(Field *velocity, double deltaT, size_t maxSteps, ADVE
return NO_ADVECT_HAPPENED;
}

int Advection::AdvectTillTime(Field *velocity, double startT, double deltaT, double targetT, ADVECTION_METHOD method)
int Advection::AdvectTillTime(Field *velocity, double startT, double deltaT, double targetT, bool fixedStepSize, ADVECTION_METHOD method)
{
int ready = CheckReady();
if (ready != 0) return ready;
Expand Down Expand Up @@ -247,8 +247,8 @@ int Advection::AdvectTillTime(Field *velocity, double startT, double deltaT, dou
} // Finish the out-of-volume condition

double dt = deltaT;
if (s.size() > 2) // If there are at least 3 particles in the stream,
{ // we also adjust *dt*
if (!fixedStepSize && s.size() > 2)
{
double mindt = deltaT / 20.0, maxdt = deltaT * 20.0;
maxdt = glm::min(maxdt, targetT - p0.time);
const auto &past1 = s[s.size() - 2];
Expand Down
12 changes: 12 additions & 0 deletions lib/params/FlowParams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const std::string FlowParams::PhongShininessTag = "PhongShininessTag";
const std::string FlowParams::_isSteadyTag = "IsSteadyTag";
const std::string FlowParams::_velocityMultiplierTag = "VelocityMultiplierTag";
const std::string FlowParams::_firstStepSizeMultiplierTag = "FirstStepSizeMultiplierTag";
const std::string FlowParams::_fixedAdvectionStepTag= "FixedAdvectionStepTag";
const std::string FlowParams::_fixedAdvectionStepSizeTag= "FixedAdvectionStepSizeTag";
const std::string FlowParams::_steadyNumOfStepsTag = "SteadyNumOfStepsTag";
const std::string FlowParams::_seedGenModeTag = "SeedGenModeTag";
const std::string FlowParams::_seedInputFilenameTag = "SeedInputFilenameTag";
Expand Down Expand Up @@ -140,6 +142,8 @@ int FlowParams::Initialize()
SetSteadyNumOfSteps(100);
SetVelocityMultiplier(1.0);
SetFirstStepSizeMultiplier(1.0);
SetUseFixedAdvectionSteps(false);
SetFixedAdvectionStepSize(0.0);
SetPeriodic(vector<bool>(3, false));
SetGridNumOfSeeds({5, 5, 1});
SetRandomNumOfSeeds(50);
Expand Down Expand Up @@ -182,10 +186,18 @@ double FlowParams::GetVelocityMultiplier() const { return GetValueDouble(_veloci

double FlowParams::GetFirstStepSizeMultiplier() const { return GetValueDouble(_firstStepSizeMultiplierTag, 1.0); }

bool FlowParams::GetUseFixedAdvectionSteps() const { return GetValueLong(_fixedAdvectionStepTag, 0); }

double FlowParams::GetFixedAdvectionStepSize() const { return GetValueDouble(_fixedAdvectionStepSizeTag, 0.0); }

void FlowParams::SetVelocityMultiplier(double coeff) { SetValueDouble(_velocityMultiplierTag, "Field Scale Factor", coeff); }

void FlowParams::SetFirstStepSizeMultiplier(double coeff) { SetValueDouble(_firstStepSizeMultiplierTag, "first step size multiplier", coeff); }

void FlowParams::SetUseFixedAdvectionSteps(bool fixed) { SetValueLong(_fixedAdvectionStepTag, "Use Fixed Advection Steps", long(fixed)); }

void FlowParams::SetFixedAdvectionStepSize(double step) { SetValueDouble(_fixedAdvectionStepSizeTag, "Fixed Advection Step Size", step); }

long FlowParams::GetSteadyNumOfSteps() const { return GetValueLong(_steadyNumOfStepsTag, 100); }

void FlowParams::SetSteadyNumOfSteps(long i) { SetValueLong(_steadyNumOfStepsTag, "num of steps for a steady integration", i); }
Expand Down
37 changes: 28 additions & 9 deletions lib/render/FlowRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,10 @@ int FlowRenderer::_paintGL(bool fast)

if (!_advectionComplete) {
auto deltaT = _cache_deltaT;
const auto fixedSteps = params->GetUseFixedAdvectionSteps();
if (fixedSteps && params->GetFixedAdvectionStepSize() > 0.0)
deltaT = params->GetFixedAdvectionStepSize();

rv = flow::ADVECT_HAPPENED;

// Advection scheme 1: advect a maximum number of steps.
Expand All @@ -280,15 +284,16 @@ int FlowRenderer::_paintGL(bool fast)

Progress::StartIndefinite("Performing flowline calculations");
Progress::Update(0);
rv = _advection.AdvectSteps(&_velocityField, deltaT, numOfSteps);
rv = _advection.AdvectSteps(&_velocityField, deltaT, numOfSteps, fixedSteps);
_printNonZero(rv, __FILE__, __func__, __LINE__);

// If the advection is bi-directional
if (_2ndAdvection) {
Progress::Update(5);
assert(deltaT > 0.0);
auto deltaT2 = deltaT * -1.0;

rv = _2ndAdvection->AdvectSteps(&_velocityField, deltaT2, numOfSteps);
rv = _2ndAdvection->AdvectSteps(&_velocityField, deltaT2, numOfSteps, fixedSteps);
_printNonZero(rv, __FILE__, __func__, __LINE__);
}
Progress::Finish();
Expand All @@ -298,7 +303,7 @@ int FlowRenderer::_paintGL(bool fast)
// This scheme is used for unsteady flow
else {
for (int i = 1; i <= _cache_currentTS; i++) {
rv = _advection.AdvectTillTime(&_velocityField, _timestamps.at(i - 1), deltaT, _timestamps.at(i));
rv = _advection.AdvectTillTime(&_velocityField, _timestamps.at(i - 1), deltaT, _timestamps.at(i), fixedSteps);
_printNonZero(rv, __FILE__, __func__, __LINE__);
}
}
Expand Down Expand Up @@ -803,22 +808,36 @@ int FlowRenderer::_updateFlowCacheAndStates(const FlowParams *params)

// Check velocity multiplier
// If the multiplier is changed, then the entire stream is out of date
const auto velMult = params->GetVelocityMultiplier();
if (_cache_velocityMltp != velMult) {
_cache_velocityMltp = velMult;
if (_cache_velocityMltp != params->GetVelocityMultiplier()) {
_cache_velocityMltp = params->GetVelocityMultiplier();
_colorStatus = FlowStatus::SIMPLE_OUTOFDATE;
_velocityStatus = FlowStatus::SIMPLE_OUTOFDATE;
}

// Check first step size multiplier
// If the multiplier is changed, then the entire stream is out of date
const auto firstMult = params->GetFirstStepSizeMultiplier();
if (_cache_firstStepSizeMltp != firstMult) {
_cache_firstStepSizeMltp = firstMult;
if (_cache_firstStepSizeMltp != params->GetFirstStepSizeMultiplier()) {
_cache_firstStepSizeMltp = params->GetFirstStepSizeMultiplier();
_colorStatus = FlowStatus::SIMPLE_OUTOFDATE;
_velocityStatus = FlowStatus::SIMPLE_OUTOFDATE;
}

// Check if using the fixed advection steps.
// If changed, then the entire stream is out ot date.
if (_cache_useFixedAdvectionSteps != params->GetUseFixedAdvectionSteps()) {
_cache_useFixedAdvectionSteps = params->GetUseFixedAdvectionSteps();
_colorStatus = FlowStatus::SIMPLE_OUTOFDATE;
_velocityStatus = FlowStatus::SIMPLE_OUTOFDATE;
}

// Check if the fixed advection step size is out of date only when specified to use fixed steps.
if (_cache_useFixedAdvectionSteps && _cache_fixedAdvectionStepSize != params->GetFixedAdvectionStepSize()) {
_cache_fixedAdvectionStepSize = params->GetFixedAdvectionStepSize();
_colorStatus = FlowStatus::SIMPLE_OUTOFDATE;
_velocityStatus = FlowStatus::SIMPLE_OUTOFDATE;
}


// Check periodicity
// If periodicity changes along any dimension, then the entire stream is out of date
// Note: FlowParams return a vector of size either 2 or 3.
Expand Down

0 comments on commit 8ceaa4f

Please sign in to comment.