ras-commander 0.33.0__py3-none-any.whl → 0.34.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ras_commander/RasCmdr.py +163 -131
- ras_commander/RasExamples.py +96 -46
- ras_commander/RasGeo.py +27 -6
- ras_commander/RasHdf.py +248 -0
- ras_commander/RasPlan.py +391 -437
- ras_commander/RasPrj.py +396 -64
- ras_commander/RasUnsteady.py +24 -4
- ras_commander/RasUtils.py +352 -51
- ras_commander/__init__.py +4 -1
- ras_commander-0.34.0.dist-info/METADATA +263 -0
- ras_commander-0.34.0.dist-info/RECORD +15 -0
- ras_commander-0.33.0.dist-info/METADATA +0 -5
- ras_commander-0.33.0.dist-info/RECORD +0 -14
- {ras_commander-0.33.0.dist-info → ras_commander-0.34.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.33.0.dist-info → ras_commander-0.34.0.dist-info}/WHEEL +0 -0
- {ras_commander-0.33.0.dist-info → ras_commander-0.34.0.dist-info}/top_level.txt +0 -0
ras_commander/RasCmdr.py
CHANGED
@@ -12,18 +12,26 @@ from .RasPrj import ras, RasPrj, init_ras_project, get_ras_exe
|
|
12
12
|
from .RasPlan import RasPlan
|
13
13
|
from .RasGeo import RasGeo
|
14
14
|
from .RasUtils import RasUtils
|
15
|
-
import subprocess
|
16
|
-
import os
|
17
15
|
import logging
|
18
16
|
import time
|
19
|
-
import pandas as pd
|
20
|
-
from threading import Thread, Lock
|
21
17
|
import queue
|
18
|
+
from threading import Thread, Lock
|
19
|
+
from typing import Union, List, Optional, Dict
|
22
20
|
from pathlib import Path
|
23
21
|
import shutil
|
24
|
-
import
|
25
|
-
from
|
26
|
-
import
|
22
|
+
import logging
|
23
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
24
|
+
from threading import Lock, Thread
|
25
|
+
from itertools import cycle
|
26
|
+
from ras_commander.RasPrj import RasPrj # Ensure RasPrj is imported
|
27
|
+
from threading import Lock, Thread, current_thread
|
28
|
+
from concurrent.futures import ThreadPoolExecutor, as_completed
|
29
|
+
from itertools import cycle
|
30
|
+
from typing import Union, List, Optional, Dict
|
31
|
+
|
32
|
+
|
33
|
+
# Configure logging
|
34
|
+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
|
27
35
|
|
28
36
|
# TO DO:
|
29
37
|
# 1. Alternate Run Mode for compute_plan and compute_parallel: Using Powershell to execute the HEC-RAS command and hide the RAS window and all child windows.
|
@@ -75,11 +83,15 @@ class RasCmdr:
|
|
75
83
|
if dest_folder.exists():
|
76
84
|
if overwrite_dest:
|
77
85
|
shutil.rmtree(dest_folder)
|
86
|
+
logging.info(f"Destination folder '{dest_folder}' exists. Overwriting as per overwrite_dest=True.")
|
78
87
|
elif any(dest_folder.iterdir()):
|
79
|
-
|
88
|
+
error_msg = f"Destination folder '{dest_folder}' exists and is not empty. Use overwrite_dest=True to overwrite."
|
89
|
+
logging.error(error_msg)
|
90
|
+
raise ValueError(error_msg)
|
80
91
|
|
81
92
|
dest_folder.mkdir(parents=True, exist_ok=True)
|
82
93
|
shutil.copytree(ras_obj.project_folder, dest_folder, dirs_exist_ok=True)
|
94
|
+
logging.info(f"Copied project folder to destination: {dest_folder}")
|
83
95
|
|
84
96
|
compute_ras = RasPrj()
|
85
97
|
compute_ras.initialize(dest_folder, ras_obj.ras_exe_path)
|
@@ -92,29 +104,29 @@ class RasCmdr:
|
|
92
104
|
compute_plan_path = Path(plan_number) if isinstance(plan_number, (str, Path)) and Path(plan_number).is_file() else RasPlan.get_plan_path(plan_number, compute_ras)
|
93
105
|
|
94
106
|
if not compute_prj_path or not compute_plan_path:
|
95
|
-
|
107
|
+
logging.error(f"Could not find project file or plan file for plan {plan_number}")
|
96
108
|
return False
|
97
109
|
|
98
110
|
# Clear geometry preprocessor files if requested
|
99
111
|
if clear_geompre:
|
100
112
|
try:
|
101
113
|
RasGeo.clear_geompre_files(compute_plan_path, ras_object=compute_ras)
|
102
|
-
|
114
|
+
logging.info(f"Cleared geometry preprocessor files for plan: {plan_number}")
|
103
115
|
except Exception as e:
|
104
|
-
|
116
|
+
logging.error(f"Error clearing geometry preprocessor files for plan {plan_number}: {str(e)}")
|
105
117
|
|
106
118
|
# Set the number of cores if specified
|
107
119
|
if num_cores is not None:
|
108
120
|
try:
|
109
121
|
RasPlan.set_num_cores(compute_plan_path, num_cores=num_cores, ras_object=compute_ras)
|
110
|
-
|
122
|
+
logging.info(f"Set number of cores to {num_cores} for plan: {plan_number}")
|
111
123
|
except Exception as e:
|
112
|
-
|
124
|
+
logging.error(f"Error setting number of cores for plan {plan_number}: {str(e)}")
|
113
125
|
|
114
126
|
# Prepare the command for HEC-RAS execution
|
115
127
|
cmd = f'"{compute_ras.ras_exe_path}" -c "{compute_prj_path}" "{compute_plan_path}"'
|
116
|
-
|
117
|
-
|
128
|
+
logging.info("Running HEC-RAS from the Command Line:")
|
129
|
+
logging.info(f"Running command: {cmd}")
|
118
130
|
|
119
131
|
# Execute the HEC-RAS command
|
120
132
|
start_time = time.time()
|
@@ -122,15 +134,15 @@ class RasCmdr:
|
|
122
134
|
subprocess.run(cmd, check=True, shell=True, capture_output=True, text=True)
|
123
135
|
end_time = time.time()
|
124
136
|
run_time = end_time - start_time
|
125
|
-
|
126
|
-
|
137
|
+
logging.info(f"HEC-RAS execution completed for plan: {plan_number}")
|
138
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
127
139
|
return True
|
128
140
|
except subprocess.CalledProcessError as e:
|
129
141
|
end_time = time.time()
|
130
142
|
run_time = end_time - start_time
|
131
|
-
|
132
|
-
|
133
|
-
|
143
|
+
logging.error(f"Error running plan: {plan_number}")
|
144
|
+
logging.error(f"Error message: {e.output}")
|
145
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
134
146
|
return False
|
135
147
|
|
136
148
|
ras_obj = ras_object or ras
|
@@ -138,77 +150,51 @@ class RasCmdr:
|
|
138
150
|
ras_obj.geom_df = ras_obj.get_geom_entries()
|
139
151
|
ras_obj.flow_df = ras_obj.get_flow_entries()
|
140
152
|
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
141
|
-
|
153
|
+
|
142
154
|
|
143
155
|
|
144
156
|
@staticmethod
|
145
157
|
def compute_parallel(
|
146
|
-
plan_number: str
|
158
|
+
plan_number: Union[str, List[str], None] = None,
|
147
159
|
max_workers: int = 2,
|
148
160
|
num_cores: int = 2,
|
149
161
|
clear_geompre: bool = False,
|
150
|
-
ras_object: RasPrj
|
151
|
-
dest_folder: str
|
162
|
+
ras_object: Optional['RasPrj'] = None, # Type hinting as string to avoid NameError
|
163
|
+
dest_folder: Union[str, Path, None] = None,
|
152
164
|
overwrite_dest: bool = False
|
153
|
-
) ->
|
165
|
+
) -> Dict[str, bool]:
|
154
166
|
"""
|
155
|
-
|
156
|
-
|
157
|
-
This function creates separate worker folders, copies the project to each, and executes the specified plans
|
158
|
-
in parallel. It allows for isolated and concurrent execution of multiple plans.
|
159
|
-
|
160
|
-
Args:
|
161
|
-
plan_number (str | list[str] | None): Plan number, list of plan numbers, or None to execute all plans.
|
162
|
-
max_workers (int, optional): Maximum number of worker threads to use. Default is 2.
|
163
|
-
num_cores (int, optional): Number of cores to use for each plan execution. Default is 2.
|
164
|
-
clear_geompre (bool, optional): Whether to clear geometry preprocessor files. Defaults to False.
|
165
|
-
ras_object (RasPrj, optional): Specific RAS object to use. If None, uses the global ras instance.
|
166
|
-
dest_folder (str | Path, optional): Destination folder for the final computed results.
|
167
|
-
If None, results will be stored in a "[Computed]" folder next to the original project.
|
168
|
-
overwrite_dest (bool, optional): If True, overwrite the destination folder if it exists. Defaults to False.
|
169
|
-
|
170
|
-
Returns:
|
171
|
-
dict[str, bool]: A dictionary with plan numbers as keys and boolean values indicating success (True) or failure (False).
|
172
|
-
|
173
|
-
Raises:
|
174
|
-
ValueError: If the destination folder exists and is not empty, and overwrite_dest is False.
|
175
|
-
FileNotFoundError: If a plan file is not found.
|
176
|
-
|
177
|
-
Notes:
|
178
|
-
- This function creates separate folders for each worker to ensure isolated execution.
|
179
|
-
- Each worker uses its own RAS object to prevent conflicts.
|
180
|
-
- Plans are distributed among workers using a queue to ensure efficient parallel processing.
|
181
|
-
- The function automatically handles cleanup and consolidation of results after execution.
|
182
|
-
|
183
|
-
Revision Notes:
|
184
|
-
- Added support for clear_geompre flag as a pass-through to compute_plan.
|
185
|
-
- Simplified worker thread logic by removing redundant operations.
|
186
|
-
- Removed duplicate RAS object initialization in worker threads.
|
167
|
+
[Docstring remains unchanged]
|
187
168
|
"""
|
188
|
-
ras_obj = ras_object or ras
|
169
|
+
ras_obj = ras_object or ras # Assuming 'ras' is a global RasPrj instance
|
189
170
|
ras_obj.check_initialized()
|
190
171
|
|
191
|
-
project_folder = ras_obj.project_folder
|
172
|
+
project_folder = Path(ras_obj.project_folder)
|
192
173
|
|
193
174
|
if dest_folder is not None:
|
194
175
|
dest_folder_path = Path(dest_folder)
|
195
176
|
if dest_folder_path.exists():
|
196
177
|
if overwrite_dest:
|
197
178
|
shutil.rmtree(dest_folder_path)
|
179
|
+
logging.info(f"Destination folder '{dest_folder_path}' exists. Overwriting as per overwrite_dest=True.")
|
198
180
|
elif any(dest_folder_path.iterdir()):
|
199
|
-
|
181
|
+
error_msg = f"Destination folder '{dest_folder_path}' exists and is not empty. Use overwrite_dest=True to overwrite."
|
182
|
+
logging.error(error_msg)
|
183
|
+
raise ValueError(error_msg)
|
200
184
|
dest_folder_path.mkdir(parents=True, exist_ok=True)
|
201
185
|
shutil.copytree(project_folder, dest_folder_path, dirs_exist_ok=True)
|
186
|
+
logging.info(f"Copied project folder to destination: {dest_folder_path}")
|
202
187
|
project_folder = dest_folder_path
|
203
188
|
|
204
189
|
if plan_number:
|
205
190
|
if isinstance(plan_number, str):
|
206
191
|
plan_number = [plan_number]
|
207
192
|
ras_obj.plan_df = ras_obj.plan_df[ras_obj.plan_df['plan_number'].isin(plan_number)]
|
193
|
+
logging.info(f"Filtered plans to execute: {plan_number}")
|
208
194
|
|
209
195
|
num_plans = len(ras_obj.plan_df)
|
210
196
|
max_workers = min(max_workers, num_plans) if num_plans > 0 else 1
|
211
|
-
|
197
|
+
logging.info(f"Adjusted max_workers to {max_workers} based on the number of plans: {num_plans}")
|
212
198
|
|
213
199
|
# Clean up existing worker folders and create new ones
|
214
200
|
worker_ras_objects = {}
|
@@ -216,85 +202,122 @@ class RasCmdr:
|
|
216
202
|
worker_folder = project_folder.parent / f"{project_folder.name} [Worker {worker_id}]"
|
217
203
|
if worker_folder.exists():
|
218
204
|
shutil.rmtree(worker_folder)
|
205
|
+
logging.info(f"Removed existing worker folder: {worker_folder}")
|
219
206
|
shutil.copytree(project_folder, worker_folder)
|
220
|
-
|
207
|
+
logging.info(f"Created worker folder: {worker_folder}")
|
208
|
+
|
209
|
+
# Instantiate RasPrj properly
|
210
|
+
ras_instance = RasPrj() # Add necessary parameters if required
|
221
211
|
worker_ras_instance = init_ras_project(
|
222
212
|
ras_project_folder=worker_folder,
|
223
213
|
ras_version=ras_obj.ras_exe_path,
|
224
|
-
ras_instance=
|
214
|
+
ras_instance=ras_instance # Pass the instance instead of a string
|
225
215
|
)
|
226
216
|
worker_ras_objects[worker_id] = worker_ras_instance
|
227
217
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
218
|
+
# Distribute plans among workers in a round-robin fashion
|
219
|
+
worker_cycle = cycle(range(1, max_workers + 1))
|
220
|
+
plan_assignments = [(next(worker_cycle), plan_num) for plan_num in ras_obj.plan_df['plan_number']]
|
221
|
+
|
222
|
+
# Initialize ThreadPoolExecutor without tracking individual plan success
|
223
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
224
|
+
# Submit all plan executions to the executor
|
225
|
+
futures = [
|
226
|
+
executor.submit(
|
227
|
+
RasCmdr.compute_plan,
|
228
|
+
plan_num,
|
229
|
+
ras_object=worker_ras_objects[worker_id],
|
230
|
+
clear_geompre=clear_geompre,
|
231
|
+
num_cores=num_cores
|
232
|
+
)
|
233
|
+
for worker_id, plan_num in plan_assignments
|
234
|
+
]
|
235
|
+
|
236
|
+
# Optionally, you can log when each plan starts and completes
|
237
|
+
for future, (worker_id, plan_num) in zip(as_completed(futures), plan_assignments):
|
244
238
|
try:
|
245
|
-
|
246
|
-
|
247
|
-
plan_number,
|
248
|
-
ras_object=worker_ras_obj,
|
249
|
-
clear_geompre=clear_geompre,
|
250
|
-
num_cores=num_cores
|
251
|
-
)
|
252
|
-
with results_lock:
|
253
|
-
execution_results[plan_number] = success
|
254
|
-
print(f"Completed: Plan {plan_number} in worker {worker_id}")
|
239
|
+
future.result() # We don't need the success flag here
|
240
|
+
logging.info(f"Plan {plan_num} executed in worker {worker_id}")
|
255
241
|
except Exception as e:
|
256
|
-
|
257
|
-
|
258
|
-
print(f"Failed: Plan {plan_number} in worker {worker_id}. Error: {str(e)}")
|
259
|
-
|
260
|
-
# Start worker threads
|
261
|
-
worker_threads = [Thread(target=worker_thread, args=(worker_id,)) for worker_id in range(1, max_workers + 1)]
|
262
|
-
for thread in worker_threads:
|
263
|
-
thread.start()
|
264
|
-
|
265
|
-
# Wait for all threads to complete
|
266
|
-
for thread in worker_threads:
|
267
|
-
thread.join()
|
242
|
+
logging.error(f"Plan {plan_num} failed in worker {worker_id}: {str(e)}")
|
243
|
+
# Depending on requirements, you might want to handle retries or mark these plans differently
|
268
244
|
|
269
245
|
# Consolidate results
|
270
246
|
final_dest_folder = dest_folder_path if dest_folder is not None else project_folder.parent / f"{project_folder.name} [Computed]"
|
271
|
-
final_dest_folder.mkdir(exist_ok=True)
|
272
|
-
|
247
|
+
final_dest_folder.mkdir(parents=True, exist_ok=True)
|
248
|
+
logging.info(f"Final destination for computed results: {final_dest_folder}")
|
273
249
|
|
274
250
|
for worker_ras in worker_ras_objects.values():
|
275
|
-
worker_folder = worker_ras.project_folder
|
251
|
+
worker_folder = Path(worker_ras.project_folder)
|
276
252
|
try:
|
277
253
|
for item in worker_folder.iterdir():
|
278
254
|
dest_path = final_dest_folder / item.name
|
279
255
|
if dest_path.exists():
|
280
256
|
if dest_path.is_dir():
|
281
257
|
shutil.rmtree(dest_path)
|
258
|
+
logging.debug(f"Removed existing directory at {dest_path}")
|
282
259
|
else:
|
283
260
|
dest_path.unlink()
|
261
|
+
logging.debug(f"Removed existing file at {dest_path}")
|
284
262
|
shutil.move(str(item), final_dest_folder)
|
263
|
+
logging.debug(f"Moved {item} to {final_dest_folder}")
|
285
264
|
shutil.rmtree(worker_folder)
|
265
|
+
logging.info(f"Removed worker folder: {worker_folder}")
|
286
266
|
except Exception as e:
|
287
|
-
|
267
|
+
logging.error(f"Error moving results from {worker_folder} to {final_dest_folder}: {str(e)}")
|
268
|
+
|
269
|
+
# Initialize a new RasPrj object for the final destination
|
270
|
+
try:
|
271
|
+
# Create a new RasPrj instance
|
272
|
+
final_dest_folder_ras_obj = RasPrj()
|
273
|
+
|
274
|
+
# Initialize it using init_ras_project
|
275
|
+
final_dest_folder_ras_obj = init_ras_project(
|
276
|
+
ras_project_folder=final_dest_folder,
|
277
|
+
ras_version=ras_obj.ras_exe_path,
|
278
|
+
ras_instance=final_dest_folder_ras_obj
|
279
|
+
)
|
280
|
+
|
281
|
+
# Now we can check if it's initialized
|
282
|
+
final_dest_folder_ras_obj.check_initialized()
|
283
|
+
except Exception as e:
|
284
|
+
logging.error(f"Failed to initialize RasPrj for final destination: {str(e)}")
|
285
|
+
raise
|
286
|
+
|
287
|
+
# Retrieve plan entries and check for HDF results
|
288
|
+
try:
|
289
|
+
plan_entries = final_dest_folder_ras_obj.get_prj_entries('Plan')
|
290
|
+
except Exception as e:
|
291
|
+
logging.error(f"Failed to retrieve plan entries from final RasPrj: {str(e)}")
|
292
|
+
raise
|
293
|
+
|
294
|
+
execution_results: Dict[str, bool] = {}
|
295
|
+
for _, row in ras_obj.plan_df.iterrows():
|
296
|
+
plan_num = row['plan_number']
|
297
|
+
# Find the corresponding entry in plan_entries
|
298
|
+
entry = plan_entries[plan_entries['plan_number'] == plan_num]
|
299
|
+
if not entry.empty:
|
300
|
+
hdf_path = entry.iloc[0].get('HDF_Results_Path')
|
301
|
+
success = hdf_path is not None and Path(hdf_path).exists()
|
302
|
+
else:
|
303
|
+
success = False
|
304
|
+
execution_results[plan_num] = success
|
288
305
|
|
289
306
|
# Print execution results for each plan
|
290
|
-
|
291
|
-
for
|
292
|
-
|
307
|
+
logging.info("\nExecution Results:")
|
308
|
+
for plan_num, success in execution_results.items():
|
309
|
+
status = 'Successful' if success else 'Failed'
|
310
|
+
logging.info(f"Plan {plan_num}: {status} \n(HDF_Results_Path: {hdf_path})")
|
311
|
+
|
312
|
+
ras_obj = ras_object or ras
|
313
|
+
ras_obj.plan_df = ras_obj.get_plan_entries()
|
314
|
+
ras_obj.geom_df = ras_obj.get_geom_entries()
|
315
|
+
ras_obj.flow_df = ras_obj.get_flow_entries()
|
316
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
293
317
|
|
294
318
|
return execution_results
|
295
319
|
|
296
|
-
|
297
|
-
|
320
|
+
|
298
321
|
@staticmethod
|
299
322
|
def compute_test_mode(
|
300
323
|
plan_number=None,
|
@@ -355,40 +378,44 @@ class RasCmdr:
|
|
355
378
|
# This line of code is used to check if the RasPrj object is initialized.
|
356
379
|
ras_obj.check_initialized()
|
357
380
|
|
358
|
-
|
381
|
+
logging.info("Starting the compute_test_mode...")
|
359
382
|
|
360
383
|
# Use the project folder from the ras object
|
361
384
|
project_folder = ras_obj.project_folder
|
362
385
|
|
363
386
|
# Check if the project folder exists
|
364
387
|
if not project_folder.exists():
|
365
|
-
|
388
|
+
logging.error(f"Project folder '{project_folder}' does not exist.")
|
366
389
|
return
|
367
390
|
|
368
391
|
# Create test folder with the specified suffix in the same directory as the project folder
|
369
392
|
compute_folder = project_folder.parent / f"{project_folder.name} {dest_folder_suffix}"
|
370
|
-
|
393
|
+
logging.info(f"Creating the test folder: {compute_folder}...")
|
371
394
|
|
372
395
|
# Check if the compute folder exists and is empty
|
373
396
|
if compute_folder.exists():
|
374
397
|
if overwrite_dest:
|
375
398
|
shutil.rmtree(compute_folder)
|
399
|
+
logging.info(f"Compute folder '{compute_folder}' exists. Overwriting as per overwrite_dest=True.")
|
376
400
|
elif any(compute_folder.iterdir()):
|
377
|
-
|
401
|
+
error_msg = (
|
378
402
|
f"Compute folder '{compute_folder}' exists and is not empty. "
|
379
403
|
"Use overwrite_dest=True to overwrite."
|
380
404
|
)
|
405
|
+
logging.error(error_msg)
|
406
|
+
raise ValueError(error_msg)
|
381
407
|
else:
|
382
408
|
try:
|
383
409
|
shutil.copytree(project_folder, compute_folder)
|
410
|
+
logging.info(f"Copied project folder to compute folder: {compute_folder}")
|
384
411
|
except FileNotFoundError:
|
385
|
-
|
412
|
+
logging.error(f"Unable to copy project folder. Source folder '{project_folder}' not found.")
|
386
413
|
return
|
387
414
|
except PermissionError:
|
388
|
-
|
415
|
+
logging.error(f"Permission denied when trying to create or copy to '{compute_folder}'.")
|
389
416
|
return
|
390
417
|
except Exception as e:
|
391
|
-
|
418
|
+
logging.error(f"Error occurred while copying project folder: {str(e)}")
|
392
419
|
return
|
393
420
|
|
394
421
|
# Initialize a new RAS project in the compute folder
|
@@ -396,22 +423,22 @@ class RasCmdr:
|
|
396
423
|
compute_ras = RasPrj()
|
397
424
|
compute_ras.initialize(compute_folder, ras_obj.ras_exe_path)
|
398
425
|
compute_prj_path = compute_ras.prj_file
|
426
|
+
logging.info(f"Initialized RAS project in compute folder: {compute_prj_path}")
|
399
427
|
except Exception as e:
|
400
|
-
|
428
|
+
logging.error(f"Error initializing RAS project in compute folder: {str(e)}")
|
401
429
|
return
|
402
430
|
|
403
431
|
if not compute_prj_path:
|
404
|
-
|
432
|
+
logging.error("Project file not found.")
|
405
433
|
return
|
406
434
|
|
407
|
-
|
408
435
|
# Get plan entries
|
409
|
-
|
436
|
+
logging.info("Getting plan entries...")
|
410
437
|
try:
|
411
438
|
ras_compute_plan_entries = compute_ras.plan_df
|
412
|
-
|
439
|
+
logging.info("Retrieved plan entries successfully.")
|
413
440
|
except Exception as e:
|
414
|
-
|
441
|
+
logging.error(f"Error retrieving plan entries: {str(e)}")
|
415
442
|
return
|
416
443
|
|
417
444
|
if plan_number:
|
@@ -420,30 +447,35 @@ class RasCmdr:
|
|
420
447
|
ras_compute_plan_entries = ras_compute_plan_entries[
|
421
448
|
ras_compute_plan_entries['plan_number'].isin(plan_number)
|
422
449
|
]
|
423
|
-
|
450
|
+
logging.info(f"Filtered plans to execute: {plan_number}")
|
424
451
|
|
425
|
-
|
452
|
+
logging.info("Running selected plans sequentially...")
|
426
453
|
for _, plan in ras_compute_plan_entries.iterrows():
|
427
454
|
plan_number = plan["plan_number"]
|
428
455
|
start_time = time.time()
|
429
456
|
try:
|
430
|
-
|
457
|
+
success = RasCmdr.compute_plan(
|
431
458
|
plan_number,
|
432
459
|
ras_object=compute_ras,
|
433
460
|
clear_geompre=clear_geompre,
|
434
461
|
num_cores=num_cores
|
435
462
|
)
|
463
|
+
if success:
|
464
|
+
logging.info(f"Successfully computed plan {plan_number}")
|
465
|
+
else:
|
466
|
+
logging.error(f"Failed to compute plan {plan_number}")
|
436
467
|
except Exception as e:
|
437
|
-
|
468
|
+
logging.error(f"Error computing plan {plan_number}: {str(e)}")
|
438
469
|
end_time = time.time()
|
439
470
|
run_time = end_time - start_time
|
440
|
-
|
471
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
441
472
|
|
442
|
-
|
443
|
-
|
473
|
+
logging.info("All selected plans have been executed.")
|
474
|
+
logging.info("compute_test_mode completed.")
|
444
475
|
|
445
476
|
ras_obj = ras_object or ras
|
446
477
|
ras_obj.plan_df = ras_obj.get_plan_entries()
|
447
478
|
ras_obj.geom_df = ras_obj.get_geom_entries()
|
448
479
|
ras_obj.flow_df = ras_obj.get_flow_entries()
|
449
|
-
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
480
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
481
|
+
|