App Schema: opensees-mp-s3#
Dig Deep into an App Schema to Create the Input
by Silvia Mazzoni, DesignSafe, 2025
We are going to walk through the app schema to develop our job input, and then we will submit the job.
We will use the OpenSeesMP app.
(opensees-mp-s3 GitHub Page)[https://github.com/TACC/WMA-Tapis-Templates/tree/main/applications/opensees-mp/opensees-mp-s3]
(Tapis Apps Documentation)[https://tapis.readthedocs.io/en/latest/technical/apps.html]
(Tapis Jobs Documentation)[https://tapis.readthedocs.io/en/latest/technical/jobs.html]
from tapipy.tapis import TapisResult
Connect to Tapis#
t=OpsUtils.connect_tapis()
-- Checking Tapis token --
Token loaded from file. Token is still valid!
Token expires at: 2025-09-19T21:03:18+00:00
Token expires in: 3:05:32.667584
-- LOG IN SUCCESSFUL! --
print('QUEUE INFO')
OpsUtils.get_system_queues(t,system_id="stampede3",display=True);
QUEUE INFO
| name | icx | skx | skx-dev | pvc | spr | nvdimm | h100 |
|---|---|---|---|---|---|---|---|
| description | icx (CPU, standard compute) | skx (CPU, recommended standard compute) | skx-dev (CPU, 2 hour max, 1 job max, for testing) | pvc (GPU, Intel no CUDA) | spr (CPU, high memory bandwidth) | nvdimm (CPU, large memory) | None |
| hpcQueueName | icx | skx | skx-dev | pvc | spr | nvdimm | h100 |
| maxJobs | -1 | -1 | -1 | -1 | -1 | -1 | -1 |
| maxJobsPerUser | 20 | 60 | 3 | 4 | 36 | 3 | 4 |
| minNodeCount | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| maxNodeCount | 32 | 256 | 16 | 4 | 32 | 1 | 4 |
| minCoresPerNode | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| maxCoresPerNode | 80 | 48 | 48 | 96 | 112 | 80 | 96 |
| minMemoryMB | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| maxMemoryMB | 256000 | 192000 | 192000 | 128000 | 128000 | 4000000 | 1000000 |
| minMinutes | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| maxMinutes | 2880 | 2880 | 120 | 2880 | 2880 | 2880 | 2880 |
App User Input#
Initialize#
# initalize
tapisInput = {}
tapisInput["name"] = 'OpenSeesMPsubmit'
appId = 'opensees-mp-s3'
appVersion = 'latest'
Get app schema – input#
thisAppData_MP = OpsUtils.get_tapis_app_schema(t,appId,version=appVersion)
OpsUtils.display_tapis_app_schema(thisAppData_MP)
########################################
########### TAPIS-APP SCHEMA ###########
########################################
######## appID: opensees-mp-s3
######## version: latest
########################################
{
sharedAppCtx: "wma_prtl"
isPublic: True
tenant: "designsafe"
id: "opensees-mp-s3"
version: "latest"
description: "Runs all the processors in parallel. Requires understanding of parallel processing and the capabilities to write parallel scripts."
owner: "wma_prtl"
enabled: True
versionEnabled: True
locked: False
runtime: "ZIP"
runtimeVersion: None
runtimeOptions: None
containerImage: "tapis://cloud.data/corral/tacc/aci/CEP/applications/v3/opensees/latest/OpenSees/opensees.zip"
jobType: "BATCH"
maxJobs: 2147483647
maxJobsPerUser: 2147483647
strictFileInputs: True
uuid: "1410a584-0c5e-4e47-b3b0-3a7bea0e1187"
deleted: False
created: "2025-02-20T18:01:49.005183Z"
updated: "2025-08-28T20:17:39.426067Z"
sharedWithUsers: []
tags: ["portalName: DesignSafe", "portalName: CEP"]
jobAttributes: {
description: None
dynamicExecSystem: False
execSystemConstraints: None
execSystemId: "stampede3"
execSystemExecDir: "${JobWorkingDir}"
execSystemInputDir: "${JobWorkingDir}"
execSystemOutputDir: "${JobWorkingDir}"
dtnSystemInputDir: "!tapis_not_set"
dtnSystemOutputDir: "!tapis_not_set"
execSystemLogicalQueue: "skx"
archiveSystemId: "stampede3"
archiveSystemDir: "HOST_EVAL($WORK)/tapis-jobs-archive/${JobCreateDate}/${JobName}-${JobUUID}"
archiveOnAppError: True
isMpi: False
mpiCmd: None
cmdPrefix: None
nodeCount: 2
coresPerNode: 48
memoryMB: 192000
maxMinutes: 120
fileInputs: [
{
name: "Input Directory"
description: "Input directory that includes the tcl script as well as any other required files. Example input is in tapis://designsafe.storage.community/app_examples/opensees/OpenSeesMP"
inputMode: "REQUIRED"
autoMountLocal: True
envKey: "inputDirectory"
sourceUrl: None
targetPath: "inputDirectory"
notes: {
selectionMode: "directory"
}
}
]
fileInputArrays: []
subscriptions: []
tags: []
parameterSet: {
appArgs: [
{
arg: "OpenSeesMP"
name: "mainProgram"
description: None
inputMode: "FIXED"
notes: {
isHidden: True
}
}
{
arg: None
name: "Main Script"
description: "The filename only of the OpenSees TCL script to execute. This file should reside in the Input Directory specified. To use with test input, use 'freeFieldEffective.tcl'"
inputMode: "REQUIRED"
notes: {
inputType: "fileInput"
}
}
]
containerArgs: []
schedulerOptions: [
{
arg: "--tapis-profile OpenSees_default"
name: "OpenSees TACC Scheduler Profile"
description: "Scheduler profile for the default version of OpenSees"
inputMode: "FIXED"
notes: {
isHidden: True
}
}
{
arg: None
name: "TACC Reservation"
description: "Reservation input string"
inputMode: "INCLUDE_ON_DEMAND"
notes: {
isHidden: True
}
}
]
envVariables: []
archiveFilter: {
includeLaunchFiles: True
includes: []
excludes: []
}
logConfig: {
stdoutFilename: ""
stderrFilename: ""
}
}
}
notes: {
icon: "OpenSees"
label: "OpenSeesMP"
helpUrl: "https://www.designsafe-ci.org/user-guide/tools/simulation/#opensees-user-guide"
category: "Simulation"
isInteractive: False
showReservation: True
hideNodeCountAndCoresPerNode: False
}
}
########################################
Create a Job input#
# Initialize our input
TapisInput = {}
Break app schema into detailed parts and review them for possible input arguments#
# Convert TapisResults Objects to dictionaries
app_MetaData = thisAppData_MP.__dict__
# Review the keys to see if there is any input we are interested in.
# You can view the full schema above to see the values
# print('app_MetaData.keys',app_MetaData.keys())
dictKeys = []
TapisResultKeys = []
listKeys = []
print('*** MAIN INPUT***')
for thisKey,thisValue in app_MetaData.items():
if isinstance(thisValue, dict):
dictKeys.append(thisKey)
if isinstance(thisValue, TapisResult):
TapisResultKeys.append(thisKey)
elif isinstance(thisValue, list):
listKeys.append(thisKey)
else:
print(f'{thisKey} = {thisValue}')
print('\n--- Nested Objects---')
print('dict-type input keys',dictKeys)
print('list-type input keys',listKeys)
print('TapisResult-type input keys',TapisResultKeys)
*** MAIN INPUT***
sharedAppCtx = wma_prtl
isPublic = True
tenant = designsafe
id = opensees-mp-s3
version = latest
description = Runs all the processors in parallel. Requires understanding of parallel processing and the capabilities to write parallel scripts.
owner = wma_prtl
enabled = True
versionEnabled = True
locked = False
runtime = ZIP
runtimeVersion = None
runtimeOptions = None
containerImage = tapis://cloud.data/corral/tacc/aci/CEP/applications/v3/opensees/latest/OpenSees/opensees.zip
jobType = BATCH
maxJobs = 2147483647
maxJobsPerUser = 2147483647
strictFileInputs = True
uuid = 1410a584-0c5e-4e47-b3b0-3a7bea0e1187
deleted = False
created = 2025-02-20T18:01:49.005183Z
updated = 2025-08-28T20:17:39.426067Z
--- Nested Objects---
dict-type input keys []
list-type input keys ['sharedWithUsers', 'tags']
TapisResult-type input keys ['jobAttributes', 'notes']
Check App Basics#
A few things to check here:
app name and version are what you want
isPublic = True (you can use the app)
if isPublic = False, make sure owner = usename
enabled = True (app is usable)
deleted = False (it exists)
read the description
print(f'***** list-type INPUT ****')
if len(listKeys)>0:
for thisKey in listKeys:
thisList = app_MetaData[thisKey]
print(f'{thisKey} : {thisList}')
else:
print('-none')
***** list-type INPUT ****
sharedWithUsers : []
tags : ['portalName: DesignSafe', 'portalName: CEP']
# Nothing related to input in the lists.
print(f'***** dict-type INPUT ****')
if len(dictKeys)>0:
for thisKey in dictKeys:
thisDict = app_MetaData[thisKey]
print(f'{thisKey} : {thisDict}')
else:
print('there are no dictionaries within jobAttributes, as expected, since Tapis works with TapisResults objects instead')
***** dict-type INPUT ****
there are no dictionaries within jobAttributes, as expected, since Tapis works with TapisResults objects instead
print(f'***** TapisResult-type INPUT ****')
TR_dictKeys = {}
TR_TapisResultKeys = {}
TR_listKeys = {}
for hereKey in TapisResultKeys:
print(f'\n*** {hereKey} ***')
thisTapisResult = app_MetaData[hereKey]
thisTapisResult_dict = thisTapisResult.__dict__
TR_dictKeys[hereKey] = []
TR_TapisResultKeys[hereKey] = []
TR_listKeys[hereKey] = []
for thisKey,thisValue in thisTapisResult_dict.items():
if isinstance(thisValue, dict):
TR_dictKeys[hereKey].append(thisKey)
if isinstance(thisValue, TapisResult):
TR_TapisResultKeys[hereKey].append(thisKey)
elif isinstance(thisValue, list):
TR_listKeys[hereKey].append(thisKey)
else:
print(f' {thisKey} = {thisValue}')
print(f'\n --- {hereKey} -- Nested Objects---')
print(f' dict-type input keys',TR_dictKeys[hereKey])
print(f' list-type input keys',TR_listKeys[hereKey])
print(f' TapisResult-type input keys',TR_TapisResultKeys[hereKey])
print('')
***** TapisResult-type INPUT ****
*** jobAttributes ***
description = None
dynamicExecSystem = False
execSystemConstraints = None
execSystemId = stampede3
execSystemExecDir = ${JobWorkingDir}
execSystemInputDir = ${JobWorkingDir}
execSystemOutputDir = ${JobWorkingDir}
dtnSystemInputDir = !tapis_not_set
dtnSystemOutputDir = !tapis_not_set
execSystemLogicalQueue = skx
archiveSystemId = stampede3
archiveSystemDir = HOST_EVAL($WORK)/tapis-jobs-archive/${JobCreateDate}/${JobName}-${JobUUID}
archiveOnAppError = True
isMpi = False
mpiCmd = None
cmdPrefix = None
nodeCount = 2
coresPerNode = 48
memoryMB = 192000
maxMinutes = 120
--- jobAttributes -- Nested Objects---
dict-type input keys []
list-type input keys ['fileInputs', 'fileInputArrays', 'subscriptions', 'tags']
TapisResult-type input keys ['parameterSet']
*** notes ***
icon = OpenSees
label = OpenSeesMP
helpUrl = https://www.designsafe-ci.org/user-guide/tools/simulation/#opensees-user-guide
category = Simulation
isInteractive = False
showReservation = True
hideNodeCountAndCoresPerNode = False
--- notes -- Nested Objects---
dict-type input keys []
list-type input keys []
TapisResult-type input keys []
notes {}#
notes is just informational.
jobAttributes {}#
This is the content we will be submitting to the app.
jobAttributes has valuable input arguments as well as nested ones.
We need to initialize this json object in our TapisInput.
Let’s look at the high-level input
Let’s look at the nested content
Initialize TapisInput[‘jobAttributes’]
# jobAttributes has valuable input arguments as well as nested ones.
TapisInput['jobAttributes'] = {}
# start this input with app id and version to jobAttributes since that is what we send to tapis
TapisInput['jobAttributes']["name"] = f'My first Tapis Job on {appId}'
TapisInput['jobAttributes']["appId"] = appId
TapisInput['jobAttributes']["appVersion"] = appVersion
Look at high-level variables to see if there is anything of value
This is where you find information about where the job is run (execSystemId)
In HPC applications this is where you define the SLURM input on queues and nodes, etc
TapisInput['jobAttributes']['execSystemId'] = 'stampede3'
# slurmm-job input
TapisInput['jobAttributes']['execSystemLogicalQueue'] = 'skx-dev'
TapisInput['jobAttributes']['nodeCount'] = 1
TapisInput['jobAttributes']['coresPerNode'] = 16
TapisInput['jobAttributes']['maxMinutes'] = 7
3. Let’s dig into the first level – app.jobAttributes#
# Let's extract and study jobAttributes
myKey = 'jobAttributes'
app_jobAttributes = app_MetaData[myKey].__dict__
# we have already extracted the contents of this dict
print(f'***** {myKey} dict-type Input ****')
if len(TR_dictKeys[myKey])>0:
for thisKey in TR_dictKeys[myKey]:
thisDict = app_jobAttributes[thisKey]
print(f'{myKey}.{thisKey} : {thisDict}')
else:
print('there are no dictionaries within jobAttributes, as expected, since Tapis works with TapisResults objects instead')
***** jobAttributes dict-type Input ****
there are no dictionaries within jobAttributes, as expected, since Tapis works with TapisResults objects instead
print(f'***** {myKey} list-type input****')
if len(TR_listKeys[myKey])>0:
for thisKey in TR_listKeys[myKey]:
thisList = app_jobAttributes[thisKey]
if len(thisList)>0:
print(f' {thisKey} = ')
print(' [')
for thisValue in thisList:
if isinstance(thisValue, TapisResult):
thisValue = thisValue.__dict__
print(f' {thisValue}')
print(' ]')
else:
print(f' {thisKey}: {thisList}')
else:
print('none')
***** jobAttributes list-type input****
fileInputs =
[
{'name': 'Input Directory', 'description': 'Input directory that includes the tcl script as well as any other required files. Example input is in tapis://designsafe.storage.community/app_examples/opensees/OpenSeesMP', 'inputMode': 'REQUIRED', 'autoMountLocal': True, 'envKey': 'inputDirectory', 'notes':
selectionMode: directory, 'sourceUrl': None, 'targetPath': 'inputDirectory'}
]
fileInputArrays: []
subscriptions: []
tags: []
fileInputs#
Here we find that jobAttributes.fileInputs is a REQUIRED input.
In this case we need to get the tapisURI for our input directory.
Storage SystemTapis & Tapis Base Path in URI format#
this is the very first part of your path, just above your home folder.
Options:
CommunityData
Published
The following options are user or project-dependent, and require unique path input.
The following option requires additional user-dependent input:
MyData
The following option requires additional user- and system- dependent input:
Work
The following option requires additional project-dependent input:
MyProjects
You can obtain a dependent tapis-URI path by performing the first step of submitting an OpenSeesMP job at the app portal: https://www.designsafe-ci.org/workspace/opensees-mp-s3
storage_system = 'MyData' # options: Community,MyData,Published,MyProjects,Work/stampede3,Work/frontera,Work/ls6
storage_system_baseURL = OpsUtils.get_user_path_tapis_uri(t,storage_system)
print('storage_system_baseURL:',storage_system_baseURL)
found paths file: /home/jupyter/MyData/.tapis_user_paths.json
storage_system_baseURL: tapis://designsafe.storage.default/silvia
input_folder = '_ToCommunityData/OpenSees/TrainingMaterial/training-OpenSees-on-DesignSafe/Examples_OpenSees/BasicExamples'
sourceUrl = f'{storage_system_baseURL}/{input_folder}'
print('sourceUrl',sourceUrl)
sourceUrl tapis://designsafe.storage.default/silvia/_ToCommunityData/OpenSees/TrainingMaterial/training-OpenSees-on-DesignSafe/Examples_OpenSees/BasicExamples
TapisInput['jobAttributes']['fileInputs'] = [{'name': 'Input Directory','sourceUrl':sourceUrl}]; # notice that it is a list!
print(f'***** {myKey} TapisResult-type input ****')
if len(TR_TapisResultKeys[myKey])>0:
for hereKey in TR_TapisResultKeys[myKey]:
print(f'\n*** {hereKey} ***')
thisTapisResult = app_jobAttributes[hereKey]
thisTapisResult_dict = thisTapisResult.__dict__
TR_dictKeys[hereKey] = []
TR_TapisResultKeys[hereKey] = []
TR_listKeys[hereKey] = []
for thisKey,thisValue in thisTapisResult_dict.items():
if isinstance(thisValue, dict):
TR_dictKeys[hereKey].append(thisKey)
if isinstance(thisValue, TapisResult):
TR_TapisResultKeys[hereKey].append(thisKey)
elif isinstance(thisValue, list):
TR_listKeys[hereKey].append(thisKey)
else:
print(f' {myKey}.{thisKey} = {thisValue}')
print(f'\n --- {hereKey} -- Nested Objects---')
print(f' {myKey}.{hereKey} dict-type input keys',TR_dictKeys[hereKey])
print(f' {myKey}.{hereKey} list-type input keys',TR_listKeys[hereKey])
print(f' {myKey}.{hereKey} TapisResult-type input keys',TR_TapisResultKeys[hereKey])
print('')
else:
print('-none')
***** jobAttributes TapisResult-type input ****
*** parameterSet ***
--- parameterSet -- Nested Objects---
jobAttributes.parameterSet dict-type input keys []
jobAttributes.parameterSet list-type input keys ['appArgs', 'containerArgs', 'schedulerOptions', 'envVariables']
jobAttributes.parameterSet TapisResult-type input keys ['archiveFilter', 'logConfig']
app.jobAttributes.parameterSet is the interesting one#
# Let's extract and study jobAttributes
myKey = 'parameterSet'
app_parameterSet = app_jobAttributes[myKey].__dict__
# we have already extracted the contents of this dict
## parameterSet is a dictionary (TapisResult):
TapisInput['jobAttributes'][myKey] = {}
print(f'***** {myKey} dict-type Input ****')
if len(TR_dictKeys[myKey])>0:
for thisKey in TR_dictKeys[myKey]:
thisDict = app_parameterSet[thisKey]
print(f'{myKey}.{thisKey} : {thisDict}')
else:
print('there are no dictionaries within app_parameterSet, as expected, since Tapis works with TapisResults objects instead')
***** parameterSet dict-type Input ****
there are no dictionaries within app_parameterSet, as expected, since Tapis works with TapisResults objects instead
print(f'***** {myKey} list-type input****')
if len(TR_listKeys[myKey])>0:
for thisKey in TR_listKeys[myKey]:
thisList = app_parameterSet[thisKey]
if len(thisList)>0:
print(f' {thisKey} = ')
print(' [')
for thisValue in thisList:
if isinstance(thisValue, TapisResult):
thisValue = thisValue.__dict__
print(f' {str(thisValue)}')
print(' ]')
else:
print(f' {thisKey}: {thisList}')
else:
print('none')
***** parameterSet list-type input****
appArgs =
[
{'arg': 'OpenSeesMP', 'name': 'mainProgram', 'description': None, 'inputMode': 'FIXED', 'notes':
isHidden: True}
{'arg': None, 'name': 'Main Script', 'description': "The filename only of the OpenSees TCL script to execute. This file should reside in the Input Directory specified. To use with test input, use 'freeFieldEffective.tcl'", 'inputMode': 'REQUIRED', 'notes':
inputType: fileInput}
]
containerArgs: []
schedulerOptions =
[
{'arg': '--tapis-profile OpenSees_default', 'name': 'OpenSees TACC Scheduler Profile', 'description': 'Scheduler profile for the default version of OpenSees', 'inputMode': 'FIXED', 'notes':
isHidden: True}
{'arg': None, 'name': 'TACC Reservation', 'description': 'Reservation input string', 'inputMode': 'INCLUDE_ON_DEMAND', 'notes':
isHidden: True}
]
envVariables: []
print('review each of these items:', TR_listKeys[myKey])
review each of these items: ['appArgs', 'containerArgs', 'schedulerOptions', 'envVariables']
app.jobAttributes.parameterSet.appArgs#
thisKey = 'appArgs'
TapisInput['jobAttributes']['parameterSet'][thisKey] = [] # it's a list, initialize as a list!
print(f'** app.jobAttributes.parameterSet.{thisKey} **')
if len(app_parameterSet[thisKey])>0:
for thisItem in app_parameterSet[thisKey]:
print(thisItem)
else:
print('.none.')
** app.jobAttributes.parameterSet.appArgs **
arg: OpenSeesMP
description: None
inputMode: FIXED
name: mainProgram
notes:
isHidden: True
arg: None
description: The filename only of the OpenSees TCL script to execute. This file should reside in the Input Directory specified. To use with test input, use 'freeFieldEffective.tcl'
inputMode: REQUIRED
name: Main Script
notes:
inputType: fileInput
The first item is the mainProgram, and it has been set as FIXED and hidden, so we don’t need it
The second item is the input script The values need to be appended as key-value dictionaries, no need for the other items.
TapisInput['jobAttributes']['parameterSet'][thisKey].append({'name':'Main Script','arg': 'Ex1a_verymany.Canti2D.Push.mp.tcl'})
app.jobAttributes.parameterSet.containerArgs#
thisKey = 'containerArgs'
TapisInput['jobAttributes']['parameterSet'][thisKey] = [] # it's a list, initialize as a list!
print(f'** app.jobAttributes.parameterSet.{thisKey} **')
if len(app_parameterSet[thisKey])>0:
for thisItem in app_parameterSet[thisKey]:
print(thisItem)
else:
print('.none.')
** app.jobAttributes.parameterSet.containerArgs **
.none.
# do nothing for this app.
app.jobAttributes.parameterSet.schedulerOptions#
thisKey = 'schedulerOptions'
TapisInput['jobAttributes']['parameterSet'][thisKey] = [] # it's a list, initialize as a list!
print(f'** app.jobAttributes.parameterSet.{thisKey} **')
if len(app_parameterSet[thisKey])>0:
for thisItem in app_parameterSet[thisKey]:
print(thisItem)
else:
print('.none.')
** app.jobAttributes.parameterSet.schedulerOptions **
arg: --tapis-profile OpenSees_default
description: Scheduler profile for the default version of OpenSees
inputMode: FIXED
name: OpenSees TACC Scheduler Profile
notes:
isHidden: True
arg: None
description: Reservation input string
inputMode: INCLUDE_ON_DEMAND
name: TACC Reservation
notes:
isHidden: True
# both of the first two items are hidden. -- we'll talk about the scheduler option some other time.
Add allocation to the scheduler option – not shown in the app schema#
user_allocation = '-A DS-HPC1'; # you get this code from your allocation dashboard
TapisInput['jobAttributes']['parameterSet']['schedulerOptions'].append({'name': 'TACC Allocation', 'arg': user_allocation})
app.jobAttributes.parameterSet.envVariables#
thisKey = 'envVariables'
TapisInput['jobAttributes']['parameterSet'][thisKey] = [] # it's a list, initialize as a list!
print(f'** app.jobAttributes.parameterSet.{thisKey} **')
if len(app_parameterSet[thisKey])>0:
for thisItem in app_parameterSet[thisKey]:
print(thisItem)
else:
print('.none.')
** app.jobAttributes.parameterSet.envVariables **
.none.
# other apps may have input here
print(f'***** {myKey} TapisResult-type input ****')
if len(TR_TapisResultKeys[myKey])>0:
for hereKey in TR_TapisResultKeys[myKey]:
print(f'\n*** {hereKey} ***')
thisTapisResult = app_parameterSet[hereKey]
thisTapisResult_dict = thisTapisResult.__dict__
TR_dictKeys[hereKey] = []
TR_TapisResultKeys[hereKey] = []
TR_listKeys[hereKey] = []
for thisKey,thisValue in thisTapisResult_dict.items():
if isinstance(thisValue, dict):
TR_dictKeys[hereKey].append(thisKey)
if isinstance(thisValue, TapisResult):
TR_TapisResultKeys[hereKey].append(thisKey)
elif isinstance(thisValue, list):
TR_listKeys[hereKey].append(thisKey)
else:
print(f' {myKey}.{thisKey} = {thisValue}')
print(f'\n --- {hereKey} -- Nested Objects---')
print(f' {myKey}.{hereKey} dict-type input keys',TR_dictKeys[hereKey])
print(f' {myKey}.{hereKey} list-type input keys',TR_listKeys[hereKey])
print(f' {myKey}.{hereKey} TapisResult-type input keys',TR_TapisResultKeys[hereKey])
print('')
else:
print('-none')
***** parameterSet TapisResult-type input ****
*** archiveFilter ***
parameterSet.includeLaunchFiles = True
--- archiveFilter -- Nested Objects---
parameterSet.archiveFilter dict-type input keys []
parameterSet.archiveFilter list-type input keys ['includes', 'excludes']
parameterSet.archiveFilter TapisResult-type input keys []
*** logConfig ***
parameterSet.stdoutFilename =
parameterSet.stderrFilename =
--- logConfig -- Nested Objects---
parameterSet.logConfig dict-type input keys []
parameterSet.logConfig list-type input keys []
parameterSet.logConfig TapisResult-type input keys []
# nothing of interest to us here...
We are done with our tapis-job input#
print('TapisInput')
display(TapisInput)
TapisInput
{'jobAttributes': {'name': 'My first Tapis Job on opensees-mp-s3',
'appId': 'opensees-mp-s3',
'appVersion': 'latest',
'execSystemId': 'stampede3',
'execSystemLogicalQueue': 'skx-dev',
'nodeCount': 1,
'coresPerNode': 16,
'maxMinutes': 7,
'fileInputs': [{'name': 'Input Directory',
'sourceUrl': 'tapis://designsafe.storage.default/silvia/_ToCommunityData/OpenSees/TrainingMaterial/training-OpenSees-on-DesignSafe/Examples_OpenSees/BasicExamples'}],
'parameterSet': {'appArgs': [{'name': 'Main Script',
'arg': 'Ex1a_verymany.Canti2D.Push.mp.tcl'}],
'containerArgs': [],
'schedulerOptions': [{'name': 'TACC Allocation', 'arg': '-A DS-HPC1'}],
'envVariables': []}}}
print('TapisInput.jobAttributes')
display(TapisInput['jobAttributes'])
TapisInput.jobAttributes
{'name': 'My first Tapis Job on opensees-mp-s3',
'appId': 'opensees-mp-s3',
'appVersion': 'latest',
'execSystemId': 'stampede3',
'execSystemLogicalQueue': 'skx-dev',
'nodeCount': 1,
'coresPerNode': 16,
'maxMinutes': 7,
'fileInputs': [{'name': 'Input Directory',
'sourceUrl': 'tapis://designsafe.storage.default/silvia/_ToCommunityData/OpenSees/TrainingMaterial/training-OpenSees-on-DesignSafe/Examples_OpenSees/BasicExamples'}],
'parameterSet': {'appArgs': [{'name': 'Main Script',
'arg': 'Ex1a_verymany.Canti2D.Push.mp.tcl'}],
'containerArgs': [],
'schedulerOptions': [{'name': 'TACC Allocation', 'arg': '-A DS-HPC1'}],
'envVariables': []}}
submitted_job = t.jobs.submitJob(**TapisInput['jobAttributes'])
print(submitted_job)
_fileInputsSpec: None
_parameterSetModel: None
appId: opensees-mp-s3
appVersion: latest
archiveCorrelationId: None
archiveOnAppError: True
archiveSystemDir: /work2/05072/silvia/stampede3/tapis-jobs-archive/2025-09-19Z/My first Tapis Job on opensees-mp-s3-2f45deef-02ec-4a48-9e47-69e576fb3e82-007
archiveSystemId: stampede3
archiveTransactionId: None
blockedCount: 0
cmdPrefix: None
condition: None
coresPerNode: 16
created: 2025-09-19T17:57:47.592790600Z
createdby: silvia
createdbyTenant: designsafe
description: opensees-mp-s3-latest submitted by silvia@designsafe
dtnInputCorrelationId: None
dtnInputTransactionId: None
dtnOutputCorrelationId: None
dtnOutputTransactionId: None
dtnSystemId: None
dtnSystemInputDir: None
dtnSystemOutputDir: None
dynamicExecSystem: False
ended: None
execSystemConstraints: None
execSystemExecDir: /scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007
execSystemId: stampede3
execSystemInputDir: /scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007
execSystemLogicalQueue: skx-dev
execSystemOutputDir: /scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007
fileInputs: [{"name":"Input Directory","description":"Input directory that includes the tcl script as well as any other required files. Example input is in tapis://designsafe.storage.community/app_examples/opensees/OpenSeesMP","envKey":"inputDirectory","autoMountLocal":true,"sourceUrl":"tapis://designsafe.storage.default/silvia/_ToCommunityData/OpenSees/TrainingMaterial/training-OpenSees-on-DesignSafe/Examples_OpenSees/BasicExamples","targetPath":"inputDirectory","notes":"{\"selectionMode\":\"directory\"}","optional":false,"srcSharedAppCtx":"","destSharedAppCtx":"wma_prtl"}]
id: 0
inputCorrelationId: None
inputTransactionId: None
isMpi: False
jobType: BATCH
lastMessage: Job created
lastUpdated: 2025-09-19T17:57:47.592790600Z
maxMinutes: 7
memoryMB: 192000
mpiCmd: None
name: My first Tapis Job on opensees-mp-s3
nodeCount: 1
notes: {"icon":"OpenSees","label":"OpenSeesMP","helpUrl":"https://www.designsafe-ci.org/user-guide/tools/simulation/#opensees-user-guide","category":"Simulation","isInteractive":false,"showReservation":true,"hideNodeCountAndCoresPerNode":false}
owner: silvia
parameterSet: {"appArgs":[{"name":"mainProgram","description":null,"include":null,"arg":"OpenSeesMP","notes":"{\"isHidden\":true}"},{"name":"Main Script","description":"The filename only of the OpenSees TCL script to execute. This file should reside in the Input Directory specified. To use with test input, use 'freeFieldEffective.tcl'","include":null,"arg":"Ex1a_verymany.Canti2D.Push.mp.tcl","notes":"{\"inputType\":\"fileInput\"}"}],"containerArgs":[],"schedulerOptions":[{"name":"OpenSees TACC Scheduler Profile","description":"Scheduler profile for the default version of OpenSees","include":null,"arg":"--tapis-profile OpenSees_default","notes":"{\"isHidden\":true}"},{"name":"TACC Allocation","description":null,"include":null,"arg":"-A DS-HPC1","notes":null}],"envVariables":[{"key":"_tapisAppId","value":"opensees-mp-s3","description":null,"include":null,"notes":null},{"key":"_tapisAppVersion","value":"latest","description":null,"include":null,"notes":null},{"key":"_tapisArchiveOnAppError","value":"true","description":null,"include":null,"notes":null},{"key":"_tapisArchiveSystemDir","value":"/work2/05072/silvia/stampede3/tapis-jobs-archive/2025-09-19Z/My first Tapis Job on opensees-mp-s3-2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisArchiveSystemId","value":"stampede3","description":null,"include":null,"notes":null},{"key":"_tapisCoresPerNode","value":"16","description":null,"include":null,"notes":null},{"key":"_tapisDynamicExecSystem","value":"false","description":null,"include":null,"notes":null},{"key":"_tapisEffectiveUserId","value":"silvia","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemExecDir","value":"/scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemHPCQueue","value":"skx-dev","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemId","value":"stampede3","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemInputDir","value":"/scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemLogicalQueue","value":"skx-dev","description":null,"include":null,"notes":null},{"key":"_tapisExecSystemOutputDir","value":"/scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisJobCreateDate","value":"2025-09-19Z","description":null,"include":null,"notes":null},{"key":"_tapisJobCreateTime","value":"17:57:47.5927906Z","description":null,"include":null,"notes":null},{"key":"_tapisJobCreateTimestamp","value":"2025-09-19T17:57:47.592790600Z","description":null,"include":null,"notes":null},{"key":"_tapisJobName","value":"My first Tapis Job on opensees-mp-s3","description":null,"include":null,"notes":null},{"key":"_tapisJobOwner","value":"silvia","description":null,"include":null,"notes":null},{"key":"_tapisJobUUID","value":"2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisJobWorkingDir","value":"/scratch/05072/silvia/tapis/2f45deef-02ec-4a48-9e47-69e576fb3e82-007","description":null,"include":null,"notes":null},{"key":"_tapisMaxMinutes","value":"7","description":null,"include":null,"notes":null},{"key":"_tapisMemoryMB","value":"192000","description":null,"include":null,"notes":null},{"key":"_tapisNodes","value":"1","description":null,"include":null,"notes":null},{"key":"_tapisStderrFilename","value":"tapisjob.out","description":null,"include":null,"notes":null},{"key":"_tapisStdoutFilename","value":"tapisjob.out","description":null,"include":null,"notes":null},{"key":"_tapisSysBatchScheduler","value":"SLURM","description":null,"include":null,"notes":null},{"key":"_tapisSysHost","value":"stampede3.tacc.utexas.edu","description":null,"include":null,"notes":null},{"key":"_tapisSysRootDir","value":"/","description":null,"include":null,"notes":null},{"key":"_tapisTenant","value":"designsafe","description":null,"include":null,"notes":null},{"key":"inputDirectory","value":"inputDirectory","description":"EnvKey from input file: Input Directory","include":true,"notes":"{}"}],"archiveFilter":{"includes":[],"excludes":[],"includeLaunchFiles":true},"logConfig":{"stdoutFilename":"tapisjob.out","stderrFilename":"tapisjob.out"}}
remoteChecksFailed: 0
remoteChecksSuccess: 0
remoteEnded: None
remoteJobId: None
remoteJobId2: None
remoteLastStatusCheck: None
remoteOutcome: None
remoteQueue: skx-dev
remoteResultInfo: None
remoteStarted: None
remoteSubmitRetries: 0
remoteSubmitted: None
sharedAppCtx: wma_prtl
sharedAppCtxAttribs: ['SAC_EXEC_SYSTEM_ID', 'SAC_ARCHIVE_SYSTEM_ID', 'SAC_EXEC_SYSTEM_INPUT_DIR', 'SAC_EXEC_SYSTEM_EXEC_DIR', 'SAC_EXEC_SYSTEM_OUTPUT_DIR', 'SAC_ARCHIVE_SYSTEM_DIR']
stageAppCorrelationId: None
stageAppTransactionId: None
status: PENDING
subscriptions: []
tags: []
tapisQueue: tapis.jobq.submit.DefaultQueue
tenant: designsafe
trackingId: None
uuid: 2f45deef-02ec-4a48-9e47-69e576fb3e82-007
visible: True
Once you have no errors you are done submitting the job.#
go to the job-status page on the web portal to monitor the your job.#
https://www.designsafe-ci.org/workspace/history
You will, likely, have to debug your OpenSees script…..
NOTE ONCE THE JOB HAS COMPLETED, go to view Output and pay attention to the location (path) of the output, it may not be in MyData, as expected.
print('done')
done