6161
6262class FloorForces : # noqa: D101
6363 def __init__ (self , recorderID = - 1 ): # noqa: N803
64- if recorderID < 0 :
64+ if recorderID < 0 or recorderID is None : # noqa: E701
6565 print ( # noqa: T201
6666 'No recorder ID, or a negative ID, provided, defaulting to 0 for all forces.'
6767 )
@@ -73,15 +73,14 @@ def __init__(self, recorderID=-1): # noqa: N803
7373 self .Y = []
7474 self .Z = []
7575 # prepend zeros to the list to account for the timeSeries transient analysis req in OpenSees
76- prependZero = False # noqa: N806
76+ prependZero = True # noqa: N806
7777 if prependZero :
7878 self .X .append (0.0 )
7979 self .Y .append (0.0 )
8080 self .Z .append (0.0 )
8181
8282 # Read in forces.[out or evt] file and add to EVENT.json
8383 # now using intermediary forces.evt for output of preceding Python calcs,
84- # prevents confusion with forces.out made by FEM tab
8584 if os .path .exists ('forces.evt' ): # noqa: PTH110
8685 with open ('forces.evt' ) as file : # noqa: PTH123
8786 print ('Reading forces from forces.evt to EVENT.json' ) # noqa: T201
@@ -93,17 +92,12 @@ def __init__(self, recorderID=-1): # noqa: N803
9392 if not strip_line :
9493 print ('Empty line found in forces.evt... skip' ) # noqa: T201
9594 continue
96- # Assume there is no header in the file
97- # Assume recorder IDs are sequential, starting from 1
95+ # Assume recorder IDs are sequential
96+ # Often, the first ID (0) is set to 0.0 for all time-steps, as it usually maps to a rigid node at the structures base
9897 if (j ) == recorderID :
99- # Strip away leading / trailing white-space,
100- # Delimit by regex to capture " ", \s, " ", tabs, etc.
98+ # Strip away leading / trailing white-space, Delimit by regex to capture " ", \s, " ", tabs, etc.
10199 # Each value should be a number, rep. the force on recorder j at a time-step i
102- # clean_line = re.split() # default is '\s+', which is any whitespace
103100 clean_line = re .split (r';\s|;|,\s|,|\s+' , strip_line )
104- # clean_line = re.split(r';|,\s', strip_line)
105- # clean_line = re.split("\s+", strip_line)
106-
107101 for k in range (len (clean_line )):
108102 self .X .append (float (clean_line [k ]))
109103 self .Y .append (0.0 )
@@ -121,23 +115,18 @@ def __init__(self, recorderID=-1): # noqa: N803
121115 self .Y = [0.0 ]
122116 self .Z = [0.0 ]
123117 else :
124- # for a timeSeries with N elements, we append an element at N+1 to represent the max force of the series
125- self .X .append (max (self .X ))
126- self .Y .append (max (self .Y ))
127- self .Z .append (max (self .Z ))
128-
129118 print ( # noqa: T201
130- 'Length : ' ,
119+ 'Force time-series length : ' ,
131120 len (self .X ),
132- ', Max force: ' ,
121+ ', Max force (X,Y,Z) : ' ,
133122 max (self .X ),
134123 max (self .Y ),
135124 max (self .Z ),
136- ', Min force: ' ,
125+ ', Min force (X,Y,Z) : ' ,
137126 min (self .X ),
138127 min (self .Y ),
139128 min (self .Z ),
140- ', Last force: ' ,
129+ ', Last force (X,Y,Z) : ' ,
141130 self .X [- 1 ],
142131 self .Y [- 1 ],
143132 self .Z [- 1 ],
@@ -180,6 +169,7 @@ def addFloorForceToEvent( # noqa: N802
180169 'timeSeries' : seriesName ,
181170 'numSteps' : len (force .X ),
182171 'dT' : dt ,
172+ 'dt' : dt ,
183173 'type' : 'WindFloorLoad' ,
184174 'floor' : str (floor ),
185175 'story' : str (floor ),
@@ -262,26 +252,55 @@ def GetFloorsCount(BIMFilePath): # noqa: N802, N803, D103
262252 return int (bim ['GeneralInformation' ]['stories' ])
263253
264254
265- def GetCelerisScript (): # noqa: N802, N803, D103
266- # filePath = BIMFilePath # noqa: N806
267- # with open(filePath, encoding='utf-8') as file: # noqa: PTH123
268- # evt = json.load(file)
269- # file.close # noqa: B018
270-
271- # fileNameKey = 'simulationScript' # noqa: N806
272- # filePathKey = fileNameKey + 'Path' # noqa: N806
273-
274- # for event in evt['Events']:
275- # fileName = event[fileNameKey] # noqa: N806
276- # filePath = event[filePathKey] # noqa: N806
277- # return os.path.join(filePath, fileName) # noqa: PTH118
278-
255+ def GetCelerisScript (defaultScriptName = 'setrun.py' ): # noqa: N802, N803, D103
279256 defaultScriptPath = f'{ os .path .realpath (os .path .dirname (__file__ ))} ' # noqa: N806, PTH120
280- defaultScriptName = 'setrun.py' # noqa: N806
281257 defaultScriptPath = os .path .join (defaultScriptPath , defaultScriptName ) # noqa: PTH118
282258 return defaultScriptPath # noqa: PTH118
283259
284260
261+ def dt (event = None ): # noqa: D102
262+ """
263+ Computes the time step based on the Courant criterion:
264+ dt = Courant * dx / sqrt(g * maxdepth)
265+
266+ Returns:
267+ float: The computed time step.
268+ """
269+ if 'Courant_num' in event ['config' ]:
270+ # Check is string
271+ if isinstance (event ['config' ]['Courant_num' ], str ):
272+ Courant = 0.1
273+ else :
274+ Courant = event ['config' ]['Courant_num' ]
275+ else :
276+ Courant = 0.1
277+
278+ if 'base_depth' in event ['config' ]:
279+ # Check is string
280+ if isinstance (event ['config' ]['base_depth' ], str ):
281+ maxdepth = 1.0
282+ else :
283+ maxdepth = event ['config' ]['base_depth' ]
284+ elif 'seaLevel' in event ['config' ]:
285+ # Check is string
286+ if isinstance (event ['config' ]['seaLevel' ], str ):
287+ maxdepth = 1.0
288+ else :
289+ maxdepth = event ['config' ]['seaLevel' ]
290+ else :
291+ maxdepth = 1.0
292+
293+ if (maxdepth <= 0.0 ):
294+ print ('Warning: maxdepth is less than or equal to 0.0, setting it to 1.0. This will affect the time-step and simulation stability' ) # noqa: T201
295+ maxdepth = 1.0
296+ dx = abs (event ['config' ]['dx' ]) if 'dx' in event ['config' ] else 1.0
297+ gravity = abs (event ['config' ]['g' ]) if 'g' in event ['config' ] else 9.80665 # Acceleration due to gravity in m/s^2
298+ dt = Courant * dx / np .sqrt (gravity * maxdepth )
299+ if dt <= 0.0 :
300+ print ('Warning: Computed dt is less than or equal to 0.0, setting it to 1.0e-3' ) # noqa: T201
301+ dt = 1.0e-3
302+ return dt # noqa: N806
303+
285304def main ():
286305 """
287306 Entry point to generate event file using Celeris.
@@ -335,10 +354,18 @@ def main():
335354 configFilename = event ['configFile' ] # noqa: N816
336355 bathymetryFilename = event ['bathymetryFile' ] # noqa: N816
337356 waveFilename = event ['waveFile' ] # noqa: N816
338- # Check for event['config']['dt'] in the event file
339- # and set dt to the value in the event file
340- # if not found, set dt to 0.01
341- dt = event ['config' ]['dt' ] if 'dt' in event ['config' ] else 0.01
357+ # Determine dt for the force time series
358+ # Try to compute using Courant_num (CFL), otherwise look for dt in the config
359+ if 'Courant_num' in event ['config' ]:
360+ print ('Courant_num found in event file. Compute dt.' ) # noqa: T201
361+ dt = dt (event = event )
362+ else :
363+ print ('Courant_num not found in event file. Use provided dt' ) # noqa: T201
364+ if 'dt' in event ['config' ]:
365+ dt = event ['config' ]['dt' ] # noqa: N816
366+ else :
367+ print ('dt not found in event file. Use default dt' ) # noqa: T201
368+ dt = 1e-3 # noqa: N806
342369
343370 print ('Running Celeris with script:' , scriptName ) # noqa: T201
344371 print ('Running Celeris with directory:' , caseDirectory ) # noqa: T201
@@ -397,4 +424,3 @@ def main():
397424
398425 # write the event file
399426 writeEVENT (forces , filenameEVENT , floorsCount = floorsCount )
400- # writeEVENT(forces, arguments.filenameEVENT)
0 commit comments