19
19
import warnings
20
20
from copy import deepcopy
21
21
from pathlib import Path
22
- from time import process_time , time
22
+ from time import time
23
23
24
24
import numpy as np
25
25
import simplekml
@@ -279,7 +279,7 @@ def __run_in_serial(self):
279
279
-------
280
280
None
281
281
"""
282
- sim_monitor = SimMonitor (
282
+ sim_monitor = _SimMonitor (
283
283
initial_count = self ._initial_sim_idx ,
284
284
n_simulations = self .number_of_simulations ,
285
285
start_time = time (),
@@ -346,7 +346,7 @@ def __run_in_parallel(self, n_workers=None):
346
346
mutex = manager .Lock ()
347
347
consumer_stop_event = manager .Event ()
348
348
349
- sim_monitor = manager .SimMonitor (
349
+ sim_monitor = manager ._SimMonitor (
350
350
initial_count = self ._initial_sim_idx ,
351
351
n_simulations = self .number_of_simulations ,
352
352
start_time = time (),
@@ -411,9 +411,34 @@ def __sim_producer(
411
411
mutex ,
412
412
seed ,
413
413
):
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
+ """
414
439
try :
415
440
while sim_monitor .keep_simulating ():
416
- sim_idx = sim_monitor .increment ()
441
+ sim_idx = sim_monitor .increment () - 1
417
442
418
443
sto_env ._set_stochastic (seed )
419
444
sto_rocket ._set_stochastic (seed )
@@ -450,6 +475,23 @@ def __sim_consumer(
450
475
mutex ,
451
476
stop_event ,
452
477
):
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
+ """
453
495
trials = 0
454
496
while not stop_event .is_set ():
455
497
try :
@@ -478,6 +520,23 @@ def __sim_consumer(
478
520
def __run_single_simulation (
479
521
sim_idx , sto_env , sto_rocket , sto_flight , export_list , export_sample_time
480
522
):
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
+ """
481
540
monte_carlo_flight = Flight (
482
541
rocket = sto_rocket .create_object (),
483
542
environment = sto_env .create_object (),
@@ -510,21 +569,6 @@ def __run_single_simulation(
510
569
511
570
return inputs_dict , outputs_dict
512
571
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
-
528
572
@staticmethod
529
573
def __export_flight_data (
530
574
inputs_dict ,
@@ -555,6 +599,21 @@ def __export_flight_data(
555
599
with open (outputs_file , "a" , encoding = "utf-8" ) as file :
556
600
file .write (json .dumps (outputs_dict , cls = RocketPyEncoder ) + "\n " )
557
601
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
+
558
617
def __check_export_list (self , export_list ):
559
618
"""
560
619
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):
1186
1245
1187
1246
1188
1247
def import_multiprocess ():
1189
- """Import the necessary modules for the multiprocess module.
1248
+ """Import the necessary modules and submodules for the
1249
+ multiprocess library.
1190
1250
1191
1251
Returns
1192
1252
-------
@@ -1217,17 +1277,21 @@ def create_multiprocess_manager(multiprocess, managers):
1217
1277
"""
1218
1278
1219
1279
class MonteCarloManager (managers .BaseManager ):
1280
+ """Custom manager for shared objects in the Monte Carlo simulation."""
1281
+
1220
1282
def __init__ (self ):
1221
1283
super ().__init__ ()
1222
1284
self .register ('Lock' , multiprocess .Lock )
1223
1285
self .register ('Queue' , multiprocess .Queue )
1224
1286
self .register ('Event' , multiprocess .Event )
1225
- self .register ('SimMonitor ' , SimMonitor )
1287
+ self .register ('_SimMonitor ' , _SimMonitor )
1226
1288
1227
1289
return MonteCarloManager ()
1228
1290
1229
1291
1230
- class SimMonitor :
1292
+ class _SimMonitor :
1293
+ """Class to monitor the simulation progress and display the status."""
1294
+
1231
1295
def __init__ (self , initial_count , n_simulations , start_time ):
1232
1296
self .initial_count = initial_count
1233
1297
self .count = initial_count
@@ -1239,7 +1303,7 @@ def keep_simulating(self):
1239
1303
1240
1304
def increment (self ):
1241
1305
self .count += 1
1242
- return self .count - 1
1306
+ return self .count
1243
1307
1244
1308
def update_status (self , sim_idx , end = "\n " , flush = False ):
1245
1309
"""Prints a message on the same line as the previous one and replaces
0 commit comments