Skip to content

Commit 54f4537

Browse files
Simulation: Started to write steps function (WIP)
Co-authored-by: Amrita Goswami <amrita16thaug646@gmail.com>
1 parent fa50560 commit 54f4537

2 files changed

Lines changed: 219 additions & 0 deletions

File tree

flowy/include/simulation.hpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,39 @@
77
#include "flowy/include/lobe.hpp"
88
#include "flowy/include/topography.hpp"
99
#include "flowy/include/topography_file.hpp"
10+
#include <chrono>
1011
#include <filesystem>
1112
#include <memory>
13+
#include <optional>
1214
#include <random>
1315
#include <vector>
1416

1517
namespace Flowy
1618
{
1719

20+
/**
21+
* @brief Track the current state of the Simulation run
22+
*
23+
*/
24+
struct SimulationState
25+
{
26+
int n_lobes_processed = 0;
27+
std::chrono::time_point<std::chrono::system_clock> t_run_start{};
28+
int n_lobes{};
29+
std::vector<Lobe> lobes{};
30+
31+
int step = 0;
32+
int idx_flow = 0;
33+
int idx_lobe = 0;
34+
int n_lobes_current_flow = 0;
35+
};
36+
37+
enum class RunStatus
38+
{
39+
Finished,
40+
Ongoing
41+
};
42+
1843
class Simulation
1944
{
2045
public:
@@ -51,9 +76,13 @@ class Simulation
5176

5277
void run();
5378

79+
// Perform `n_steps` steps of the simulation (per step, a single lobe is added to the topography)
80+
RunStatus steps( int n_steps );
81+
5482
private:
5583
int rng_seed;
5684
std::mt19937 gen{};
85+
std::optional<SimulationState> simulation_state = std::nullopt;
5786
};
5887

5988
} // namespace Flowy

src/simulation.cpp

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,196 @@ void Simulation::save_post_run_output()
397397
write_avg_thickness_file();
398398
}
399399

400+
RunStatus Simulation::steps( int n_steps )
401+
{
402+
RunStatus run_status = RunStatus::Ongoing;
403+
404+
// If the simulation state has no value, we initialize a new simulation
405+
if( !simulation_state.has_value() )
406+
{
407+
simulation_state = SimulationState();
408+
simulation_state->t_run_start = std::chrono::high_resolution_clock::now();
409+
}
410+
auto common_lobe_dimensions = CommonLobeDimensions( input );
411+
412+
// Define some aliases for convenience
413+
auto & lobes = simulation_state->lobes;
414+
auto & idx_flow = simulation_state->idx_flow;
415+
auto & idx_lobe = simulation_state->idx_lobe;
416+
auto & n_lobes_processed = simulation_state->n_lobes_processed;
417+
auto & n_lobes = simulation_state->n_lobes;
418+
419+
// Now we have to figure out the value of idx_flow and if we are past n_init or not
420+
const int step_initial = simulation_state->step;
421+
422+
for( int step = step_initial; step < step_initial + n_steps; step++ )
423+
{
424+
bool is_first_step_of_new_flow = {}; // TODO: figure this out
425+
bool is_last_step_of_flow = {};
426+
bool is_an_initial_lobe = {};
427+
bool is_last_step = {};
428+
429+
if( is_first_step_of_new_flow )
430+
{
431+
// simulation_state->idx_flow++;
432+
simulation_state->n_lobes_current_flow
433+
= MrLavaLoba::compute_n_lobes( simulation_state->idx_flow, input, gen );
434+
simulation_state->lobes = std::vector<Lobe>{};
435+
simulation_state->lobes.reserve( simulation_state->n_lobes_current_flow );
436+
// set the intersection cache
437+
topography.reset_intersection_cache( simulation_state->n_lobes_current_flow );
438+
439+
// set idx_lobe to zero, because we are at the beginning of a flow
440+
idx_lobe = 0;
441+
}
442+
443+
if( is_an_initial_lobe )
444+
{
445+
lobes.emplace_back();
446+
Lobe & lobe_cur = lobes.back();
447+
448+
MrLavaLoba::compute_initial_lobe_position( idx_flow, lobe_cur, input, gen );
449+
450+
// Compute the thickness of the lobe
451+
lobe_cur.thickness
452+
= MrLavaLoba::compute_current_lobe_thickness( idx_lobe, n_lobes, input, common_lobe_dimensions );
453+
454+
auto [height_lobe_center, slope] = topography.height_and_slope( lobe_cur.center );
455+
456+
if( height_lobe_center == topography.no_data_value )
457+
{
458+
throw std::runtime_error(
459+
"The initial lobe center has been placed on a no_data value point in the topography." );
460+
}
461+
462+
// Perturb the angle (and set it)
463+
lobe_cur.set_azimuthal_angle( std::atan2( slope[1], slope[0] ) ); // Sets the angle prior to perturbation
464+
const double slope_norm = xt::linalg::norm( slope, 2 ); // Similar to np.linalg.norm
465+
MrLavaLoba::perturb_lobe_angle( lobe_cur, slope_norm, input, gen );
466+
467+
// compute lobe axes
468+
MrLavaLoba::compute_lobe_axes( lobe_cur, slope_norm, input, common_lobe_dimensions );
469+
470+
// Add rasterized lobe
471+
topography.add_lobe( lobe_cur, input.volume_correction, idx_lobe );
472+
n_lobes_processed++;
473+
write_thickness_if_necessary( n_lobes_processed );
474+
}
475+
else
476+
{
477+
lobes.emplace_back();
478+
Lobe & lobe_cur = lobes.back();
479+
480+
// Select which of the previously created lobes is the parent lobe
481+
// from which the new descendent lobe will bud
482+
auto idx_parent = MrLavaLoba::select_parent_lobe( idx_lobe, lobes, input, common_lobe_dimensions, gen );
483+
Lobe & lobe_parent = lobes[idx_parent];
484+
485+
// stopping condition (parent lobe close the domain boundary or at a not defined z value)
486+
if( stop_condition( lobe_parent.center, lobe_parent.semi_axes[0] ) )
487+
{
488+
lobes.pop_back();
489+
run_status = RunStatus::Finished;
490+
break;
491+
}
492+
493+
// Find the preliminary budding point on the perimeter of the parent lobe (npoints is the number of raster
494+
// points on the ellipse)
495+
Flowy::Vector2 budding_point = topography.find_preliminary_budding_point( lobe_parent, input.npoints );
496+
497+
auto [height_lobe_center, slope_parent] = topography.height_and_slope( lobe_parent.center );
498+
auto [height_bp, slope_bp] = topography.height_and_slope( budding_point );
499+
500+
Vector2 diff = ( budding_point - lobe_parent.center );
501+
502+
// Perturb the angle and set it (not on the parent anymore)
503+
lobe_cur.set_azimuthal_angle( std::atan2( diff[1], diff[0] ) ); // Sets the angle prior to perturbation
504+
const double slope_parent_norm = topography.slope_between_points( lobe_parent.center, budding_point );
505+
MrLavaLoba::perturb_lobe_angle( lobe_cur, slope_parent_norm, input, gen );
506+
507+
// Add the inertial contribution
508+
MrLavaLoba::add_inertial_contribution( lobe_cur, lobe_parent, slope_parent_norm, input );
509+
510+
// Compute the final budding point
511+
// It is defined by the point on the perimeter of the parent lobe closest to the center of the new lobe
512+
auto angle_diff = lobe_parent.get_azimuthal_angle() - lobe_cur.get_azimuthal_angle();
513+
Vector2 final_budding_point = lobe_parent.point_at_angle( -angle_diff );
514+
515+
// final_budding_point = budding_point;
516+
if( stop_condition( final_budding_point, lobe_parent.semi_axes[0] ) )
517+
{
518+
lobes.pop_back();
519+
run_status = RunStatus::Finished;
520+
break;
521+
}
522+
// Get the slope at the final budding point
523+
double slope_budding_point = topography.slope_between_points( lobe_parent.center, final_budding_point );
524+
525+
// compute the new lobe axes
526+
MrLavaLoba::compute_lobe_axes( lobe_cur, slope_budding_point, input, common_lobe_dimensions );
527+
528+
// Get new lobe center
529+
MrLavaLoba::compute_descendent_lobe_position( lobe_cur, lobe_parent, final_budding_point, input );
530+
531+
if( stop_condition( lobe_cur.center, lobe_cur.semi_axes[0] ) )
532+
{
533+
lobes.pop_back();
534+
run_status = RunStatus::Finished;
535+
break;
536+
}
537+
538+
// Compute the thickness of the lobe
539+
lobe_cur.thickness
540+
= MrLavaLoba::compute_current_lobe_thickness( idx_lobe, n_lobes, input, common_lobe_dimensions );
541+
542+
// Add rasterized lobe
543+
topography.add_lobe( lobe_cur, input.volume_correction, idx_lobe );
544+
n_lobes_processed++;
545+
write_thickness_if_necessary( n_lobes_processed );
546+
}
547+
548+
if( is_last_step_of_flow )
549+
{
550+
// Increment idx_flow
551+
idx_flow++;
552+
553+
if( input.save_hazard_data )
554+
{
555+
compute_cumulative_descendents( lobes );
556+
topography.compute_hazard_flow( lobes );
557+
}
558+
559+
if( input.write_lobes_csv )
560+
{
561+
write_lobe_data_to_file( lobes, input.output_folder / fmt::format( "lobes_{}.csv", idx_flow ) );
562+
}
563+
564+
if( input.print_remaining_time )
565+
{
566+
auto t_cur = std::chrono::high_resolution_clock::now();
567+
auto remaining_time = std::chrono::duration_cast<std::chrono::milliseconds>(
568+
( input.n_flows - idx_flow - 1 ) * ( t_cur - simulation_state->t_run_start ) / ( idx_flow + 1 ) );
569+
fmt::print( " remaining_time = {:%Hh %Mm %Ss}\n", remaining_time );
570+
}
571+
}
572+
573+
if( is_last_step )
574+
{
575+
run_status = RunStatus::Finished;
576+
}
577+
578+
n_lobes_processed++;
579+
idx_lobe++;
580+
}
581+
582+
if( run_status == RunStatus::Finished )
583+
{
584+
save_post_run_output();
585+
}
586+
587+
return run_status;
588+
}
589+
400590
void Simulation::run()
401591
{
402592
int n_lobes_processed = 0;

0 commit comments

Comments
 (0)