Skip to content

Commit 9208093

Browse files
authored
Merge pull request #396 from JustinBonus/master
Update Celeris
2 parents f692b3e + 95adc17 commit 9208093

File tree

3 files changed

+105
-58
lines changed

3 files changed

+105
-58
lines changed

modules/createEVENT/Celeris/Celeris.py

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161

6262
class 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+
285304
def 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)

modules/createEVENT/Celeris/celeris/domain.py

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def __init__( # noqa: C901
225225
self.WaveType = WaveType # -1 to read from a file
226226
self.sine_wave = sine_wave
227227
self.data = np.zeros((2, 4))
228-
self.N_data = 2
228+
self.N_data = 1
229229
self.W_data = None
230230
self.init_eta = init_eta
231231
self.amplitude = Amplitude
@@ -242,6 +242,12 @@ def __init__( # noqa: C901
242242
self.amplitude = float(self.configfile['amplitude'])
243243
if checjson('period', self.configfile) == 1:
244244
self.period = float(self.configfile['period'])
245+
if checjson('sine_wave', self.configfile) == 1:
246+
self.sine_wave = [float(self.configfile['sine_wave'][0]),
247+
float(self.configfile['sine_wave'][1]),
248+
float(self.configfile['sine_wave'][2]),
249+
float(self.configfile['sine_wave'][3])]
250+
self.N_data = 1 # Just one wave
245251
if checjson('BoundaryWidth', self.configfile) == 1:
246252
self.BoundaryWidth = int(self.configfile['BoundaryWidth'])
247253
else:
@@ -343,10 +349,17 @@ def get_data(self): # noqa: D102
343349
Returns:
344350
ti.field: A Taichi field of shape `(N_data, 4)` containing wave parameters.
345351
"""
352+
data = None # noqa: N806
346353
if self.WaveType == -1:
347354
self.load_data()
348-
data = ti.field(self.precision, shape=(self.N_data, 4))
349-
data.from_numpy(self.data)
355+
data = ti.field(self.precision, shape=(self.N_data, 4))
356+
data.from_numpy(self.data)
357+
elif self.WaveType == 1 or self.WaveType == 2:
358+
data = ti.field(self.precision, shape=(self.N_data, 4))
359+
data.from_numpy(np.array([self.sine_wave]))
360+
else:
361+
data = ti.field(self.precision, shape=(self.N_data, 4))
362+
data.from_numpy(np.array([[0, 0, 0, 0]]))
350363
return data
351364

352365

@@ -478,11 +491,19 @@ def __init__( # noqa: C901, PLR0913
478491
if checjson('WIDTH', self.configfile) == 1:
479492
self.Nx = int(self.configfile['WIDTH'])
480493
else:
481-
self.Nx = Nx
494+
if (self.topodata != None) and (self.topodata.datatype == 'celeris' or self.topodata.datatype == 'txt'):
495+
self.Nx = self.topodata.z().shape[0]
496+
else:
497+
self.Nx = Nx
498+
self.configfile["WIDTH"] = self.Nx
482499
if checjson('HEIGHT', self.configfile) == 1:
483500
self.Ny = int(self.configfile['HEIGHT'])
484501
else:
485-
self.Ny = Ny
502+
if (self.topodata != None) and (self.topodata.datatype == 'celeris' or self.topodata.datatype == 'txt'):
503+
self.Ny = self.topodata.z().shape[1]
504+
else:
505+
self.Ny = Ny
506+
self.configfile["HEIGHT"] = self.Ny
486507
if checjson('dx', self.configfile) == 1:
487508
self.dx = float(self.configfile['dx'])
488509
else:

modules/createEVENT/Celeris/celeris/solver.py

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,8 @@ def __init__( # noqa: C901, PLR0913, PLR0915
371371
self.force_sensor_begin = self.bc.configfile['force_sensor_begin']
372372
self.force_sensor_begin[0] = int(self.force_sensor_begin[0] / self.dx)
373373
self.force_sensor_begin[1] = int(self.force_sensor_begin[1] / self.dy)
374-
self.force_sensor_begin_scaled[0] = self.force_sensor_begin[0] / self.bc.configfile['WIDTH']
375-
self.force_sensor_begin_scaled[1] = self.force_sensor_begin[1] / self.bc.configfile['HEIGHT']
374+
self.force_sensor_begin_scaled[0] = self.force_sensor_begin[0] / self.domain.Nx
375+
self.force_sensor_begin_scaled[1] = self.force_sensor_begin[1] / self.domain.Ny
376376
else:
377377
self.force_sensor_begin = [0.0, 0.0]
378378
self.force_sensor_begin_scaled = [0.0, 0.0]
@@ -381,10 +381,10 @@ def __init__( # noqa: C901, PLR0913, PLR0915
381381
self.force_sensor_end = self.bc.configfile['force_sensor_end']
382382
self.force_sensor_end[0] = int(self.force_sensor_end[0] / self.dx)
383383
self.force_sensor_end[1] = int(self.force_sensor_end[1] / self.dy)
384-
self.force_sensor_end_scaled[0] = self.force_sensor_end[0] / self.bc.configfile['WIDTH']
385-
self.force_sensor_end_scaled[1] = self.force_sensor_end[1] / self.bc.configfile['HEIGHT']
384+
self.force_sensor_end_scaled[0] = self.force_sensor_end[0] / self.domain.Nx
385+
self.force_sensor_end_scaled[1] = self.force_sensor_end[1] / self.domain.Ny
386386
else:
387-
self.force_sensor_end = [self.bc.configfile['WIDTH'], self.bc.configfile['HEIGHT']]
387+
self.force_sensor_end = [self.domain.Nx, self.domain.Ny]
388388
self.force_sensor_end_scaled = [1.0, 1.0]
389389
if checjson('NumberOfTimeSeries', self.bc.configfile) == 1:
390390
self.num_wave_gauges = int(self.bc.configfile['NumberOfTimeSeries'])
@@ -401,27 +401,27 @@ def __init__( # noqa: C901, PLR0913, PLR0915
401401
locationOfTimeSeries[1] = self.bc.configfile['locationOfTimeSeries'][ts]["yts"]
402402
self.wave_gauge_pixels[ts,0] = int(locationOfTimeSeries[0] / self.dx)
403403
self.wave_gauge_pixels[ts,1] = int(locationOfTimeSeries[1] / self.dy)
404-
self.wave_gauge_scaled[ts,0] = self.wave_gauge_pixels[ts,0] / self.bc.configfile['WIDTH']
405-
self.wave_gauge_scaled[ts,1] = self.wave_gauge_pixels[ts,1] / self.bc.configfile['HEIGHT']
404+
self.wave_gauge_scaled[ts,0] = self.wave_gauge_pixels[ts,0] / self.domain.Nx
405+
self.wave_gauge_scaled[ts,1] = self.wave_gauge_pixels[ts,1] / self.domain.Ny
406406
print("Wave gauge location: ", locationOfTimeSeries[0], locationOfTimeSeries[1])
407407
print("Wave gauge pixel location: ", self.wave_gauge_pixels[ts,0], self.wave_gauge_pixels[ts,1])
408408
print("Wave gauge scaled location: ", self.wave_gauge_scaled[ts,0], self.wave_gauge_scaled[ts,1])
409409

410410
self.velocimeter_pixels[ts,0] = int(locationOfTimeSeries[0] / self.dx)
411411
self.velocimeter_pixels[ts,1] = int(locationOfTimeSeries[1] / self.dy)
412-
self.velocimeter_scaled[ts,0] = self.velocimeter_pixels[ts,0] / self.bc.configfile['WIDTH']
413-
self.velocimeter_scaled[ts,1] = self.velocimeter_pixels[ts,1] / self.bc.configfile['HEIGHT']
412+
self.velocimeter_scaled[ts,0] = self.velocimeter_pixels[ts,0] / self.domain.Nx
413+
self.velocimeter_scaled[ts,1] = self.velocimeter_pixels[ts,1] / self.domain.Ny
414414

415415
else:
416416
self.wave_gauge_pixels[0,0] = int(1)
417417
self.wave_gauge_pixels[0,1] = int(1)
418-
self.wave_gauge_scaled[0,0] = self.wave_gauge_pixels[0,0] / self.bc.configfile['WIDTH']
419-
self.wave_gauge_scaled[0,1] = self.wave_gauge_pixels[0,1] / self.bc.configfile['HEIGHT']
418+
self.wave_gauge_scaled[0,0] = self.wave_gauge_pixels[0,0] / self.domain.Nx
419+
self.wave_gauge_scaled[0,1] = self.wave_gauge_pixels[0,1] / self.domain.Ny
420420

421421
self.velocimeter_pixels[0,0] = int(1)
422422
self.velocimeter_pixels[0,1] = int(1)
423-
self.velocimeter_scaled[0,0] = self.velocimeter_pixels[0,0] / self.bc.configfile['WIDTH']
424-
self.velocimeter_scaled[0,1] = self.velocimeter_pixels[0,1] / self.bc.configfile['HEIGHT']
423+
self.velocimeter_scaled[0,0] = self.velocimeter_pixels[0,0] / self.domain.Nx
424+
self.velocimeter_scaled[0,1] = self.velocimeter_pixels[0,1] / self.domain.Ny
425425

426426

427427
if checjson('whiteWaterDecayRate', self.bc.configfile) == 1:

0 commit comments

Comments
 (0)