@@ -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+
400590void Simulation::run ()
401591{
402592 int n_lobes_processed = 0 ;
0 commit comments