From 693d6634bc01e6bcc00d26a5d856b79e70065b54 Mon Sep 17 00:00:00 2001 From: ampk Date: Mon, 22 Sep 2025 15:59:39 -0700 Subject: [PATCH 1/5] Add SSI simulation support with new application and script --- modules/Workflow/WorkflowApplications.json | 16 ++++ modules/createSAM/CMakeLists.txt | 1 + modules/createSAM/ssi_model/CMakeLists.txt | 1 + modules/createSAM/ssi_model/ssi.py | 100 +++++++++++++++++++++ 4 files changed, 118 insertions(+) create mode 100644 modules/createSAM/ssi_model/CMakeLists.txt create mode 100644 modules/createSAM/ssi_model/ssi.py diff --git a/modules/Workflow/WorkflowApplications.json b/modules/Workflow/WorkflowApplications.json index 3bb364d9a..bae0b78e0 100644 --- a/modules/Workflow/WorkflowApplications.json +++ b/modules/Workflow/WorkflowApplications.json @@ -758,6 +758,22 @@ } ] }, + { + "Name": "SSISimulation", + "ExecutablePath": "applications/createSAM/ssi_model/ssi.py", + "ApplicationSpecificInputs": [ + { + "id": "fileName", + "type": "string", + "description": "Defines the name of the main OpenSees model file." + }, + { + "id": "filePath", + "type": "string", + "description": "Defines the location of the main OpenSees model file." + } + ] + }, { "Name": "CustomPyInput", "ExecutablePath": "applications/createSAM/customPyInput/customPyInput.py", diff --git a/modules/createSAM/CMakeLists.txt b/modules/createSAM/CMakeLists.txt index a5d83fbe5..55c0b5191 100644 --- a/modules/createSAM/CMakeLists.txt +++ b/modules/createSAM/CMakeLists.txt @@ -7,3 +7,4 @@ add_subdirectory(AutoSDA) add_subdirectory(RCFIAP) add_subdirectory(customPyInput) add_subdirectory(surrogateGP) +add_subdirectory(ssi_model) \ No newline at end of file diff --git a/modules/createSAM/ssi_model/CMakeLists.txt b/modules/createSAM/ssi_model/CMakeLists.txt new file mode 100644 index 000000000..ea176aeee --- /dev/null +++ b/modules/createSAM/ssi_model/CMakeLists.txt @@ -0,0 +1 @@ +simcenter_add_python_script(SCRIPT ssi.py) diff --git a/modules/createSAM/ssi_model/ssi.py b/modules/createSAM/ssi_model/ssi.py new file mode 100644 index 000000000..7840561fa --- /dev/null +++ b/modules/createSAM/ssi_model/ssi.py @@ -0,0 +1,100 @@ +# Copyright (c) 2022 Leland Stanford Junior University +# Copyright (c) 2022 The Regents of the University of California +# +# This file is part of the SimCenter Backend Applications +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 3. Neither the name of the copyright holder nor the names of its contributors +# may be used to endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# +# You should have received a copy of the BSD 3-Clause License along with +# this file. If not, see . +# +# Contributors: +# Amin Pakzad +# +# Description: +# implementing SSI simulations to the SIM tab + + +import argparse +import json +import os +import sys + +errFileName = os.path.join(os.getcwd(), 'workflow.err') + + +def create_SAM(AIM_file, EVENT_file ,SAM_file): + print("create_SAM is called") + print("AIM_file: ", AIM_file) + print("SAM_file: ", SAM_file) + SAM_json = {} + AIM_json = {} + EVENT_json = {} + with open(EVENT_file, 'r') as f: + EVENT_json = json.load(f) + with open(AIM_file, 'r') as f: + AIM_json = json.load(f) + + SAM_json = AIM_json['Modeling'] + SAM_json['GeneralInformation'] = AIM_json['GeneralInformation'] + SAM_json['subtype'] = "SSISimulation" + + + # {"mainScript": "femoramodel_example.tcl", "type": "OpenSeesInput", "NodeMapping": [], "numStory": -1, "ndm": 3, "ndf": 3, "subType": "FemoraInput", "useDamping": false, "coresPerModel": 10, "randomVar": [{"name": "softMat_vs", "value": 276.9518021028489}, {"name": "softMat_vp_vs_ratio", "value": 1.753312207525559}, {"name": "softMat_rho", "value": 2.049575892485012}], "dampingRatio": 0} + SAM_json['type'] = "OpenSeesInput" + SAM_json['mainScript'] = "" + SAM_json['NodeMapping'] = [] + SAM_json['numStory'] = -1 + SAM_json['ndm'] = 3 + SAM_json['ndf'] = 6 + SAM_json['subType'] = "SSISimulation" + SAM_json['useDamping'] = False + SAM_json['coresPerModel'] = -1 + SAM_json['randomVar'] = [] + SAM_json['dampingRatio'] = 0.0 + + with open(SAM_file, 'w') as f: + json.dump(SAM_json, f, indent=4) + print("SAM file is created") + + + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('--filenameAIM') + parser.add_argument('--filenameEVENT') + parser.add_argument('--filenameSAM') + parser.add_argument('--mainScript') + parser.add_argument('--getRV', nargs='?', const=True, default=False) + args = parser.parse_args() + print(args) + sys.exit(create_SAM(args.filenameAIM, args.filenameEVENT , args.filenameSAM)) + + + + From 6b354e6f1a1089cbadbb8d91e8ee67f5da856aee Mon Sep 17 00:00:00 2001 From: ampk Date: Mon, 22 Sep 2025 16:01:56 -0700 Subject: [PATCH 2/5] Add SSISimulation subtype support with validation for building and soil types --- .../openSees/OpenSeesSimulation.py | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/modules/performSIMULATION/openSees/OpenSeesSimulation.py b/modules/performSIMULATION/openSees/OpenSeesSimulation.py index 123e86f19..fcc1a59c0 100644 --- a/modules/performSIMULATION/openSees/OpenSeesSimulation.py +++ b/modules/performSIMULATION/openSees/OpenSeesSimulation.py @@ -106,6 +106,42 @@ def main(args): # noqa: D103 with open(samName, 'w') as samFile: json.dump(samData, samFile) + + if subtype == "SSISimulation": + # "building_type": "custom_3d_building" + if samData.get("building_type", "") not in ["custom_3d_building"]: + print(f"Error: building_type '{samData.get('building_type', '')}' is not supported for SSISimulation subtype.") + print("Only 'custom_3d_building' is supported.") + exit(1) + if samData.get("soil_type", "") not in ["soil_foundation_type_1"]: + print(f"Error: foundation_type '{samData.get('foundation_type', '')}' is not supported for SSISimulation subtype.") + print("Only 'foundation_type_1' is supported.") + exit(1) + + if samData.get("building_type", "") == "custom_3d_building" and samData.get("soil_type", "") == "soil_foundation_type_1": + main_script = samData["structure_info"].get("model_file", None) + main_script = os.path.basename(main_script) + ext = "." + main_script.rsplit('.')[-1] + main_script = main_script[:-len(ext)] # remove the extension + main_script_new = main_script + "_example.tcl" + if main_script is None: + print("Error: model_file not found in structure_info of SAM file.") + exit(1) + from femora.components.simcenter.eeuq.soil_foundation_type_one import soil_foundation_type_one + num_cores = soil_foundation_type_one(model_filename=main_script_new, + info_file=samName) + num_cores = int(num_cores) + samData["coresPerModel"] = num_cores + samData["mainScript"] = main_script_new + + + with open(samName, 'w') as samFile: + json.dump(samData, samFile) + + + + + 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 @@ -113,7 +149,7 @@ def main(args): # noqa: D103 # exit(exit_code) # Run OpenSees - if subtype == "FemoraInput": + if subtype == "FemoraInput" or subtype == "SSISimulation": coresPerModel = samData.get("coresPerModel", 1) # Run OpenSees in parallel using mpirun if runtype == "runningLocal": From badb720589af5568cf792f1a8d27c3b3633368dd Mon Sep 17 00:00:00 2001 From: ampk Date: Tue, 23 Sep 2025 05:50:27 -0700 Subject: [PATCH 3/5] Update SAM_json structure for SSISimulation with dynamic values from AIM_json --- modules/createSAM/ssi_model/ssi.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/createSAM/ssi_model/ssi.py b/modules/createSAM/ssi_model/ssi.py index 7840561fa..fc6e93e31 100644 --- a/modules/createSAM/ssi_model/ssi.py +++ b/modules/createSAM/ssi_model/ssi.py @@ -66,15 +66,15 @@ def create_SAM(AIM_file, EVENT_file ,SAM_file): # {"mainScript": "femoramodel_example.tcl", "type": "OpenSeesInput", "NodeMapping": [], "numStory": -1, "ndm": 3, "ndf": 3, "subType": "FemoraInput", "useDamping": false, "coresPerModel": 10, "randomVar": [{"name": "softMat_vs", "value": 276.9518021028489}, {"name": "softMat_vp_vs_ratio", "value": 1.753312207525559}, {"name": "softMat_rho", "value": 2.049575892485012}], "dampingRatio": 0} SAM_json['type'] = "OpenSeesInput" - SAM_json['mainScript'] = "" - SAM_json['NodeMapping'] = [] + SAM_json['mainScript'] = "" # will be set in the workflow + SAM_json['NodeMapping'] = AIM_json["Modeling"]["structure_info"].get("NodeMapping", []) SAM_json['numStory'] = -1 - SAM_json['ndm'] = 3 - SAM_json['ndf'] = 6 + SAM_json['ndm'] = AIM_json["Modeling"]["structure_info"].get("ndm", 3) + SAM_json['ndf'] = AIM_json["Modeling"]["structure_info"].get("ndf", 6) SAM_json['subType'] = "SSISimulation" SAM_json['useDamping'] = False - SAM_json['coresPerModel'] = -1 - SAM_json['randomVar'] = [] + SAM_json['coresPerModel'] = -1 # will be set in the workflow + SAM_json['randomVar'] = AIM_json["Modeling"].get("randomVar", []) SAM_json['dampingRatio'] = 0.0 with open(SAM_file, 'w') as f: From 25d556e7dd64ea9ab304b404a05fb85d43670fac Mon Sep 17 00:00:00 2001 From: ampk Date: Tue, 23 Sep 2025 05:50:46 -0700 Subject: [PATCH 4/5] Add EEUQ parameter to soil_foundation_type_one for core allocation in SSISimulation --- modules/performSIMULATION/openSees/OpenSeesSimulation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/performSIMULATION/openSees/OpenSeesSimulation.py b/modules/performSIMULATION/openSees/OpenSeesSimulation.py index fcc1a59c0..86aa218bd 100644 --- a/modules/performSIMULATION/openSees/OpenSeesSimulation.py +++ b/modules/performSIMULATION/openSees/OpenSeesSimulation.py @@ -129,7 +129,8 @@ def main(args): # noqa: D103 exit(1) from femora.components.simcenter.eeuq.soil_foundation_type_one import soil_foundation_type_one num_cores = soil_foundation_type_one(model_filename=main_script_new, - info_file=samName) + info_file=samName, + EEUQ=True) num_cores = int(num_cores) samData["coresPerModel"] = num_cores samData["mainScript"] = main_script_new From 4d3a341e33ac2b847b9268e340761e5cb9437ca0 Mon Sep 17 00:00:00 2001 From: ampk Date: Tue, 23 Sep 2025 05:51:04 -0700 Subject: [PATCH 5/5] Add PID check in processEvents for OpenSeesPreprocessor --- modules/performSIMULATION/openSees/OpenSeesPreprocessor.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/performSIMULATION/openSees/OpenSeesPreprocessor.cpp b/modules/performSIMULATION/openSees/OpenSeesPreprocessor.cpp index 0a2e039fb..0f391fffb 100644 --- a/modules/performSIMULATION/openSees/OpenSeesPreprocessor.cpp +++ b/modules/performSIMULATION/openSees/OpenSeesPreprocessor.cpp @@ -672,6 +672,8 @@ OpenSeesPreprocessor::processEvents(ofstream &s){ // loop through EDPs and find corresponding EDP char edpEventName[50]; + s << "set pid [getPID]\n"; + s << "if {$pid == 0} {\n"; for (int j=0; j