@@ -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
0 commit comments