ras-commander 0.33.0__py3-none-any.whl → 0.35.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 +171 -138
- ras_commander/RasExamples.py +334 -120
- ras_commander/RasGeo.py +27 -6
- ras_commander/RasHdf.py +1702 -0
- ras_commander/RasPlan.py +398 -437
- ras_commander/RasPrj.py +403 -65
- ras_commander/RasUnsteady.py +24 -4
- ras_commander/RasUtils.py +352 -51
- ras_commander/__init__.py +4 -1
- ras_commander-0.35.0.dist-info/METADATA +319 -0
- ras_commander-0.35.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.35.0.dist-info}/LICENSE +0 -0
- {ras_commander-0.33.0.dist-info → ras_commander-0.35.0.dist-info}/WHEEL +0 -0
- {ras_commander-0.33.0.dist-info → ras_commander-0.35.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.
|
@@ -66,7 +74,8 @@ class RasCmdr:
|
|
66
74
|
Raises:
|
67
75
|
ValueError: If the specified dest_folder already exists and is not empty, and overwrite_dest is False.
|
68
76
|
"""
|
69
|
-
ras_obj = ras_object
|
77
|
+
ras_obj = ras_object if ras_object is not None else ras
|
78
|
+
logging.info(f"Using ras_object with project folder: {ras_obj.project_folder}")
|
70
79
|
ras_obj.check_initialized()
|
71
80
|
|
72
81
|
if dest_folder is not None:
|
@@ -75,11 +84,15 @@ class RasCmdr:
|
|
75
84
|
if dest_folder.exists():
|
76
85
|
if overwrite_dest:
|
77
86
|
shutil.rmtree(dest_folder)
|
87
|
+
logging.info(f"Destination folder '{dest_folder}' exists. Overwriting as per overwrite_dest=True.")
|
78
88
|
elif any(dest_folder.iterdir()):
|
79
|
-
|
89
|
+
error_msg = f"Destination folder '{dest_folder}' exists and is not empty. Use overwrite_dest=True to overwrite."
|
90
|
+
logging.error(error_msg)
|
91
|
+
raise ValueError(error_msg)
|
80
92
|
|
81
93
|
dest_folder.mkdir(parents=True, exist_ok=True)
|
82
94
|
shutil.copytree(ras_obj.project_folder, dest_folder, dirs_exist_ok=True)
|
95
|
+
logging.info(f"Copied project folder to destination: {dest_folder}")
|
83
96
|
|
84
97
|
compute_ras = RasPrj()
|
85
98
|
compute_ras.initialize(dest_folder, ras_obj.ras_exe_path)
|
@@ -92,29 +105,29 @@ class RasCmdr:
|
|
92
105
|
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
106
|
|
94
107
|
if not compute_prj_path or not compute_plan_path:
|
95
|
-
|
108
|
+
logging.error(f"Could not find project file or plan file for plan {plan_number}")
|
96
109
|
return False
|
97
110
|
|
98
111
|
# Clear geometry preprocessor files if requested
|
99
112
|
if clear_geompre:
|
100
113
|
try:
|
101
114
|
RasGeo.clear_geompre_files(compute_plan_path, ras_object=compute_ras)
|
102
|
-
|
115
|
+
logging.info(f"Cleared geometry preprocessor files for plan: {plan_number}")
|
103
116
|
except Exception as e:
|
104
|
-
|
117
|
+
logging.error(f"Error clearing geometry preprocessor files for plan {plan_number}: {str(e)}")
|
105
118
|
|
106
119
|
# Set the number of cores if specified
|
107
120
|
if num_cores is not None:
|
108
121
|
try:
|
109
122
|
RasPlan.set_num_cores(compute_plan_path, num_cores=num_cores, ras_object=compute_ras)
|
110
|
-
|
123
|
+
logging.info(f"Set number of cores to {num_cores} for plan: {plan_number}")
|
111
124
|
except Exception as e:
|
112
|
-
|
125
|
+
logging.error(f"Error setting number of cores for plan {plan_number}: {str(e)}")
|
113
126
|
|
114
127
|
# Prepare the command for HEC-RAS execution
|
115
128
|
cmd = f'"{compute_ras.ras_exe_path}" -c "{compute_prj_path}" "{compute_plan_path}"'
|
116
|
-
|
117
|
-
|
129
|
+
logging.info("Running HEC-RAS from the Command Line:")
|
130
|
+
logging.info(f"Running command: {cmd}")
|
118
131
|
|
119
132
|
# Execute the HEC-RAS command
|
120
133
|
start_time = time.time()
|
@@ -122,93 +135,67 @@ class RasCmdr:
|
|
122
135
|
subprocess.run(cmd, check=True, shell=True, capture_output=True, text=True)
|
123
136
|
end_time = time.time()
|
124
137
|
run_time = end_time - start_time
|
125
|
-
|
126
|
-
|
138
|
+
logging.info(f"HEC-RAS execution completed for plan: {plan_number}")
|
139
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
127
140
|
return True
|
128
141
|
except subprocess.CalledProcessError as e:
|
129
142
|
end_time = time.time()
|
130
143
|
run_time = end_time - start_time
|
131
|
-
|
132
|
-
|
133
|
-
|
144
|
+
logging.error(f"Error running plan: {plan_number}")
|
145
|
+
logging.error(f"Error message: {e.output}")
|
146
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
134
147
|
return False
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
148
|
+
finally:
|
149
|
+
# Update the RAS object's dataframes
|
150
|
+
ras_obj.plan_df = ras_obj.get_plan_entries()
|
151
|
+
ras_obj.geom_df = ras_obj.get_geom_entries()
|
152
|
+
ras_obj.flow_df = ras_obj.get_flow_entries()
|
153
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
154
|
+
|
142
155
|
|
143
156
|
|
144
157
|
@staticmethod
|
145
158
|
def compute_parallel(
|
146
|
-
plan_number: str
|
159
|
+
plan_number: Union[str, List[str], None] = None,
|
147
160
|
max_workers: int = 2,
|
148
161
|
num_cores: int = 2,
|
149
162
|
clear_geompre: bool = False,
|
150
|
-
ras_object: RasPrj
|
151
|
-
dest_folder: str
|
163
|
+
ras_object: Optional['RasPrj'] = None, # Type hinting as string to avoid NameError
|
164
|
+
dest_folder: Union[str, Path, None] = None,
|
152
165
|
overwrite_dest: bool = False
|
153
|
-
) ->
|
166
|
+
) -> Dict[str, bool]:
|
154
167
|
"""
|
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.
|
168
|
+
[Docstring remains unchanged]
|
187
169
|
"""
|
188
|
-
ras_obj = ras_object or ras
|
170
|
+
ras_obj = ras_object or ras # Assuming 'ras' is a global RasPrj instance
|
189
171
|
ras_obj.check_initialized()
|
190
172
|
|
191
|
-
project_folder = ras_obj.project_folder
|
173
|
+
project_folder = Path(ras_obj.project_folder)
|
192
174
|
|
193
175
|
if dest_folder is not None:
|
194
176
|
dest_folder_path = Path(dest_folder)
|
195
177
|
if dest_folder_path.exists():
|
196
178
|
if overwrite_dest:
|
197
179
|
shutil.rmtree(dest_folder_path)
|
180
|
+
logging.info(f"Destination folder '{dest_folder_path}' exists. Overwriting as per overwrite_dest=True.")
|
198
181
|
elif any(dest_folder_path.iterdir()):
|
199
|
-
|
182
|
+
error_msg = f"Destination folder '{dest_folder_path}' exists and is not empty. Use overwrite_dest=True to overwrite."
|
183
|
+
logging.error(error_msg)
|
184
|
+
raise ValueError(error_msg)
|
200
185
|
dest_folder_path.mkdir(parents=True, exist_ok=True)
|
201
186
|
shutil.copytree(project_folder, dest_folder_path, dirs_exist_ok=True)
|
187
|
+
logging.info(f"Copied project folder to destination: {dest_folder_path}")
|
202
188
|
project_folder = dest_folder_path
|
203
189
|
|
204
190
|
if plan_number:
|
205
191
|
if isinstance(plan_number, str):
|
206
192
|
plan_number = [plan_number]
|
207
193
|
ras_obj.plan_df = ras_obj.plan_df[ras_obj.plan_df['plan_number'].isin(plan_number)]
|
194
|
+
logging.info(f"Filtered plans to execute: {plan_number}")
|
208
195
|
|
209
196
|
num_plans = len(ras_obj.plan_df)
|
210
197
|
max_workers = min(max_workers, num_plans) if num_plans > 0 else 1
|
211
|
-
|
198
|
+
logging.info(f"Adjusted max_workers to {max_workers} based on the number of plans: {num_plans}")
|
212
199
|
|
213
200
|
# Clean up existing worker folders and create new ones
|
214
201
|
worker_ras_objects = {}
|
@@ -216,85 +203,122 @@ class RasCmdr:
|
|
216
203
|
worker_folder = project_folder.parent / f"{project_folder.name} [Worker {worker_id}]"
|
217
204
|
if worker_folder.exists():
|
218
205
|
shutil.rmtree(worker_folder)
|
206
|
+
logging.info(f"Removed existing worker folder: {worker_folder}")
|
219
207
|
shutil.copytree(project_folder, worker_folder)
|
220
|
-
|
208
|
+
logging.info(f"Created worker folder: {worker_folder}")
|
209
|
+
|
210
|
+
# Instantiate RasPrj properly
|
211
|
+
ras_instance = RasPrj() # Add necessary parameters if required
|
221
212
|
worker_ras_instance = init_ras_project(
|
222
213
|
ras_project_folder=worker_folder,
|
223
214
|
ras_version=ras_obj.ras_exe_path,
|
224
|
-
ras_instance=
|
215
|
+
ras_instance=ras_instance # Pass the instance instead of a string
|
225
216
|
)
|
226
217
|
worker_ras_objects[worker_id] = worker_ras_instance
|
227
218
|
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
219
|
+
# Distribute plans among workers in a round-robin fashion
|
220
|
+
worker_cycle = cycle(range(1, max_workers + 1))
|
221
|
+
plan_assignments = [(next(worker_cycle), plan_num) for plan_num in ras_obj.plan_df['plan_number']]
|
222
|
+
|
223
|
+
# Initialize ThreadPoolExecutor without tracking individual plan success
|
224
|
+
with ThreadPoolExecutor(max_workers=max_workers) as executor:
|
225
|
+
# Submit all plan executions to the executor
|
226
|
+
futures = [
|
227
|
+
executor.submit(
|
228
|
+
RasCmdr.compute_plan,
|
229
|
+
plan_num,
|
230
|
+
ras_object=worker_ras_objects[worker_id],
|
231
|
+
clear_geompre=clear_geompre,
|
232
|
+
num_cores=num_cores
|
233
|
+
)
|
234
|
+
for worker_id, plan_num in plan_assignments
|
235
|
+
]
|
236
|
+
|
237
|
+
# Optionally, you can log when each plan starts and completes
|
238
|
+
for future, (worker_id, plan_num) in zip(as_completed(futures), plan_assignments):
|
244
239
|
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}")
|
240
|
+
future.result() # We don't need the success flag here
|
241
|
+
logging.info(f"Plan {plan_num} executed in worker {worker_id}")
|
255
242
|
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()
|
243
|
+
logging.error(f"Plan {plan_num} failed in worker {worker_id}: {str(e)}")
|
244
|
+
# Depending on requirements, you might want to handle retries or mark these plans differently
|
268
245
|
|
269
246
|
# Consolidate results
|
270
247
|
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
|
-
|
248
|
+
final_dest_folder.mkdir(parents=True, exist_ok=True)
|
249
|
+
logging.info(f"Final destination for computed results: {final_dest_folder}")
|
273
250
|
|
274
251
|
for worker_ras in worker_ras_objects.values():
|
275
|
-
worker_folder = worker_ras.project_folder
|
252
|
+
worker_folder = Path(worker_ras.project_folder)
|
276
253
|
try:
|
277
254
|
for item in worker_folder.iterdir():
|
278
255
|
dest_path = final_dest_folder / item.name
|
279
256
|
if dest_path.exists():
|
280
257
|
if dest_path.is_dir():
|
281
258
|
shutil.rmtree(dest_path)
|
259
|
+
logging.debug(f"Removed existing directory at {dest_path}")
|
282
260
|
else:
|
283
261
|
dest_path.unlink()
|
262
|
+
logging.debug(f"Removed existing file at {dest_path}")
|
284
263
|
shutil.move(str(item), final_dest_folder)
|
264
|
+
logging.debug(f"Moved {item} to {final_dest_folder}")
|
285
265
|
shutil.rmtree(worker_folder)
|
266
|
+
logging.info(f"Removed worker folder: {worker_folder}")
|
286
267
|
except Exception as e:
|
287
|
-
|
268
|
+
logging.error(f"Error moving results from {worker_folder} to {final_dest_folder}: {str(e)}")
|
269
|
+
|
270
|
+
# Initialize a new RasPrj object for the final destination
|
271
|
+
try:
|
272
|
+
# Create a new RasPrj instance
|
273
|
+
final_dest_folder_ras_obj = RasPrj()
|
274
|
+
|
275
|
+
# Initialize it using init_ras_project
|
276
|
+
final_dest_folder_ras_obj = init_ras_project(
|
277
|
+
ras_project_folder=final_dest_folder,
|
278
|
+
ras_version=ras_obj.ras_exe_path,
|
279
|
+
ras_instance=final_dest_folder_ras_obj
|
280
|
+
)
|
281
|
+
|
282
|
+
# Now we can check if it's initialized
|
283
|
+
final_dest_folder_ras_obj.check_initialized()
|
284
|
+
except Exception as e:
|
285
|
+
logging.error(f"Failed to initialize RasPrj for final destination: {str(e)}")
|
286
|
+
raise
|
287
|
+
|
288
|
+
# Retrieve plan entries and check for HDF results
|
289
|
+
try:
|
290
|
+
plan_entries = final_dest_folder_ras_obj.get_prj_entries('Plan')
|
291
|
+
except Exception as e:
|
292
|
+
logging.error(f"Failed to retrieve plan entries from final RasPrj: {str(e)}")
|
293
|
+
raise
|
294
|
+
|
295
|
+
execution_results: Dict[str, bool] = {}
|
296
|
+
for _, row in ras_obj.plan_df.iterrows():
|
297
|
+
plan_num = row['plan_number']
|
298
|
+
# Find the corresponding entry in plan_entries
|
299
|
+
entry = plan_entries[plan_entries['plan_number'] == plan_num]
|
300
|
+
if not entry.empty:
|
301
|
+
hdf_path = entry.iloc[0].get('HDF_Results_Path')
|
302
|
+
success = hdf_path is not None and Path(hdf_path).exists()
|
303
|
+
else:
|
304
|
+
success = False
|
305
|
+
execution_results[plan_num] = success
|
288
306
|
|
289
307
|
# Print execution results for each plan
|
290
|
-
|
291
|
-
for
|
292
|
-
|
308
|
+
logging.info("\nExecution Results:")
|
309
|
+
for plan_num, success in execution_results.items():
|
310
|
+
status = 'Successful' if success else 'Failed'
|
311
|
+
logging.info(f"Plan {plan_num}: {status} \n(HDF_Results_Path: {hdf_path})")
|
312
|
+
|
313
|
+
ras_obj = ras_object or ras
|
314
|
+
ras_obj.plan_df = ras_obj.get_plan_entries()
|
315
|
+
ras_obj.geom_df = ras_obj.get_geom_entries()
|
316
|
+
ras_obj.flow_df = ras_obj.get_flow_entries()
|
317
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
293
318
|
|
294
319
|
return execution_results
|
295
320
|
|
296
|
-
|
297
|
-
|
321
|
+
|
298
322
|
@staticmethod
|
299
323
|
def compute_test_mode(
|
300
324
|
plan_number=None,
|
@@ -355,40 +379,44 @@ class RasCmdr:
|
|
355
379
|
# This line of code is used to check if the RasPrj object is initialized.
|
356
380
|
ras_obj.check_initialized()
|
357
381
|
|
358
|
-
|
382
|
+
logging.info("Starting the compute_test_mode...")
|
359
383
|
|
360
384
|
# Use the project folder from the ras object
|
361
385
|
project_folder = ras_obj.project_folder
|
362
386
|
|
363
387
|
# Check if the project folder exists
|
364
388
|
if not project_folder.exists():
|
365
|
-
|
389
|
+
logging.error(f"Project folder '{project_folder}' does not exist.")
|
366
390
|
return
|
367
391
|
|
368
392
|
# Create test folder with the specified suffix in the same directory as the project folder
|
369
393
|
compute_folder = project_folder.parent / f"{project_folder.name} {dest_folder_suffix}"
|
370
|
-
|
394
|
+
logging.info(f"Creating the test folder: {compute_folder}...")
|
371
395
|
|
372
396
|
# Check if the compute folder exists and is empty
|
373
397
|
if compute_folder.exists():
|
374
398
|
if overwrite_dest:
|
375
399
|
shutil.rmtree(compute_folder)
|
400
|
+
logging.info(f"Compute folder '{compute_folder}' exists. Overwriting as per overwrite_dest=True.")
|
376
401
|
elif any(compute_folder.iterdir()):
|
377
|
-
|
402
|
+
error_msg = (
|
378
403
|
f"Compute folder '{compute_folder}' exists and is not empty. "
|
379
404
|
"Use overwrite_dest=True to overwrite."
|
380
405
|
)
|
406
|
+
logging.error(error_msg)
|
407
|
+
raise ValueError(error_msg)
|
381
408
|
else:
|
382
409
|
try:
|
383
410
|
shutil.copytree(project_folder, compute_folder)
|
411
|
+
logging.info(f"Copied project folder to compute folder: {compute_folder}")
|
384
412
|
except FileNotFoundError:
|
385
|
-
|
413
|
+
logging.error(f"Unable to copy project folder. Source folder '{project_folder}' not found.")
|
386
414
|
return
|
387
415
|
except PermissionError:
|
388
|
-
|
416
|
+
logging.error(f"Permission denied when trying to create or copy to '{compute_folder}'.")
|
389
417
|
return
|
390
418
|
except Exception as e:
|
391
|
-
|
419
|
+
logging.error(f"Error occurred while copying project folder: {str(e)}")
|
392
420
|
return
|
393
421
|
|
394
422
|
# Initialize a new RAS project in the compute folder
|
@@ -396,22 +424,22 @@ class RasCmdr:
|
|
396
424
|
compute_ras = RasPrj()
|
397
425
|
compute_ras.initialize(compute_folder, ras_obj.ras_exe_path)
|
398
426
|
compute_prj_path = compute_ras.prj_file
|
427
|
+
logging.info(f"Initialized RAS project in compute folder: {compute_prj_path}")
|
399
428
|
except Exception as e:
|
400
|
-
|
429
|
+
logging.error(f"Error initializing RAS project in compute folder: {str(e)}")
|
401
430
|
return
|
402
431
|
|
403
432
|
if not compute_prj_path:
|
404
|
-
|
433
|
+
logging.error("Project file not found.")
|
405
434
|
return
|
406
435
|
|
407
|
-
|
408
436
|
# Get plan entries
|
409
|
-
|
437
|
+
logging.info("Getting plan entries...")
|
410
438
|
try:
|
411
439
|
ras_compute_plan_entries = compute_ras.plan_df
|
412
|
-
|
440
|
+
logging.info("Retrieved plan entries successfully.")
|
413
441
|
except Exception as e:
|
414
|
-
|
442
|
+
logging.error(f"Error retrieving plan entries: {str(e)}")
|
415
443
|
return
|
416
444
|
|
417
445
|
if plan_number:
|
@@ -420,30 +448,35 @@ class RasCmdr:
|
|
420
448
|
ras_compute_plan_entries = ras_compute_plan_entries[
|
421
449
|
ras_compute_plan_entries['plan_number'].isin(plan_number)
|
422
450
|
]
|
423
|
-
|
451
|
+
logging.info(f"Filtered plans to execute: {plan_number}")
|
424
452
|
|
425
|
-
|
453
|
+
logging.info("Running selected plans sequentially...")
|
426
454
|
for _, plan in ras_compute_plan_entries.iterrows():
|
427
455
|
plan_number = plan["plan_number"]
|
428
456
|
start_time = time.time()
|
429
457
|
try:
|
430
|
-
|
458
|
+
success = RasCmdr.compute_plan(
|
431
459
|
plan_number,
|
432
460
|
ras_object=compute_ras,
|
433
461
|
clear_geompre=clear_geompre,
|
434
462
|
num_cores=num_cores
|
435
463
|
)
|
464
|
+
if success:
|
465
|
+
logging.info(f"Successfully computed plan {plan_number}")
|
466
|
+
else:
|
467
|
+
logging.error(f"Failed to compute plan {plan_number}")
|
436
468
|
except Exception as e:
|
437
|
-
|
469
|
+
logging.error(f"Error computing plan {plan_number}: {str(e)}")
|
438
470
|
end_time = time.time()
|
439
471
|
run_time = end_time - start_time
|
440
|
-
|
472
|
+
logging.info(f"Total run time for plan {plan_number}: {run_time:.2f} seconds")
|
441
473
|
|
442
|
-
|
443
|
-
|
474
|
+
logging.info("All selected plans have been executed.")
|
475
|
+
logging.info("compute_test_mode completed.")
|
444
476
|
|
445
477
|
ras_obj = ras_object or ras
|
446
478
|
ras_obj.plan_df = ras_obj.get_plan_entries()
|
447
479
|
ras_obj.geom_df = ras_obj.get_geom_entries()
|
448
480
|
ras_obj.flow_df = ras_obj.get_flow_entries()
|
449
|
-
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
481
|
+
ras_obj.unsteady_df = ras_obj.get_unsteady_entries()
|
482
|
+
|