Skip to content

Commit 47292fe

Browse files
SierdNick
and
Nick
authored
1d2d patch (#207)
fixes issue #190 * Update model.py * initiate quasi 2D implementation * quasi 2D with sorting * handy caching for numba speeds up compilation * write quasi 2D output in 1D nc-file * New rotation scheme Capabilities added to port 1D parameterizations into 2D using a central rotation grid --------- Co-authored-by: Nick <[email protected]>
1 parent acb4452 commit 47292fe

15 files changed

+1064
-114
lines changed

aeolis/bed.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,14 @@ def initialize(s, p):
105105
for j in range(nf):
106106
s['mass'][:,:,i,j] = p['rhog'] * (1. - p['porosity']) \
107107
* s['thlyr'][:,:,i] * gs[j]
108-
else:
109-
s['mass'][:,:,:,:] = p['bedcomp_file'].reshape(s['mass'].shape)
108+
else:
109+
# if a quasi 2D domain is used, the bedcomp_file is reshaped to fit the domain
110+
if s['mass'].shape[0] == 3:
111+
s['mass'][0,:,:,:] = p['bedcomp_file'].reshape(s['mass'].shape[1:])
112+
s['mass'][1,:,:,:] = p['bedcomp_file'].reshape(s['mass'].shape[1:])
113+
s['mass'][2,:,:,:] = p['bedcomp_file'].reshape(s['mass'].shape[1:])
114+
else:
115+
s['mass'][:,:,:,:] = p['bedcomp_file'].reshape(s['mass'].shape)
110116

111117
# initialize masks
112118
for k, v in p.items():
@@ -305,8 +311,11 @@ def update(s, p):
305311
if p['grain_dist'].ndim == 2:
306312
m[ix_ero,-1,:] -= dm[ix_ero,:] * normalize(p['grain_dist'][-1,:])[np.newaxis,:].repeat(np.sum(ix_ero), axis=0)
307313
elif type(p['bedcomp_file']) == np.ndarray:
308-
gs = p['bedcomp_file'].reshape((-1,nl,nf))
309-
m[ix_ero,-1,:] -= dm[ix_ero,:] * normalize(gs[ix_ero,-1, :], axis=1)
314+
gs = np.zeros(s['mass'].shape)
315+
gs[0,:,:,:] = p['bedcomp_file'].reshape((-1,nl,nf))
316+
gs[1,:,:,:] = p['bedcomp_file'].reshape((-1,nl,nf))
317+
gs[2,:,:,:] = p['bedcomp_file'].reshape((-1,nl,nf))
318+
m[ix_ero,-1,:] -= dm[ix_ero,:] * normalize(gs.reshape((-1,nl,nf))[ix_ero,-1, :], axis=1)
310319
else:
311320
m[ix_ero,-1,:] -= dm[ix_ero,:] * normalize(p['grain_dist'])[np.newaxis,:].repeat(np.sum(ix_ero), axis=0)
312321
# remove tiny negatives

aeolis/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@
322322
'method_transport' : 'bagnold', # Name of method to compute equilibrium sediment transport rate
323323
'method_roughness' : 'constant', # Name of method to compute the roughness height z0, note that here the z0 = k, which does not follow the definition of Nikuradse where z0 = k/30.
324324
'method_grainspeed' : 'windspeed', # Name of method to assume/compute grainspeed (windspeed, duran, constant)
325+
'method_shear' : 'fft', # Name of method to compute topographic effects on wind shear stress (fft, quasi2d, duna2d (experimental))
325326
'max_error' : 1e-6, # [-] Maximum error at which to quit iterative solution in implicit numerical schemes
326327
'max_iter' : 1000, # [-] Maximum number of iterations at which to quit iterative solution in implicit numerical schemes
327328
'max_iter_ava' : 1000, # [-] Maximum number of iterations at which to quit iterative solution in avalanching calculation

aeolis/examples/grainsizevariations/aeolis_horizontalgradient1.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Cdk = 5. % [-] Constant in DK formulati
8787

8888
%% -------------------- [Solver] ----------------------------- %%
8989
T = 1. % [s] Adaptation time scale in advection equation
90-
solver = trunk % [-] Numerical solver of advection scheme
90+
solver = trunk % [-] Numerical solver of advection scheme
9191
CFL = 1. % [-] CFL number to determine time step in explicit scheme
9292
accfac = 1. % [-] Numerical acceleration factor
9393
scheme = euler_backward % [-] Name of numerical scheme (euler_forward, euler_backward or crank_nicolson)

aeolis/examples/grainsizevariations/aeolis_horizontalgradient2.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ Cdk = 5. % [-] Constant in DK formulati
8787

8888
%% -------------------- [Solver] ----------------------------- %%
8989
T = 1. % [s] Adaptation time scale in advection equation
90-
solver = trunk % [-] Numerical solver of advection scheme
90+
solver = trunk % [-] Numerical solver of advection scheme
9191
CFL = 1. % [-] CFL number to determine time step in explicit scheme
9292
accfac = 1. % [-] Numerical acceleration factor
9393
scheme = euler_backward % [-] Name of numerical scheme (euler_forward, euler_backward or crank_nicolson)

aeolis/examples/grainsizevariations/aeolis_verticallayering1.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Cdk = 5. % [-] Constant in DK formulati
8686

8787
%% -------------------- [Solver] ----------------------------- %%
8888
T = 1. % [s] Adaptation time scale in advection equation
89-
solver = trunk % [-] Numerical solver of advection scheme
89+
solver = trunk % [-] Numerical solver of advection scheme
9090
CFL = 1. % [-] CFL number to determine time step in explicit scheme
9191
accfac = 1. % [-] Numerical acceleration factor
9292
scheme = euler_backward % [-] Name of numerical scheme (euler_forward, euler_backward or crank_nicolson)

aeolis/examples/grainsizevariations/aeolis_verticallayering2.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Cdk = 5. % [-] Constant in DK formulati
8686

8787
%% -------------------- [Solver] ----------------------------- %%
8888
T = 1. % [s] Adaptation time scale in advection equation
89-
solver = trunk % [-] Numerical solver of advection scheme
89+
solver = trunk % [-] Numerical solver of advection scheme
9090
CFL = 1. % [-] CFL number to determine time step in explicit scheme
9191
accfac = 1. % [-] Numerical acceleration factor
9292
scheme = euler_backward % [-] Name of numerical scheme (euler_forward, euler_backward or crank_nicolson)

aeolis/inout.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def read_configfile(configfile, parse_files=True, load_defaults=True):
117117
# set default for nsavetimes, if not given
118118
if 'nsavetimes' in p and not p['nsavetimes']:
119119
p['nsavetimes'] = int(p['dzb_interval']/p['dt'])
120-
120+
121121
return p
122122

123123

aeolis/model.py

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def initialize(self)-> None:
189189
self.p = aeolis.inout.read_configfile(self.configfile)
190190
aeolis.inout.check_configuration(self.p)
191191

192-
# set nx, ny and nfractions
192+
# set nx, ny and nfractions and make 1D into quasi 2D
193193
if self.p['xgrid_file'].ndim == 2:
194194
self.p['ny'], self.p['nx'] = self.p['xgrid_file'].shape
195195

@@ -198,9 +198,29 @@ def initialize(self)-> None:
198198
self.p['ny'] -= 1
199199

200200
else:
201-
self.p['nx'] = len(self.p['xgrid_file'])
202-
self.p['nx'] -= 1
203-
self.p['ny'] = 0
201+
if 0:
202+
#this is the old 1D stuff
203+
self.p['nx'] = len(self.p['xgrid_file'])
204+
self.p['nx'] -= 1
205+
self.p['ny'] = 0
206+
207+
if 1:
208+
# this is the new quasi 2D stuff
209+
# this is where we make the 1D grid into a 2D grid to ensure process compatibility
210+
self.p['xgrid_file'] = np.transpose(np.stack((self.p['xgrid_file'], self.p['xgrid_file'], self.p['xgrid_file']),axis=1))
211+
self.p['ny'], self.p['nx'] = self.p['xgrid_file'].shape
212+
213+
dy = self.p['xgrid_file'][1,2]-self.p['xgrid_file'][1,1]
214+
215+
# repeat the above for ygrid_file
216+
self.p['ygrid_file'] = np.transpose(np.stack((self.p['ygrid_file'], self.p['ygrid_file']+dy, self.p['ygrid_file']+2*dy),axis=1))
217+
218+
# repeat the above for bed_file
219+
self.p['bed_file'] = np.transpose(np.stack((self.p['bed_file'], self.p['bed_file'], self.p['bed_file']),axis=1))
220+
221+
# change from number of points to number of cells
222+
self.p['nx'] -= 1
223+
self.p['ny'] -= 1
204224

205225
#self.p['nfractions'] = len(self.p['grain_dist'])
206226
self.p['nfractions'] = len(self.p['grain_size'])
@@ -266,10 +286,9 @@ def update(self, dt:float=-1) -> None:
266286
267287
'''
268288

269-
self.p['_time'] = self.t
289+
self.p['_time'] = self.t
290+
270291

271-
# here are going to make a change
272-
#
273292

274293
# store previous state
275294
self.l = self.s.copy()
@@ -1631,7 +1650,12 @@ def solve_SS(self, alpha:float=0., beta:float=1.) -> dict:
16311650
w = w_init.copy()
16321651
else:
16331652
# use initial guess for first time step
1634-
w = p['grain_dist'].reshape((1,1,-1))
1653+
# when p['grain_dist'] has 2 dimensions take the first row otherwise take the only row
1654+
if len(p['grain_dist'].shape) == 2:
1655+
w = p['grain_dist'][0,:].reshape((1,1,-1))
1656+
else:
1657+
w = p['grain_dist'].reshape((1,1,-1))
1658+
16351659
w = w.repeat(p['ny']+1, axis=0)
16361660
w = w.repeat(p['nx']+1, axis=1)
16371661
else:
@@ -1678,7 +1702,7 @@ def solve_SS(self, alpha:float=0., beta:float=1.) -> dict:
16781702
Ct[-1,:,0] = -2
16791703

16801704
# Ct, pickup = sweep(s['Cu'].copy(), s['mass'].copy(), self.dt, p['T'], s['ds'], s['dn'], s['us'], s['un'] )
1681-
Ct, pickup = sweep3(Ct, s['Cu'].copy(), s['mass'].copy(), self.dt, p['T'], s['ds'], s['dn'], s['us'], s['un'] )
1705+
Ct, pickup = sweep3(Ct, s['Cu'].copy(), s['mass'].copy(), self.dt, p['T'], s['ds'], s['dn'], s['us'], s['un'],w)
16821706

16831707
if 0:
16841708
#define 4 quadrants based on wind directions

aeolis/netcdf.py

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,14 @@ def initialize(outputfile, outputvars, s, p, dimensions):
8484
with netCDF4.Dataset(outputfile, 'w') as nc:
8585

8686
# add dimensions
87-
nc.createDimension('s', p['nx']+1)
88-
nc.createDimension('n', p['ny']+1)
87+
nc.createDimension('s', p['nx']+1)
88+
89+
# this is where a quasi 2D model is stored in 1D
90+
if p['ny']+1 == 3:
91+
nc.createDimension('n', 1)
92+
else:
93+
nc.createDimension('n', p['ny']+1)
94+
8995
nc.createDimension('time', 0)
9096
nc.createDimension('nv', 2)
9197
nc.createDimension('nv2', 4)
@@ -287,9 +293,17 @@ def initialize(outputfile, outputvars, s, p, dimensions):
287293

288294
# store static data
289295
nc.variables['s'][:] = np.arange(p['nx']+1)
290-
nc.variables['n'][:] = np.arange(p['ny']+1)
291-
nc.variables['x'][:,:] = s['x']
292-
nc.variables['y'][:,:] = s['y']
296+
297+
# this is where a quasi 2D model is stored in 1D
298+
if p['ny']+1 == 3:
299+
nc.variables['n'][:] = np.arange(1)
300+
nc.variables['x'][:,:] = s['x'][0,:]
301+
nc.variables['y'][:,:] = s['y'][0,:]
302+
else:
303+
nc.variables['n'][:] = np.arange(p['ny']+1)
304+
nc.variables['x'][:,:] = s['x']
305+
nc.variables['y'][:,:] = s['y']
306+
293307
nc.variables['layers'][:] = np.arange(p['nlayers'])
294308
nc.variables['fractions'][:] = p['grain_size']
295309

@@ -344,14 +358,21 @@ def append(outputfile, variables):
344358
# abort if netCDF4 is not available
345359
if not HAVE_NETCDF:
346360
return
347-
361+
348362
with netCDF4.Dataset(outputfile, 'a') as nc:
349363
i = nc.variables['time'].shape[0]
350364
nc.variables['time'][i] = variables['time']
351365
for k, v in variables.items():
352366
if k == 'time':
353367
continue
354-
nc.variables[k][i,...] = v
368+
# this is where a quasi 2D model is stored in 1D
369+
if v.shape[0]==3:
370+
nc.variables[k][i,...] = v[1,:]
371+
# this is where a 2D model is stored in 2D
372+
else:
373+
nc.variables[k][i,...] = v
374+
375+
355376

356377
set_bounds(outputfile)
357378

0 commit comments

Comments
 (0)