Skip to content

Commit 243487d

Browse files
committed
ENH: Turned the MrLavaLoba class into a namespace
1 parent 5a487ae commit 243487d

2 files changed

Lines changed: 163 additions & 175 deletions

File tree

flowy/include/models/mr_lava_loba.hpp

Lines changed: 163 additions & 173 deletions
Original file line numberDiff line numberDiff line change
@@ -63,214 +63,204 @@ class CommonLobeDimensions
6363
double exp_lobe_exponent = 1;
6464
};
6565

66-
class MrLavaLoba
66+
namespace MrLavaLoba
6767
{
68-
public:
69-
CommonLobeDimensions lobe_dimensions;
70-
Config::InputParams input;
71-
72-
MrLavaLoba( const Config::InputParams & input, std::mt19937 & gen )
73-
: lobe_dimensions( input ), input( input ), gen( gen )
68+
// Calculate n_lobes
69+
inline int compute_n_lobes( int idx_flow, const Config::InputParams & input, std::mt19937 & gen )
70+
{
71+
int n_lobes{};
72+
// Number of lobes in the flow is a random number between the min and max values
73+
if( input.a_beta == 0 && input.b_beta == 0 )
7474
{
75+
std::uniform_int_distribution<> dist_num_lobes( input.min_n_lobes, input.max_n_lobes );
76+
n_lobes = dist_num_lobes( gen );
7577
}
76-
77-
explicit MrLavaLoba( Simulation & simulation )
78-
: lobe_dimensions( simulation.input ), input( simulation.input ), gen( simulation.gen )
78+
// Deterministic number of lobes, such that a beta probability density distribution is used (not a beta
79+
// distribution). However this means that n_lobes could potentially be greater than min_n_lobes
80+
else
7981
{
82+
const double x_beta = ( 1.0 * idx_flow ) / ( input.n_flows - 1.0 );
83+
const double random_number = Math::beta_pdf( x_beta, input.a_beta, input.b_beta );
84+
n_lobes
85+
= int( std::round( input.min_n_lobes + 0.5 * ( input.max_n_lobes - input.min_n_lobes ) * random_number ) );
8086
}
87+
return n_lobes;
88+
}
8189

82-
// Calculate n_lobes
83-
int compute_n_lobes( int idx_flow ) const
84-
{
85-
int n_lobes{};
86-
// Number of lobes in the flow is a random number between the min and max values
87-
if( input.a_beta == 0 && input.b_beta == 0 )
88-
{
89-
std::uniform_int_distribution<> dist_num_lobes( input.min_n_lobes, input.max_n_lobes );
90-
n_lobes = dist_num_lobes( gen );
91-
}
92-
// Deterministic number of lobes, such that a beta probability density distribution is used (not a beta
93-
// distribution). However this means that n_lobes could potentially be greater than min_n_lobes
94-
else
95-
{
96-
double x_beta = ( 1.0 * idx_flow ) / ( input.n_flows - 1.0 );
97-
double random_number = Math::beta_pdf( x_beta, input.a_beta, input.b_beta );
98-
n_lobes = int(
99-
std::round( input.min_n_lobes + 0.5 * ( input.max_n_lobes - input.min_n_lobes ) * random_number ) );
100-
}
101-
return n_lobes;
102-
}
90+
// Calculate the current thickness of a lobe
91+
inline double compute_current_lobe_thickness(
92+
int idx_lobe, int n_lobes, const Config::InputParams & input, CommonLobeDimensions & lobe_dimensions )
93+
{
94+
const double delta_lobe_thickness
95+
= 2.0 * ( lobe_dimensions.avg_lobe_thickness - lobe_dimensions.thickness_min ) / ( n_lobes - 1.0 );
10396

104-
// Calculate the current thickness of a lobe
105-
double compute_current_lobe_thickness( int idx_lobe, int n_lobes ) const
106-
{
107-
double delta_lobe_thickness
108-
= 2.0 * ( lobe_dimensions.avg_lobe_thickness - lobe_dimensions.thickness_min ) / ( n_lobes - 1.0 );
97+
// Calculated for each flow with n_lobes number of lobes
98+
FLOWY_CHECK( delta_lobe_thickness );
10999

110-
// Calculated for each flow with n_lobes number of lobes
111-
FLOWY_CHECK( delta_lobe_thickness );
100+
return ( 1.0 - input.thickening_parameter ) * ( lobe_dimensions.thickness_min + idx_lobe * delta_lobe_thickness );
101+
}
112102

113-
return ( 1.0 - input.thickening_parameter )
114-
* ( lobe_dimensions.thickness_min + idx_lobe * delta_lobe_thickness );
115-
}
103+
// calculates the initial lobe position
104+
inline void
105+
compute_initial_lobe_position( int idx_flow, Lobe & lobe, const Config::InputParams & input, std::mt19937 & gen )
106+
{
107+
std::unique_ptr<VentFlag> f{};
116108

117-
// calculates the initial lobe position
118-
void compute_initial_lobe_position( int idx_flow, Lobe & lobe ) const
109+
// Initial lobes are on the vent and flow starts from the first vent, second vent and so on
110+
if( input.vent_flag == 0 )
119111
{
120-
std::unique_ptr<VentFlag> f{};
121-
122-
// Initial lobes are on the vent and flow starts from the first vent, second vent and so on
123-
if( input.vent_flag == 0 )
124-
{
125-
f = std::make_unique<VentFlag0>( idx_flow, input.n_flows, input.vent_coordinates, gen );
126-
}
127-
else if( input.vent_flag == 1 )
128-
{
129-
f = std::make_unique<VentFlag1>(
130-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
131-
}
132-
else if( input.vent_flag == 2 )
133-
{
134-
f = std::make_unique<VentFlag2>(
135-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
136-
}
137-
else if( input.vent_flag == 3 )
138-
{
139-
f = std::make_unique<VentFlag3>(
140-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
141-
}
142-
else if( input.vent_flag == 4 )
143-
{
144-
f = std::make_unique<VentFlag4>(
145-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
146-
}
147-
else if( input.vent_flag == 5 )
148-
{
149-
f = std::make_unique<VentFlag5>(
150-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
151-
}
152-
else if( input.vent_flag == 6 )
153-
{
154-
f = std::make_unique<VentFlag6>(
155-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
156-
}
157-
else if( input.vent_flag == 7 )
158-
{
159-
f = std::make_unique<VentFlag7>(
160-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
161-
}
162-
else if( input.vent_flag == 8 )
163-
{
164-
f = std::make_unique<VentFlag8>(
165-
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
166-
}
167-
168-
lobe.center = f->get_position();
112+
f = std::make_unique<VentFlag0>( idx_flow, input.n_flows, input.vent_coordinates, gen );
169113
}
170-
171-
// perturbes the initial azimuthal angle of the lobe, which is
172-
// computed from the terrain slope
173-
void compute_lobe_axes( Lobe & lobe, double slope ) const
114+
else if( input.vent_flag == 1 )
174115
{
175-
// Factor for the lobe eccentricity
176-
double aspect_ratio = std::min( input.max_aspect_ratio, 1.0 + input.aspect_ratio_coeff * slope );
177-
178-
// Compute the semi-axes of the lobe
179-
double semi_major_axis = std::sqrt( lobe_dimensions.lobe_area / Math::pi ) * std::sqrt( aspect_ratio );
180-
double semi_minor_axis = std::sqrt( lobe_dimensions.lobe_area / Math::pi ) / std::sqrt( aspect_ratio );
181-
// Set the semi-axes
182-
lobe.semi_axes = { semi_major_axis, semi_minor_axis };
116+
f = std::make_unique<VentFlag1>(
117+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
183118
}
184-
185-
void compute_descendent_lobe_position( Lobe & lobe, const Lobe & parent, const Vector2 & final_budding_point ) const
119+
else if( input.vent_flag == 2 )
186120
{
187-
Vector2 direction_to_new_lobe
188-
= ( final_budding_point - parent.center ) / xt::linalg::norm( final_budding_point - parent.center );
189-
Vector2 new_lobe_center = final_budding_point + input.dist_fact * direction_to_new_lobe * lobe.semi_axes[0];
190-
lobe.center = new_lobe_center;
121+
f = std::make_unique<VentFlag2>(
122+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
191123
}
192-
193-
void perturb_lobe_angle( Lobe & lobe, double slope ) const
124+
else if( input.vent_flag == 3 )
194125
{
195-
const double slope_deg = 180.0 / Math::pi * std::atan( slope );
196-
197-
if( input.max_slope_prob < 1 )
198-
{
199-
if( slope_deg > 0.0 && input.max_slope_prob > 0 )
200-
{
201-
// Since we use radians instead of degrees, max_slope_prob has to be rescaled accordingly
202-
const double sigma = ( 1.0 - input.max_slope_prob ) / input.max_slope_prob * ( 90.0 - slope_deg )
203-
/ slope_deg * Math::pi / 180.0;
204-
205-
ProbabilityDist::truncated_normal_distribution<double> dist_truncated( 0, sigma, -Math::pi, Math::pi );
206-
const double angle_perturbation = dist_truncated( gen );
207-
lobe.set_azimuthal_angle( lobe.get_azimuthal_angle() + angle_perturbation );
208-
}
209-
else
210-
{
211-
std::uniform_real_distribution<double> dist_uniform( -Math::pi / 2, Math::pi / 2 );
212-
const double angle_perturbation = dist_uniform( gen );
213-
lobe.set_azimuthal_angle( lobe.get_azimuthal_angle() + angle_perturbation );
214-
}
215-
}
126+
f = std::make_unique<VentFlag3>(
127+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
216128
}
217-
218-
// 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 ) const
129+
else if( input.vent_flag == 4 )
130+
{
131+
f = std::make_unique<VentFlag4>(
132+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
133+
}
134+
else if( input.vent_flag == 5 )
135+
{
136+
f = std::make_unique<VentFlag5>(
137+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
138+
}
139+
else if( input.vent_flag == 6 )
140+
{
141+
f = std::make_unique<VentFlag6>(
142+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
143+
}
144+
else if( input.vent_flag == 7 )
220145
{
221-
Lobe & lobe_descendent = lobes[idx_descendant];
146+
f = std::make_unique<VentFlag7>(
147+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
148+
}
149+
else if( input.vent_flag == 8 )
150+
{
151+
f = std::make_unique<VentFlag8>(
152+
input.vent_coordinates, input.fissure_probabilities, input.fissure_end_coordinates, gen );
153+
}
222154

223-
int idx_parent{};
155+
lobe.center = f->get_position();
156+
}
224157

225-
// Generate from the last lobe
226-
if( input.lobe_exponent <= 0 )
227-
{
228-
idx_parent = idx_descendant - 1;
229-
}
230-
else if( input.lobe_exponent >= 1 ) // Draw from a uniform random distribution if exponent is 1
158+
// perturbes the initial azimuthal angle of the lobe, which is
159+
// computed from the terrain slope
160+
inline void compute_lobe_axes(
161+
Lobe & lobe, double slope, const Config::InputParams & input, CommonLobeDimensions & lobe_dimensions )
162+
{
163+
// Factor for the lobe eccentricity
164+
const double aspect_ratio = std::min( input.max_aspect_ratio, 1.0 + input.aspect_ratio_coeff * slope );
165+
166+
// Compute the semi-axes of the lobe
167+
const double semi_major_axis = std::sqrt( lobe_dimensions.lobe_area / Math::pi ) * std::sqrt( aspect_ratio );
168+
const double semi_minor_axis = std::sqrt( lobe_dimensions.lobe_area / Math::pi ) / std::sqrt( aspect_ratio );
169+
// Set the semi-axes
170+
lobe.semi_axes = { semi_major_axis, semi_minor_axis };
171+
}
172+
173+
inline void compute_descendent_lobe_position(
174+
Lobe & lobe, const Lobe & parent, const Vector2 & final_budding_point, const Config::InputParams & input )
175+
{
176+
const Vector2 direction_to_new_lobe
177+
= ( final_budding_point - parent.center ) / xt::linalg::norm( final_budding_point - parent.center );
178+
const Vector2 new_lobe_center = final_budding_point + input.dist_fact * direction_to_new_lobe * lobe.semi_axes[0];
179+
lobe.center = new_lobe_center;
180+
}
181+
182+
inline void perturb_lobe_angle( Lobe & lobe, double slope, const Config::InputParams & input, std::mt19937 & gen )
183+
{
184+
const double slope_deg = 180.0 / Math::pi * std::atan( slope );
185+
186+
if( input.max_slope_prob < 1 )
187+
{
188+
if( slope_deg > 0.0 && input.max_slope_prob > 0 )
231189
{
232-
std::uniform_int_distribution<int> dist_int( 0, idx_descendant - 1 );
233-
idx_parent = dist_int( gen );
190+
// Since we use radians instead of degrees, max_slope_prob has to be rescaled accordingly
191+
const double sigma = ( 1.0 - input.max_slope_prob ) / input.max_slope_prob * ( 90.0 - slope_deg )
192+
/ slope_deg * Math::pi / 180.0;
193+
194+
ProbabilityDist::truncated_normal_distribution<double> dist_truncated( 0, sigma, -Math::pi, Math::pi );
195+
const double angle_perturbation = dist_truncated( gen );
196+
lobe.set_azimuthal_angle( lobe.get_azimuthal_angle() + angle_perturbation );
234197
}
235198
else
236199
{
237-
std::uniform_real_distribution<double> dist( 0, 1 );
238-
const double idx0 = dist( gen );
239-
const auto idx1 = std::pow( idx0, input.lobe_exponent );
240-
idx_parent = idx_descendant * idx1;
200+
std::uniform_real_distribution<double> dist_uniform( -Math::pi / 2, Math::pi / 2 );
201+
const double angle_perturbation = dist_uniform( gen );
202+
lobe.set_azimuthal_angle( lobe.get_azimuthal_angle() + angle_perturbation );
241203
}
204+
}
205+
}
206+
207+
// Select which lobe amongst the existing lobes will be the parent for the new descendent lobe
208+
inline int select_parent_lobe(
209+
int idx_descendant, std::vector<Lobe> & lobes, const Config::InputParams & input,
210+
CommonLobeDimensions & lobe_dimensions, std::mt19937 & gen )
211+
{
212+
Lobe & lobe_descendent = lobes[idx_descendant];
242213

243-
// Update the lobe information
244-
lobe_descendent.idx_parent = idx_parent;
245-
lobe_descendent.dist_n_lobes = lobes[idx_parent].dist_n_lobes + 1;
246-
lobe_descendent.parent_weight *= lobe_dimensions.exp_lobe_exponent;
214+
int idx_parent{};
247215

248-
return idx_parent;
216+
// Generate from the last lobe
217+
if( input.lobe_exponent <= 0 )
218+
{
219+
idx_parent = idx_descendant - 1;
249220
}
250-
251-
void add_inertial_contribution( Lobe & lobe, const Lobe & parent, double slope ) const
221+
else if( input.lobe_exponent >= 1 ) // Draw from a uniform random distribution if exponent is 1
222+
{
223+
std::uniform_int_distribution<int> dist_int( 0, idx_descendant - 1 );
224+
idx_parent = dist_int( gen );
225+
}
226+
else
252227
{
253-
double cos_angle_parent = parent.get_cos_azimuthal_angle();
254-
double sin_angle_parent = parent.get_sin_azimuthal_angle();
255-
double cos_angle_lobe = lobe.get_cos_azimuthal_angle();
256-
double sin_angle_lobe = lobe.get_sin_azimuthal_angle();
228+
std::uniform_real_distribution<double> dist( 0, 1 );
229+
const double idx0 = dist( gen );
230+
const auto idx1 = std::pow( idx0, input.lobe_exponent );
231+
idx_parent = idx_descendant * idx1;
232+
}
257233

258-
double alpha_inertial = 0.0;
234+
// Update the lobe information
235+
lobe_descendent.idx_parent = idx_parent;
236+
lobe_descendent.dist_n_lobes = lobes[idx_parent].dist_n_lobes + 1;
237+
lobe_descendent.parent_weight *= lobe_dimensions.exp_lobe_exponent;
259238

260-
const double eta = input.inertial_exponent;
261-
if( eta > 0 )
262-
{
263-
alpha_inertial = std::pow( ( 1.0 - std::pow( 2.0 * std::atan( slope ) / Math::pi, eta ) ), ( 1.0 / eta ) );
264-
}
239+
return idx_parent;
240+
}
241+
242+
inline void
243+
add_inertial_contribution( Lobe & lobe, const Lobe & parent, double slope, const Config::InputParams & input )
244+
{
245+
const double cos_angle_parent = parent.get_cos_azimuthal_angle();
246+
const double sin_angle_parent = parent.get_sin_azimuthal_angle();
247+
const double cos_angle_lobe = lobe.get_cos_azimuthal_angle();
248+
const double sin_angle_lobe = lobe.get_sin_azimuthal_angle();
265249

266-
const double x_avg = ( 1.0 - alpha_inertial ) * cos_angle_lobe + alpha_inertial * cos_angle_parent;
267-
const double y_avg = ( 1.0 - alpha_inertial ) * sin_angle_lobe + alpha_inertial * sin_angle_parent;
250+
double alpha_inertial = 0.0;
268251

269-
lobe.set_azimuthal_angle( std::atan2( y_avg, x_avg ) );
252+
const double eta = input.inertial_exponent;
253+
if( eta > 0 )
254+
{
255+
alpha_inertial = std::pow( ( 1.0 - std::pow( 2.0 * std::atan( slope ) / Math::pi, eta ) ), ( 1.0 / eta ) );
270256
}
271257

272-
private:
273-
std::mt19937 & gen;
274-
};
258+
const double x_avg = ( 1.0 - alpha_inertial ) * cos_angle_lobe + alpha_inertial * cos_angle_parent;
259+
const double y_avg = ( 1.0 - alpha_inertial ) * sin_angle_lobe + alpha_inertial * sin_angle_parent;
260+
261+
lobe.set_azimuthal_angle( std::atan2( y_avg, x_avg ) );
262+
}
263+
264+
} // namespace MrLavaLoba
275265

276266
} // namespace Flowy

flowy/include/simulation.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414

1515
namespace Flowy
1616
{
17-
class MrLavaLoba;
1817

1918
class Simulation
2019
{
2120
public:
22-
friend class MrLavaLoba;
2321
Simulation( const Config::InputParams & input, std::optional<int> rng_seed );
2422

2523
Config::InputParams input;

0 commit comments

Comments
 (0)