Skip to content

Commit 004bf23

Browse files
committed
MNT: improve docstrings for parallel MonteCarlo.
1 parent 8316993 commit 004bf23

File tree

2 files changed

+89
-25
lines changed

2 files changed

+89
-25
lines changed

rocketpy/simulation/monte_carlo.py

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import warnings
2020
from copy import deepcopy
2121
from pathlib import Path
22-
from time import process_time, time
22+
from time import time
2323

2424
import numpy as np
2525
import simplekml
@@ -279,7 +279,7 @@ def __run_in_serial(self):
279279
-------
280280
None
281281
"""
282-
sim_monitor = SimMonitor(
282+
sim_monitor = _SimMonitor(
283283
initial_count=self._initial_sim_idx,
284284
n_simulations=self.number_of_simulations,
285285
start_time=time(),
@@ -346,7 +346,7 @@ def __run_in_parallel(self, n_workers=None):
346346
mutex = manager.Lock()
347347
consumer_stop_event = manager.Event()
348348

349-
sim_monitor = manager.SimMonitor(
349+
sim_monitor = manager._SimMonitor(
350350
initial_count=self._initial_sim_idx,
351351
n_simulations=self.number_of_simulations,
352352
start_time=time(),
@@ -411,9 +411,34 @@ def __sim_producer(
411411
mutex,
412412
seed,
413413
):
414+
"""Simulation producer to be used in parallel by multiprocessing.
415+
416+
Parameters
417+
----------
418+
sto_env : StochasticEnvironment
419+
The stochastic environment object to be iterated over.
420+
sto_rocket : StochasticRocket
421+
The stochastic rocket object to be iterated over.
422+
sto_flight : StochasticFlight
423+
The stochastic flight object to be iterated over.
424+
sim_monitor : _SimMonitor
425+
The simulation monitor object to keep track of the simulations.
426+
export_list : list
427+
The list of variables to export at each simulation.
428+
export_sample_time : float
429+
Sample time to downsample the arrays in seconds.
430+
export_queue : multiprocess.Queue
431+
The queue to export the results.
432+
error_file : str
433+
The file to write the errors.
434+
mutex : multiprocess.Lock
435+
The mutex to lock access to critical regions.
436+
seed : int
437+
The seed to set the random number generator.
438+
"""
414439
try:
415440
while sim_monitor.keep_simulating():
416-
sim_idx = sim_monitor.increment()
441+
sim_idx = sim_monitor.increment() - 1
417442

418443
sto_env._set_stochastic(seed)
419444
sto_rocket._set_stochastic(seed)
@@ -450,6 +475,23 @@ def __sim_consumer(
450475
mutex,
451476
stop_event,
452477
):
478+
"""Simulation consumer to be used in parallel by multiprocessing.
479+
It consumes the results from the queue and writes them to the files.
480+
If no results are received for 10 seconds, a TimeoutError is raised.
481+
482+
Parameters
483+
----------
484+
export_queue : multiprocess.Queue
485+
The queue to export the results.
486+
inputs_file : str
487+
The file path to write the inputs.
488+
outputs_file : str
489+
The file path to write the outputs.
490+
mutex : multiprocess.Lock
491+
The mutex to lock access to critical regions.
492+
stop_event : multiprocess.Event
493+
The event indicating that the simulations are done.
494+
"""
453495
trials = 0
454496
while not stop_event.is_set():
455497
try:
@@ -478,6 +520,23 @@ def __sim_consumer(
478520
def __run_single_simulation(
479521
sim_idx, sto_env, sto_rocket, sto_flight, export_list, export_sample_time
480522
):
523+
"""Runs a single simulation and returns the inputs and outputs.
524+
525+
Parameters
526+
----------
527+
sim_idx : int
528+
The index of the simulation.
529+
sto_env : StochasticEnvironment
530+
The stochastic environment object to be iterated over.
531+
sto_rocket : StochasticRocket
532+
The stochastic rocket object to be iterated over.
533+
sto_flight : StochasticFlight
534+
The stochastic flight object to be iterated over.
535+
export_list : list
536+
The list of variables to export at each simulation.
537+
export_sample_time : float
538+
Sample time to downsample the arrays in seconds.
539+
"""
481540
monte_carlo_flight = Flight(
482541
rocket=sto_rocket.create_object(),
483542
environment=sto_env.create_object(),
@@ -510,21 +569,6 @@ def __run_single_simulation(
510569

511570
return inputs_dict, outputs_dict
512571

513-
def __terminate_simulation(self):
514-
"""
515-
Terminates the simulation, closes the files and prints the results.
516-
517-
Returns
518-
-------
519-
None
520-
"""
521-
# resave the files on self and calculate post simulation attributes
522-
self.input_file = self.batch_path / f"{self.filename}.inputs.txt"
523-
self.output_file = self.batch_path / f"{self.filename}.outputs.txt"
524-
self.error_file = self.batch_path / f"{self.filename}.errors.txt"
525-
526-
print(f"Results saved to {self._output_file}")
527-
528572
@staticmethod
529573
def __export_flight_data(
530574
inputs_dict,
@@ -555,6 +599,21 @@ def __export_flight_data(
555599
with open(outputs_file, "a", encoding="utf-8") as file:
556600
file.write(json.dumps(outputs_dict, cls=RocketPyEncoder) + "\n")
557601

602+
def __terminate_simulation(self):
603+
"""
604+
Terminates the simulation, closes the files and prints the results.
605+
606+
Returns
607+
-------
608+
None
609+
"""
610+
# resave the files on self and calculate post simulation attributes
611+
self.input_file = self.batch_path / f"{self.filename}.inputs.txt"
612+
self.output_file = self.batch_path / f"{self.filename}.outputs.txt"
613+
self.error_file = self.batch_path / f"{self.filename}.errors.txt"
614+
615+
print(f"Results saved to {self._output_file}")
616+
558617
def __check_export_list(self, export_list):
559618
"""
560619
Checks if the export_list is valid and returns a valid list. If no
@@ -1186,7 +1245,8 @@ def prepare_export_data(obj, sample_time=0.1, remove_functions=False):
11861245

11871246

11881247
def import_multiprocess():
1189-
"""Import the necessary modules for the multiprocess module.
1248+
"""Import the necessary modules and submodules for the
1249+
multiprocess library.
11901250
11911251
Returns
11921252
-------
@@ -1217,17 +1277,21 @@ def create_multiprocess_manager(multiprocess, managers):
12171277
"""
12181278

12191279
class MonteCarloManager(managers.BaseManager):
1280+
"""Custom manager for shared objects in the Monte Carlo simulation."""
1281+
12201282
def __init__(self):
12211283
super().__init__()
12221284
self.register('Lock', multiprocess.Lock)
12231285
self.register('Queue', multiprocess.Queue)
12241286
self.register('Event', multiprocess.Event)
1225-
self.register('SimMonitor', SimMonitor)
1287+
self.register('_SimMonitor', _SimMonitor)
12261288

12271289
return MonteCarloManager()
12281290

12291291

1230-
class SimMonitor:
1292+
class _SimMonitor:
1293+
"""Class to monitor the simulation progress and display the status."""
1294+
12311295
def __init__(self, initial_count, n_simulations, start_time):
12321296
self.initial_count = initial_count
12331297
self.count = initial_count
@@ -1239,7 +1303,7 @@ def keep_simulating(self):
12391303

12401304
def increment(self):
12411305
self.count += 1
1242-
return self.count - 1
1306+
return self.count
12431307

12441308
def update_status(self, sim_idx, end="\n", flush=False):
12451309
"""Prints a message on the same line as the previous one and replaces

tests/integration/test_monte_carlo.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,12 @@ def test_monte_carlo_simulate(monte_carlo_calisto, parallel):
3030
assert str(monte_carlo_calisto.error_file.name) == "monte_carlo_test.errors.txt"
3131
assert str(monte_carlo_calisto.output_file.name) == "monte_carlo_test.outputs.txt"
3232
assert np.isclose(
33-
monte_carlo_calisto.processed_results["apogee"][0], 4711, rtol=0.15
33+
monte_carlo_calisto.processed_results["apogee"][0], 4711, rtol=0.2
3434
)
3535
assert np.isclose(
3636
monte_carlo_calisto.processed_results["impact_velocity"][0],
3737
-5.234,
38-
rtol=0.15,
38+
rtol=0.2,
3939
)
4040
os.remove("monte_carlo_test.errors.txt")
4141
os.remove("monte_carlo_test.outputs.txt")

0 commit comments

Comments
 (0)