Build and append the incompressible flow stages.
Appends in the order: self-advection, buoyancy, diffusion, wall, divergence, pressure, solenoidal, wall, then one advection per carried scalar. Carriers run last so they are transported by the projected velocity.
Stages added to the chain before this call keep their position ahead of it, which is where an influx stage belongs.
317{
318 FlowStages stages;
319
320 auto self = std::dynamic_pointer_cast<VolumeGridBuffer>(shared_from_this());
322
325 "setup_flow: no processing chain, call after registration");
326 return stages;
327 }
328
329 const auto require = [
this](
const std::string&
name,
const char* role) {
332 "setup_flow: no field supplied for '{}'", role);
333 return false;
334 }
337 "setup_flow: '{}' names no field on this volume, supplied as '{}'",
339 return false;
340 }
341 return true;
342 };
343
344 if (!require(config.velocity, "velocity")
345 || !require(config.divergence, "divergence")
346 || !require(config.pressure, "pressure")) {
347 return stages;
348 }
349
350 if (config.viscosity > 0.0F && !require(config.scratch, "scratch")) {
351 return stages;
352 }
353
354 stages.self_advect = std::make_shared<AdvectProcessor>(
355 config.velocity, config.velocity, "volume_advect_vector.comp.spv");
356 stages.self_advect->set_time_step(config.time_step);
357 chain->add_processor(stages.self_advect, self);
358
359 if (config.buoyancy) {
360 const auto&
b = *config.buoyancy;
361
362 if (!require(
b.temperature,
"buoyancy.temperature")
363 || !require(
b.density,
"buoyancy.density")) {
364 return stages;
365 }
366
367 stages.buoyancy = std::make_shared<BuoyancyProcessor>(
368 b.temperature,
b.density, config.velocity,
369 b.direction,
"volume_buoyancy.comp.spv");
370 stages.buoyancy->set_time_step(config.time_step);
371 stages.buoyancy->set_temperature_gain(
b.temperature_gain);
372 stages.buoyancy->set_density_gain(
b.density_gain);
373 stages.buoyancy->set_ambient(
b.ambient);
374 chain->add_processor(stages.buoyancy, self);
375 }
376
377 if (config.viscosity > 0.0F) {
378 stages.diffuse = std::make_shared<DiffuseProcessor>(
379 config.velocity, config.scratch, "volume_diffuse_vector.comp.spv");
380 stages.diffuse->set_rate(config.viscosity);
381 stages.diffuse->set_time_step(config.time_step);
382 chain->add_processor(stages.diffuse, self);
383 }
384
385 if (config.walls) {
386 stages.wall_advected = std::make_shared<WallProcessor>(
387 config.velocity, "volume_wall.comp.spv");
388 chain->add_processor(stages.wall_advected, self);
389 }
390
391 stages.divergence = std::make_shared<DivergenceProcessor>(
392 config.velocity, config.divergence, "volume_divergence.comp.spv");
393 chain->add_processor(stages.divergence, self);
394
395 stages.pressure = std::make_shared<PressureProcessor>(
396 config.divergence, config.pressure, "volume_pressure_jacobi.comp.spv");
397 stages.pressure->set_iteration_count(config.jacobi_iterations);
398 chain->add_processor(stages.pressure, self);
399
400 stages.solenoidal = std::make_shared<SolenoidalProcessor>(
401 config.pressure, config.velocity, "volume_solenoidal.comp.spv");
402 chain->add_processor(stages.solenoidal, self);
403
404 if (config.walls) {
405 stages.wall_projected = std::make_shared<WallProcessor>(
406 config.velocity, "volume_wall.comp.spv");
407 chain->add_processor(stages.wall_projected, self);
408 }
409
410 for (const auto& carried : config.carried) {
411 if (!require(carried.field, "carried")) {
412 continue;
413 }
414
415 auto advect = std::make_shared<AdvectProcessor>(
416 config.velocity, carried.field, "volume_advect_scalar.comp.spv");
417 advect->set_time_step(config.time_step);
418 advect->set_dissipation(carried.dissipation);
419 chain->add_processor(advect, self);
420
421 stages.carriers.push_back(std::move(advect));
422 }
423
425 "VolumeGridBuffer::setup_flow: {} carried, buoyancy {}, viscosity {}, walls {}",
426 stages.carriers.size(), config.buoyancy ? "on" : "off",
427 config.viscosity, config.walls ? "on" : "off");
428
429 return stages;
430}
#define MF_INFO(comp, ctx,...)
#define MF_ERROR(comp, ctx,...)
BufferProcessingChain * chain
std::shared_ptr< Buffers::BufferProcessingChain > get_processing_chain() override
Access the buffer's processing chain.
bool has_field(const std::string &name) const
Whether a field of this name was declared.
@ Init
Engine/subsystem initialization.
@ Buffers
Buffers, Managers, processors and processing chains.