diff --git a/modules/Workflow/whale/main.py b/modules/Workflow/whale/main.py index 71bad4c89..a9e101b3d 100644 --- a/modules/Workflow/whale/main.py +++ b/modules/Workflow/whale/main.py @@ -313,7 +313,7 @@ def create_command(command_list, enforced_python=None): return command # noqa: DOC201, RUF100 -def run_command(command): +def run_command(command, app_category=""): # noqa: C901 """Short description Long description @@ -375,28 +375,32 @@ def run_command(command): if returncode != 0: log_error(f'return code: {returncode}') - # if platform.system() == 'Windows': - # return result.decode(sys.stdout.encoding), returncode - # else: - # #print(result, returncode) - # return str(result), returncode - + # # sy - error checking trial 2 : only for windows and python & additional try statement + # try: + if (platform.system() == 'Windows') and ('python.exe' in str(command)): if returncode != 0: - raise WorkFlowInputError('Analysis Failed') + raise WorkFlowInputError('Analysis Failed at ' + app_category) # noqa: TRY301 + + # sy - safe apps should be added below + elif ('OpenSeesInput' in str(command)): + if returncode != 0: + raise WorkFlowInputError('Analysis Failed at ' + app_category) # noqa: TRY301 return str(result), returncode except WorkFlowInputError as e: - print(str(e).replace("'", '')) - print(str(result)) + # this will catch the error + print(str(e).replace('\'','')) # noqa: T201 + print(" =====================================") # noqa: T201 + print(str(result)) # noqa: T201 sys.exit(-20) - except: - # if for whatever reason the above fails, move on + except: # noqa: E722 + # if for whatever reason the function inside "try" failes, move on without checking error return str(result), 0 return result, returncode @@ -1303,7 +1307,7 @@ def create_asset_files(self): prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Asset Creater") # Check if the command was completed successfully if returncode != 0: @@ -1593,7 +1597,7 @@ def perform_system_performance_assessment(self, asset_type): prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Performance Assessment") log_msg( f'\n{result}\n', prepend_timestamp=False, @@ -1657,7 +1661,7 @@ def perform_regional_event(self): prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Hazard Event") log_msg('Output: ', prepend_timestamp=False, prepend_blank_space=False) log_msg( @@ -1720,7 +1724,7 @@ def perform_regional_recovery(self, asset_keys): # noqa: ARG002 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command, "Recovery") log_msg('Output: ', prepend_timestamp=False, prepend_blank_space=False) log_msg( @@ -1803,7 +1807,7 @@ def perform_regional_mapping(self, AIM_file_path, assetType, doParallel=True): ) else: - result, returncode = run_command(command) + result, returncode = run_command(command,"Hazard-Asset Mapping (HTA)") log_msg( 'Output: ' + str(returncode), @@ -2043,7 +2047,7 @@ def preprocess_inputs( # noqa: C901 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,f'{app_type} - at the initial setup (getRV)') log_msg( 'Output: ' + str(returncode), @@ -2085,7 +2089,7 @@ def preprocess_inputs( # noqa: C901 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command, app_type) log_msg( 'Output: ' + str(returncode), @@ -2160,7 +2164,7 @@ def preprocess_inputs( # noqa: C901 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command, app_type) log_msg( 'Output: ' + str(returncode), @@ -2179,11 +2183,11 @@ def preprocess_inputs( # noqa: C901 try: if command.startswith('python'): if platform.system() == 'Windows': - driver_script += 'if %errorlevel% neq 0 exit /b -1 \n' + driver_script += 'if %errorlevel% neq 0 exit /b -1 \n' # noqa: F821, F841 else: pass - except: + except: # noqa: S110, E722 pass log_msg( @@ -2248,7 +2252,7 @@ def gather_workflow_inputs(self, asst_id=None, AIM_file_path='AIM.json'): # noq # print('FMK- gather command:', command) - result, returncode = run_command(command) + result, returncode = run_command(command, ' Gathering workflow inputs') log_msg('Output: ', prepend_timestamp=False, prepend_blank_space=False) log_msg( @@ -2453,7 +2457,7 @@ def simulate_response(self, AIM_file_path='AIM.json', asst_id=None): # noqa: C9 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command, "Response Simulator") if self.run_type in ['run', 'runningLocal']: log_msg( @@ -2530,7 +2534,7 @@ def perform_asset_performance(asset_type): # noqa: N805, D102 app_path=self.app_dir_local # noqa: F821 ) command = create_command(app_command_list) - result, returncode = run_command(command) + result, returncode = run_command(command,"Performance assessment") def estimate_losses( # noqa: C901 self, @@ -2623,7 +2627,7 @@ def estimate_losses( # noqa: C901 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Damage and loss") log_msg(result, prepend_timestamp=False) @@ -2674,7 +2678,7 @@ def estimate_losses( # noqa: C901 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Damage and loss") log_msg(result, prepend_timestamp=False) @@ -2817,7 +2821,7 @@ def estimate_performance( # noqa: D102 prepend_blank_space=False, ) - result, returncode = run_command(command) + result, returncode = run_command(command,"Performance Assessment") log_msg(result, prepend_timestamp=False) diff --git a/modules/performSIMULATION/openSees/OpenSeesPostprocessor.cpp b/modules/performSIMULATION/openSees/OpenSeesPostprocessor.cpp index 09f7506ab..7eee9934b 100644 --- a/modules/performSIMULATION/openSees/OpenSeesPostprocessor.cpp +++ b/modules/performSIMULATION/openSees/OpenSeesPostprocessor.cpp @@ -31,6 +31,9 @@ int main(int argc, char **argv) } + + + OpenSeesPostprocessor::OpenSeesPostprocessor() :filenameEDP(0), filenameAIM(0), filenameSAM(0) { @@ -184,9 +187,15 @@ OpenSeesPostprocessor::processEDPs(){ // open file ifstream myfile; myfile.open (fileName); + double tmp; if (myfile.is_open()) { + + if (myfile.peek() == std::ifstream::traits_type::eof()) { + std::cout<< "The OpenSees simulation was not successful"; + exit(-1); + } // read first 2 rows of useless data for (int ii=0; ii<2; ii++) @@ -233,6 +242,13 @@ OpenSeesPostprocessor::processEDPs(){ double tmp; if (myfile.is_open()) { + + if (myfile.peek() == std::ifstream::traits_type::eof()) { + std::cout<< "The OpenSees simulation was not successful"; + exit(-1); + } + + for (int jj=0; jj> tmp; @@ -272,6 +288,12 @@ OpenSeesPostprocessor::processEDPs(){ double tmp; if (myfile.is_open()) { + + + if (myfile.peek() == std::ifstream::traits_type::eof()) { + std::cout<< "The OpenSees simulation was not successful"; + exit(-1); + } // read first 2 rows of useless data for (int ii=0; ii<2; ii++) @@ -318,6 +340,12 @@ OpenSeesPostprocessor::processEDPs(){ absValue = 0.0; if (myfile.is_open()) { + + if (myfile.peek() == std::ifstream::traits_type::eof()) { + std::cout<< "The OpenSees simulation was not successful"; + exit(-1); + } + myfile >> absMin >> absMax >> absValue; myfile.close(); } diff --git a/modules/performSIMULATION/openSees/OpenSeesSimulation.py b/modules/performSIMULATION/openSees/OpenSeesSimulation.py index 72bb89e42..a7e8d02b8 100644 --- a/modules/performSIMULATION/openSees/OpenSeesSimulation.py +++ b/modules/performSIMULATION/openSees/OpenSeesSimulation.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 # noqa: EXE001, D100 +#!/usr/bin/env python3 # noqa: D100, EXE001, RUF100 import os import subprocess @@ -26,14 +26,14 @@ def main(args): # noqa: D103 # If requesting random variables run getUncertainty # Otherwise, Run Opensees if '--getRV' in args: - getUncertaintyCommand = f'"{scriptDir}/OpenSeesPreprocessor" {aimName} {samName} {evtName} {simName}' # noqa: N806 + getUncertaintyCommand = f'"{scriptDir}/OpenSeesPreprocessor" {aimName} {samName} {evtName} {simName} > workflow.err 2>&1' # noqa: N806 exit_code = subprocess.Popen(getUncertaintyCommand, shell=True).wait() # noqa: S602 # exit_code = subprocess.run(getUncertaintyCommand, shell=True).returncode # if not exit_code==0: # exit(exit_code) else: # Run preprocessor - preprocessorCommand = f'"{scriptDir}/OpenSeesPreprocessor" {aimName} {samName} {evtName} {edpName} {simName} example.tcl' # noqa: N806 + preprocessorCommand = f'"{scriptDir}/OpenSeesPreprocessor" {aimName} {samName} {evtName} {edpName} {simName} example.tcl > workflow.err 2>&1' # noqa: N806 exit_code = subprocess.Popen(preprocessorCommand, shell=True).wait() # noqa: S602 # exit_code = subprocess.run(preprocessorCommand, shell=True).returncode # Maybe better for compatibility - jb # if not exit_code==0: @@ -41,7 +41,7 @@ def main(args): # noqa: D103 # Run OpenSees exit_code = subprocess.Popen( # noqa: S602 - 'OpenSees example.tcl >> workflow.err 2>&1', # noqa: S607 + 'OpenSees example.tcl >> workflow.err 2>&1', # noqa: S607 shell=True, ).wait() # Maybe better for compatibility, need to doublecheck - jb @@ -58,7 +58,7 @@ def main(args): # noqa: D103 # exit(exit_code) # Run postprocessor - postprocessorCommand = f'"{scriptDir}/OpenSeesPostprocessor" {aimName} {samName} {evtName} {edpName}' # noqa: N806 + postprocessorCommand = f'"{scriptDir}/OpenSeesPostprocessor" {aimName} {samName} {evtName} {edpName} >> workflow.err 2>&1' # noqa: N806 exit_code = subprocess.Popen(postprocessorCommand, shell=True).wait() # noqa: S602, F841 # exit_code = subprocess.run(postprocessorCommand, shell=True).returncode # Maybe better for compatibility - jb # if not exit_code==0: diff --git a/modules/performUQ/SimCenterUQ/nataf_gsa/ERANataf.cpp b/modules/performUQ/SimCenterUQ/nataf_gsa/ERANataf.cpp index 97755be42..5fb5d1b82 100644 --- a/modules/performUQ/SimCenterUQ/nataf_gsa/ERANataf.cpp +++ b/modules/performUQ/SimCenterUQ/nataf_gsa/ERANataf.cpp @@ -544,6 +544,12 @@ void ERANataf::simulateAppBatch(string workflowDriver, // TODO: need to use numExistingDirectories for MFMC return; } + else if (inp.femAppName.compare("unknown") == 0) { + //*ERROR* + std::string errMsg = "FEM simulation model is unknown."; + theErrorFile.write(errMsg); + return; + } // // u -> x; diff --git a/modules/performUQ/dakota/DakotaUQ.py b/modules/performUQ/dakota/DakotaUQ.py index 318cd12b7..b72f3e5ec 100644 --- a/modules/performUQ/dakota/DakotaUQ.py +++ b/modules/performUQ/dakota/DakotaUQ.py @@ -67,7 +67,7 @@ def main(args): # noqa: C901, D103 osType = 'Linux' # noqa: N806 cwd = os.getcwd() # noqa: PTH109 - print('CWD: ' + cwd) # noqa: T201 + print('cwd: ' + cwd) # noqa: T201 thisScriptDir = os.path.dirname(os.path.realpath(__file__)) # noqa: PTH120, N806 @@ -127,7 +127,9 @@ def main(args): # noqa: C901, D103 if data['parType'] == 'parRUN': dakotaCommand = data['mpiExec'] + ' -n 1 ' + dakotaCommand # noqa: N806 - print('running Dakota: ', dakotaCommand) # noqa: T201 + print('Running Dakota: ', dakotaCommand) # noqa: T201 + + run_success = True try: result = subprocess.check_output( # noqa: S602 @@ -136,13 +138,16 @@ def main(args): # noqa: C901, D103 returncode = 0 except subprocess.CalledProcessError as e: result = e.output - print('RUNNING DAKOTA ERROR: ', result) # noqa: T201 + #print('RUNNING DAKOTA ERROR: ', result) # noqa: RUF100, T201 returncode = e.returncode # noqa: F841 + run_success = False dakotaErrFile = os.path.join(os.getcwd(), 'dakota.err') # noqa: PTH109, PTH118, N806 dakotaOutFile = os.path.join(os.getcwd(), 'dakota.out') # noqa: PTH109, PTH118, N806 + dakotaTabFile = os.path.join(os.getcwd(), 'dakotaTab.out') # noqa: PTH109, PTH118, N806 checkErrFile = os.path.getsize(dakotaErrFile) # noqa: PTH202, N806 checkOutFile = os.path.exists(dakotaOutFile) # noqa: PTH110, N806 + checkTabFile = os.path.exists(dakotaTabFile) # noqa: F841, N806, PTH110 if checkOutFile == False and checkErrFile == 0: # noqa: E712 with open(dakotaErrFile, 'a') as file: # noqa: PTH123 @@ -151,5 +156,38 @@ def main(args): # noqa: C901, D103 pass + if not run_success: + # noqa: W293 + display_err = "\nERROR. Dakota did not run. dakota.err not created." + # # noqa: PLR2044 + + # First see if dakota.err is created + with open(dakotaErrFile, 'r') as file: # noqa: PTH123, UP015 + dakota_err = file.read() + + display_err = "\nERROR. Workflow did not run: " + dakota_err + + + # Second, see if workflow.err is found + if 'workdir.' in dakota_err: + + display_err = "\nERROR. Workflow did not run: " + dakota_err + + start_index = dakota_err.find("workdir.") + len("workdir.") + end_index = dakota_err.find("\\", start_index) + workdir_no = dakota_err[start_index:end_index] + + workflow_err_path = os.path.join(os.getcwd(),f'workdir.{workdir_no}/workflow.err') # noqa: PTH109, PTH118 + if os.path.isfile(workflow_err_path): # noqa: N806, PTH110, PTH113, RUF100 + with open(workflow_err_path, 'r') as file: # noqa: PTH123, UP015 + workflow_err = file.read() + + if not workflow_err=="": # noqa: SIM201 + display_err = str("\nERROR running the workflow: \n" + workflow_err + "\n Check out more in " + str(os.path.dirname(workflow_err_path)).replace('\\','/')) + + print(display_err) # noqa: T201 + exit(0) # sy - this could be -1 like any other tools. But if it is 0, quoFEM,EE,WE,Hydro will highlight the error messages in "red" by using the parser in UI. To use this parser in UI, we need to make UI believe that the analysis is successful. Something that needs improvment # noqa: PLR1722 + + if __name__ == '__main__': main(sys.argv[1:])