Skip to content

Commit 8520829

Browse files
authored
Merge pull request #36 from flowy-code/intermediate_dems
Intermediate dems
2 parents 3e8474b + 9c59460 commit 8520829

12 files changed

Lines changed: 86 additions & 64 deletions

flowy/include/asc_file.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ class AscFile : public TopographyFile
1212
{
1313
public:
1414
AscFile() = default;
15-
AscFile( const Topography & topography, OutputQuantitiy output )
15+
AscFile( const Topography & topography, OutputQuantity output )
1616
: TopographyFile::TopographyFile( topography, output )
1717
{
1818
}

flowy/include/config.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ class InputParams
3939
bool print_remaining_time = false;
4040
bool save_final_dem = false;
4141

42+
// If this std::optional has a value `n`, write the lava thickness (not the dem!) to a file every `n` lobes
43+
std::optional<int> write_thickness_every_n_lobes{};
44+
4245
// The tolerance in the volume ratio when finding the threshold thickness for masking
4346
double masking_tolerance = 1e-5;
4447
// The maximum number of bisection search iterations when finding the threshold thickness for masking

flowy/include/lobe.hpp

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -130,27 +130,29 @@ class Lobe
130130
const double a2 = a * a;
131131
const double b2 = b * b;
132132

133+
// Compute coefficients of quadratic equation
133134
const double alpha = 1.0 / ( a2 ) * ( diff[0] * diff[0] ) + 1.0 / b2 * ( diff[1] * diff[1] );
134135
const double beta = 2.0 * ( x1_prime[0] * diff[0] / a2 + x1_prime[1] * diff[1] / b2 );
135136
const double gamma = x1_prime[0] * x1_prime[0] / a2 + x1_prime[1] * x1_prime[1] / b2 - 1.0;
136137

137-
// The solution to this quadratic equation is
138+
// The solution to the quadratic equation is
138139
// t = (-beta +- sqrt(beta^2 - 4*alpha*gamma)) / (2*alpha)
139-
140-
// Therefore, if beta^2 - 4*alpha*gamma < 0, the line se\beta\frgment misses the ellipse
140+
// Therefore, if beta^2 - 4*alpha*gamma < 0, the line segment misses the ellipse
141141
const double radicand = beta * beta - 4 * alpha * gamma;
142142
if( radicand < 0 )
143143
return std::nullopt;
144144

145145
const double sqrt_r = std::sqrt( radicand );
146146

147-
// Else, we compute the two points of intersection and check if they fall into the interval [0, 1]
147+
// Else (if the line segment does not miss the ellipse) we compute the two points of intersection t1 and t2 and check if
148148
const double t1 = ( -beta - sqrt_r ) / ( 2.0 * alpha );
149149
const double t2 = ( -beta + sqrt_r ) / ( 2.0 * alpha );
150150

151-
// This condition determines if any of the points of the line segment lie within the lobe
152-
// This is the condition for the intersection of [0,1] and [t1, t2] to not be empty
151+
// The following condition determines if any of the points of the line segment lie within the lobe
152+
// It can be thought of as the the condition for the intersection of [0,1] and [t1,t2] to not be empty
153153
const bool condition = !( ( t1 < 0 && t2 < 0 ) || ( t1 > 1 && t2 > 1 ) );
154+
155+
// If the conditions if fulfilled, we compute the intersection points
154156
if( condition )
155157
{
156158
// We clamp t1 and t2 to the interval [0,1] in case the line segment intersects the ellipse only once
@@ -165,20 +167,22 @@ class Lobe
165167
const std::array<Vector2, 2> res = { v1 + center, v2 + center };
166168
return res;
167169
}
168-
169-
return std::nullopt;
170+
else // else we return nullopt
171+
{
172+
return std::nullopt;
173+
}
170174
}
171175

172176
// Gives a point on the perimeter of the ellipse
173177
// The angle is relative to the semi major axis angle
174-
inline Vector2 point_at_angle( const double phi ) const
178+
inline Vector2 point_at_angle( double phi ) const
175179
{
176180
return point_at_angle( std::sin( phi ), std::cos( phi ) );
177181
}
178182

179183
// Gives a point on the perimeter of the ellipse
180184
// The angle is relative to the semi major axis angle
181-
inline Vector2 point_at_angle( const double sin_phi, const double cos_phi ) const
185+
inline Vector2 point_at_angle( double sin_phi, double cos_phi ) const
182186
{
183187
const double a = semi_axes[0]; // major axis
184188
const double b = semi_axes[1]; // minor axis
@@ -187,20 +191,8 @@ class Lobe
187191
return coord + center;
188192
}
189193

190-
inline std::vector<Vector2> rasterize_perimeter( int n_raster_points ) const
191-
{
192-
VectorX phi_list = xt::linspace<double>( 0.0, 2.0 * Math::pi, n_raster_points, false );
193-
auto res = std::vector<Vector2>( n_raster_points );
194-
195-
for( int idx_phi = 0; idx_phi < n_raster_points; idx_phi++ )
196-
{
197-
res[idx_phi] = point_at_angle( phi_list[idx_phi] );
198-
}
199-
200-
return res;
201-
}
202-
203-
inline std::vector<Vector2> rasterize_perimeter( std::span<double> sin_phi, std::span<double> cos_phi ) const
194+
inline std::vector<Vector2>
195+
rasterize_perimeter( const std::span<double> sin_phi, const std::span<double> cos_phi ) const
204196
{
205197
const int n_raster_points = sin_phi.size();
206198
auto res = std::vector<Vector2>( n_raster_points );

flowy/include/models/mr_lava_loba.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ class MrLavaLoba
8080
}
8181

8282
// Calculate n_lobes
83-
int compute_n_lobes( int idx_flow )
83+
int compute_n_lobes( int idx_flow ) const
8484
{
8585
int n_lobes{};
8686
// Number of lobes in the flow is a random number between the min and max values
@@ -115,7 +115,7 @@ class MrLavaLoba
115115
}
116116

117117
// calculates the initial lobe position
118-
void compute_initial_lobe_position( int idx_flow, Lobe & lobe )
118+
void compute_initial_lobe_position( int idx_flow, Lobe & lobe ) const
119119
{
120120
std::unique_ptr<VentFlag> f{};
121121

@@ -182,15 +182,15 @@ class MrLavaLoba
182182
lobe.semi_axes = { semi_major_axis, semi_minor_axis };
183183
}
184184

185-
void compute_descendent_lobe_position( Lobe & lobe, const Lobe & parent, Vector2 final_budding_point )
185+
void compute_descendent_lobe_position( Lobe & lobe, const Lobe & parent, const Vector2 & final_budding_point ) const
186186
{
187187
Vector2 direction_to_new_lobe
188188
= ( final_budding_point - parent.center ) / xt::linalg::norm( final_budding_point - parent.center );
189189
Vector2 new_lobe_center = final_budding_point + input.dist_fact * direction_to_new_lobe * lobe.semi_axes[0];
190190
lobe.center = new_lobe_center;
191191
}
192192

193-
void perturb_lobe_angle( Lobe & lobe, double slope )
193+
void perturb_lobe_angle( Lobe & lobe, double slope ) const
194194
{
195195
const double slope_deg = 180.0 / Math::pi * std::atan( slope );
196196

@@ -216,7 +216,7 @@ class MrLavaLoba
216216
}
217217

218218
// Select which lobe amongst the existing lobes will be the parent for the new descendent lobe
219-
int select_parent_lobe( int idx_descendant, std::vector<Lobe> & lobes )
219+
int select_parent_lobe( int idx_descendant, std::vector<Lobe> & lobes ) const
220220
{
221221
Lobe & lobe_descendent = lobes[idx_descendant];
222222

flowy/include/netcdf_file.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class NetCDFFile : public TopographyFile
2424

2525
StorageDataType data_type = StorageDataType::Short;
2626
NetCDFFile() = default;
27-
NetCDFFile( const Topography & topography, OutputQuantitiy output )
27+
NetCDFFile( const Topography & topography, OutputQuantity output )
2828
: TopographyFile::TopographyFile( topography, output )
2929
{
3030
}

flowy/include/simulation.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,14 @@ class Simulation
3939

4040
void write_avg_thickness_file();
4141

42+
// Check if the dem has to be written (because of the input.write_dem_every_n_lobes_setting) and, if yes, writes the topography
43+
void write_thickness_if_necessary(int n_lobes_processed);
44+
45+
// Computes the topography_thickness field by substacting the initial topography and dividing by (1.0 - filling_parameter)
46+
void compute_topography_thickness();
47+
4248
std::unique_ptr<TopographyFile>
43-
get_file_handle( const Topography & topography, OutputQuantitiy output_quantity ) const;
49+
get_file_handle( const Topography & topography, OutputQuantity output_quantity ) const;
4450

4551
void run();
4652

flowy/include/topography_file.hpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ struct TopographyCrop
1919
double y_max;
2020
};
2121

22-
enum class OutputQuantitiy
22+
enum class OutputQuantity
2323
{
2424
Hazard,
2525
Height
@@ -51,14 +51,14 @@ class TopographyFile
5151
TopographyFile() = default;
5252

5353
// Constructor that takes topography
54-
TopographyFile( const Topography & topography, OutputQuantitiy output )
54+
TopographyFile( const Topography & topography, OutputQuantity output )
5555
: x_data( topography.x_data ), y_data( topography.y_data ), no_data_value( topography.no_data_value )
5656
{
57-
if( output == OutputQuantitiy::Height )
57+
if( output == OutputQuantity::Height )
5858
{
5959
data = topography.height_data;
6060
}
61-
else if( output == OutputQuantitiy::Hazard )
61+
else if( output == OutputQuantity::Hazard )
6262
{
6363
data = topography.hazard;
6464
}

src/config_parser.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ InputParams parse_config( const std::filesystem::path & path )
5252
set_if_specified( params.write_lobes_csv, tbl["write_lobes_csv"] );
5353
set_if_specified( params.print_remaining_time, tbl["print_remaining_time"] );
5454
set_if_specified( params.save_final_dem, tbl["save_final_dem"] );
55+
params.write_thickness_every_n_lobes = tbl["write_thickness_every_n_lobes"].value<int>();
5556

5657
std::optional<std::string> output_folder_string{};
5758
output_folder_string = tbl["output_folder"].value<std::string>();
@@ -270,6 +271,11 @@ void validate_settings( const InputParams & options )
270271
"Allowed values of the vent_flag are 0 to 8, inclusive." );
271272

272273
// Output settings validation
274+
if( options.write_thickness_every_n_lobes.has_value() )
275+
{
276+
check( name_and_var( options.write_thickness_every_n_lobes.value() ), g_zero );
277+
}
278+
273279
check(
274280
name_and_var( options.output_settings.compression_level ), []( auto x ) { return x >= 0 && x <= 9; },
275281
"The compression level can only be between 0 and 9, inclusive." );

src/simulation.cpp

Lines changed: 37 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -296,13 +296,13 @@ void Simulation::write_avg_thickness_file()
296296
xt::filter( topography_masked.hazard, topography_thickness.height_data < threshold_thickness ) = 0.0;
297297

298298
// Write the masked thickness and the masked hazard maps
299-
auto file_thick = get_file_handle( topography_masked, OutputQuantitiy::Height );
299+
auto file_thick = get_file_handle( topography_masked, OutputQuantity::Height );
300300
file_thick->save(
301301
input.output_folder / fmt::format( "{}_thickness_masked_{:.2f}", input.run_name, threshold ) );
302302

303303
if( input.save_hazard_data )
304304
{
305-
auto file_hazard = get_file_handle( topography_masked, OutputQuantitiy::Hazard );
305+
auto file_hazard = get_file_handle( topography_masked, OutputQuantity::Hazard );
306306
file_hazard->save(
307307
input.output_folder / fmt::format( "{}_hazard_masked_{:.2f}", input.run_name, threshold ) );
308308
}
@@ -311,7 +311,7 @@ void Simulation::write_avg_thickness_file()
311311
}
312312

313313
std::unique_ptr<TopographyFile>
314-
Simulation::get_file_handle( const Topography & topography, OutputQuantitiy output_quantity ) const
314+
Simulation::get_file_handle( const Topography & topography, OutputQuantity output_quantity ) const
315315
{
316316
std::unique_ptr<TopographyFile> res{};
317317

@@ -343,6 +343,33 @@ Simulation::get_file_handle( const Topography & topography, OutputQuantitiy outp
343343
return res;
344344
}
345345

346+
void Simulation::compute_topography_thickness()
347+
{
348+
// Compute the thickness by substracting the initial topography and correcting for the thickening parametr
349+
topography_thickness = topography;
350+
topography_thickness.no_data_value = DEFAULT_NO_DATA_VALUE_THICKNESS;
351+
topography_thickness.height_data -= topography_initial.height_data;
352+
topography_thickness.height_data /= ( 1.0 - input.thickening_parameter );
353+
}
354+
355+
void Simulation::write_thickness_if_necessary( int n_lobes_processed )
356+
{
357+
// If the optional does not have a value, we simply return without doing anything
358+
if( !input.write_thickness_every_n_lobes.has_value() )
359+
{
360+
return;
361+
}
362+
363+
// Else we check if we have to write a dem file according to our setting
364+
if( n_lobes_processed % input.write_thickness_every_n_lobes.value() == 0 )
365+
{
366+
compute_topography_thickness();
367+
auto file_thick = get_file_handle( topography_thickness, OutputQuantity::Height );
368+
file_thick->save(
369+
input.output_folder / fmt::format( "{}_thickness_after_{}_lobes", input.run_name, n_lobes_processed ) );
370+
}
371+
}
372+
346373
void Simulation::run()
347374
{
348375
// Initialize MrLavaLoba method
@@ -394,6 +421,7 @@ void Simulation::run()
394421
// Add rasterized lobe
395422
topography.add_lobe( lobe_cur, input.volume_correction, idx_lobe );
396423
n_lobes_processed++;
424+
write_thickness_if_necessary( n_lobes_processed );
397425
}
398426

399427
// Loop over the rest of the lobes (skipping the initial ones).
@@ -464,6 +492,7 @@ void Simulation::run()
464492
// Add rasterized lobe
465493
topography.add_lobe( lobe_cur, input.volume_correction, idx_lobe );
466494
n_lobes_processed++;
495+
write_thickness_if_necessary( n_lobes_processed );
467496
}
468497

469498
if( input.save_hazard_data )
@@ -501,29 +530,25 @@ void Simulation::run()
501530
fmt::print( "Used RNG seed: {}\n", rng_seed );
502531

503532
// Save initial topography to asc file
504-
auto file_initial = get_file_handle( topography_initial, OutputQuantitiy::Height );
533+
auto file_initial = get_file_handle( topography_initial, OutputQuantity::Height );
505534
file_initial->save( input.output_folder / fmt::format( "{}_DEM", input.run_name ) );
506535

507536
// Save final topography to asc file
508537
if( input.save_final_dem )
509538
{
510-
auto file_final = get_file_handle( topography, OutputQuantitiy::Height );
539+
auto file_final = get_file_handle( topography, OutputQuantity::Height );
511540
file_final->save( input.output_folder / fmt::format( "{}_DEM_final", input.run_name ) );
512541
}
513542

514543
// Save full thickness to asc file
515-
topography_thickness = topography;
516-
topography_thickness.no_data_value = DEFAULT_NO_DATA_VALUE_THICKNESS;
517-
topography_thickness.height_data -= topography_initial.height_data;
518-
topography_thickness.height_data /= ( 1.0 - input.thickening_parameter );
519-
520-
auto file_thick = get_file_handle( topography_thickness, OutputQuantitiy::Height );
544+
compute_topography_thickness();
545+
auto file_thick = get_file_handle( topography_thickness, OutputQuantity::Height );
521546
file_thick->save( input.output_folder / fmt::format( "{}_thickness_full", input.run_name ) );
522547

523548
// Save the full hazard map
524549
if( input.save_hazard_data )
525550
{
526-
auto file_hazard = get_file_handle( topography, OutputQuantitiy::Hazard );
551+
auto file_hazard = get_file_handle( topography, OutputQuantity::Hazard );
527552
file_hazard->save( input.output_folder / fmt::format( "{}_hazard_full", input.run_name ) );
528553
}
529554

src/topography.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -516,11 +516,8 @@ Vector2 Topography::find_preliminary_budding_point( const Lobe & lobe, size_t np
516516
// First, we rasterize the perimeter of the ellipse
517517
const auto sin = std::span<double>( sin_phi_lobe_perimeter->begin(), sin_phi_lobe_perimeter->end() );
518518
const auto cos = std::span<double>( cos_phi_lobe_perimeter->begin(), cos_phi_lobe_perimeter->end() );
519-
520519
std::vector<Vector2> perimeter = lobe.rasterize_perimeter( sin, cos );
521520

522-
// std::vector<Vector2> perimeter = lobe.rasterize_perimeter( npoints );
523-
524521
// Then, we find the point of minimal elevation amongst the rasterized points on the perimeter
525522
auto min_elevation_point_it = std::min_element(
526523
perimeter.begin(), perimeter.end(), [&]( const Vector2 & p1, const Vector2 & p2 )

0 commit comments

Comments
 (0)