def __loadConfig(self): import src.config as cf configvars = [var for var in dir(cf) if not var.startswith('__')] d = {} for var in configvars: exec('d[var] = cf.' + var) return DataContainer(d)
def __init__(self, value, gridData, gridName='grid'): # if grid data is a dictionary, first convert to datacontainer if isinstance(gridData, dict): from src.DataContainer import DataContainer dc = DataContainer() dc.addData(gridName, gridData) gridData = dc del dc # check if a grid is provided in DC data dimensions = gridData.v(gridName, 'dimensions') dimNames = [dimensions[i] for i in range(0, len(value.shape))] NumericalFunctionBase.__init__(self, dimNames) # add grid (with name 'grid') and value self.addGrid(gridData) self.addValue(value) return
def run(self): # self.timers[0].tic() self.logger.info('Running module StaticAvailability') ################################################################################################################ ## Init ################################################################################################################ jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') L = self.input.v('L') self.x = self.input.v('grid', 'axis', 'x') self.zarr = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0]-self.input.v('R', x=self.x/L).reshape((len(self.x), 1)) #YMD 22-8-17 includes reference level; note that we take a reference frame z=[-H-R, 0] c00 = np.real(self.input.v('hatc0', 'a', range(0, jmax+1), range(0, kmax+1), 0)) c04 = np.abs(self.input.v('hatc0', 'a', range(0, jmax+1), range(0, kmax+1), 2)) # c20 = np.real(self.input.v('hatc2', 'a', range(0, jmax+1), range(0, kmax+1), 0)) # NB. do not include hatc2 in the definition of alpha1 here alpha1 = ny.integrate(c00, 'z', kmax, 0, self.input.slice('grid'))[:, 0] alpha1[-1] += alpha1[-2] # correct alpha1 at last point to prevent zero value alpha2 = ny.integrate(c04, 'z', kmax, 0, self.input.slice('grid'))[:, 0]/(alpha1+1e-10) + 1.e-3 # self.timers[0].toc() ################################################################################################################ ## Compute T and F ################################################################################################################ # self.timers[1].tic() d = self.compute_transport() G = self.compute_source() # self.timers[1].toc() ################################################################################################################ ## 4. Calculate availability ################################################################################################################ # self.timers[2].tic() # Add all mechanisms to datacontainer dctrans = DataContainer(d) # Calculate availability a, f0, f0x = self.availability(dctrans.v('F', range(0, jmax+1)), dctrans.v('T', range(0, jmax+1)), G, alpha1, alpha2) f0 = f0.reshape(jmax+1, 1) f0x = f0x.reshape(jmax+1, 1) d['a'] = a nfu = ny.functionTemplates.NumericalFunctionWrapper(f0[:, 0], self.input.slice('grid')) nfu.addDerivative(f0x[:, 0], 'x') d['f'] = nfu.function # self.timers[2].toc() ################################################################################################################ # 5. Calculate concentrations, i.e. a*hatc(a) + ax*hatc(ax) ################################################################################################################ # self.timers[3].tic() d['c0'] = {} d['c1'] = {} d['c2'] = {} # Calculate c0=f*hatc0 for submod in self.input.getKeysOf('hatc0', 'a'): c0_comp = self.input.v('hatc0', 'a', submod, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['c0'][submod] = {} tmp = f0[:, None] * c0_comp d['c0'][submod] = tmp # Calculate c1 = f*hatc1_f + fx*hatc1_fx for submod in self.input.getKeysOf('hatc1', 'a'): if submod == 'erosion': for subsubmod in self.input.getKeysOf('hatc1', 'a', 'erosion'): c1_comp = self.input.v('hatc1', 'a', 'erosion', subsubmod, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['c1'] = self.dictExpand(d['c1'], 'erosion', subsubmod) tmp = f0[:, None] * c1_comp d['c1']['erosion'][subsubmod] = tmp elif submod == 'sedadv': c1_comp_a = self.input.v('hatc1', 'a', 'sedadv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) c1_comp_ax = self.input.v('hatc1', 'ax', 'sedadv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['c1'][submod] = {} tmp = f0[:, None] * c1_comp_a + f0x[:, None] * c1_comp_ax d['c1'][submod] = tmp else: c1_comp = self.input.v('hatc1', 'a', submod, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['c1'][submod] = {} tmp = f0[:, None] * c1_comp d['c1'][submod] = tmp # Calculate c2 = f*hatc2 for subsubmod in self.input.getKeysOf('hatc2', 'a', 'erosion'): c2_comp = self.input.v('hatc2', 'a', 'erosion', subsubmod, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['c2'] = self.dictExpand(d['c2'], 'erosion', subsubmod) tmp = f0[:, None] * c2_comp d['c2']['erosion'][subsubmod] = tmp # self.timers[3].toc() # self.timers[0].disp('time availability - init') # self.timers[1].disp('time availability - T, F') # self.timers[2].disp('time availability - a, f') # self.timers[3].disp('time availability - to dict') # self.timers[4].disp('time availability - cap') # self.timers[5].disp('time availability - trap') # [self.timers[i].reset() for i in range(0, len(self.timers))] return d
import json import datetime import os from src.DataContainer import DataContainer from src.globalVar import module_path if __name__ == '__main__': if not os.path.exists(module_path + "/result"): os.mkdir(module_path + "/result") time = datetime.datetime.now() curr_year = time.year f = open(module_path + "/settings.json", "r") settings = json.load(f) company_list = settings['company'] startyear = settings['start year'] finalyear = settings['final year'] season = settings['season'] pickleload = settings['load from file'] pickledump = settings['write to file'] platform = DataContainer(company_list, startyear, finalyear, season, curr_year, pickleload, pickledump) platform.calculate() platform.write()
def run(self): """ """ self.logger.info('Running module DynamicAvailability_upwind') ################################################################################################################ # Init ################################################################################################################ jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') self.x = ny.dimensionalAxis(self.input.slice('grid'), 'x')[:, 0, 0] self.dx = (self.x[1:] - self.x[:-1]) self.zarr = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0] self.B = self.input.v('B', range(0, jmax + 1)) self.Bx = self.input.d('B', range(0, jmax + 1), dim='x') self.Kh = self.input.v('Kh') self.u0tide_bed = self.input.v('u0', 'tide', range(0, jmax + 1), kmax, 1) c00 = np.real( self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1), 0)) c04 = np.abs( self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1), 2)) c04_int = np.trapz(c04, x=-self.zarr) hatc2 = np.abs( self.input.v('hatc2', range(0, jmax + 1), range(0, kmax + 1), 0)) alpha1 = np.trapz(c00 + hatc2, x=-self.zarr, axis=1) if alpha1[-1] == 0: alpha1[-1] = alpha1[-2] alpha2 = c04_int / alpha1 + 1e-3 ## load time series Q t = self.interpretValues(self.input.v('t')) toutput = self.interpretValues(self.input.v('toutput')) toutput[0] = t[ 0] # correct output time; first time level is always equal to initial computation time Qarray = self.interpretValues(self.input.v('Q1')) if len(Qarray) != len(t): from src.util.diagnostics.KnownError import KnownError raise KnownError( 'Length of Q does not correspond to length of time array.') ################################################################################################################ # Compute transport, source and BC ################################################################################################################ ## Transport d = self.compute_transport() dc = DataContainer(d) # change size of those components that depend on the river discharge and put init value in first element T_r = copy(dc.v('T', 'river', range(0, jmax + 1))) T_rr = copy(dc.v('T', 'river_river', range(0, jmax + 1))) T_dr = copy(dc.v('T', 'diffusion_river', range(0, jmax + 1))) F_dr = dc.v('F', 'diffusion_river', range(0, jmax + 1)) d['T']['river'] = np.zeros((jmax + 1, 1, 1, len(toutput))) d['T']['river'][:, 0, 0, 0] = T_r d['T']['river_river'] = np.zeros((jmax + 1, 1, 1, len(toutput))) d['T']['river_river'][:, 0, 0, 0] = T_rr d['T']['diffusion_river'] = np.zeros((jmax + 1, 1, 1, len(toutput))) d['T']['diffusion_river'][:, 0, 0, 0] = T_dr d['F']['diffusion_river'] = np.zeros((jmax + 1, 1, 1, len(toutput))) d['F']['diffusion_river'][:, 0, 0, 0] = F_dr T = dc.v('T', range(0, jmax + 1), 0, 0, 0) F = dc.v('F', range(0, jmax + 1), 0, 0, 0) ## Source G = self.compute_source() #NB does not change over long time scale ## Seaward boundary condition if self.input.v('sedbc') == 'csea': csea = self.input.v('csea') fsea = csea / alpha1[0] * ( self.input.v('grid', 'low', 'z', 0) - self.input.v('grid', 'high', 'z', 0) ) #NB does not change over long time scale else: from src.util.diagnostics.KnownError import KnownError raise KnownError( 'incorrect seaward boundary type (sedbc) for sediment module') ## compute TQ, uQ, hatc2Q: quantities relative to the river discharge u1river = np.real( self.input.v('u1', 'river', range(0, jmax + 1), range(0, kmax + 1), 0)) Q_init = -np.trapz(u1river[-1, :], x=-self.zarr[-1, :]) * self.B[ -1] # initial discharge self.TQ = T_r / Q_init # river transport per discharge unit self.uQ = u1river / Q_init # river velocity per discharge unit ################################################################################################################ # Initialise X = (f, S) ################################################################################################################ if self.input.v('initial') == 'erodibility': finit = self.input.v('finit', range(0, jmax + 1)) Sinit = self.init_stock(finit, alpha1, alpha2) elif self.input.v('initial') == 'stock': Sinit = self.input.v('Sinit', range(0, jmax + 1)) finit = self.erodibility_stock_relation(alpha2, Sinit / alpha1) elif self.input.v('initial') == 'equilibrium': _, finit, _ = self.availability(F, T, G, alpha1, alpha2) Sinit = self.init_stock(finit, alpha1, alpha2) else: from src.util.diagnostics.KnownError import KnownError raise KnownError( 'incorrect initial value for sediment module. Use erodibility, stock or equilibrium' ) X = np.concatenate((finit, Sinit)) f = np.zeros((jmax + 1, 1, 1, len(toutput))) S = np.zeros((jmax + 1, 1, 1, len(toutput))) f[:, 0, 0, 0] = finit S[:, 0, 0, 0] = Sinit ################################################################################################################ # Time integrator ################################################################################################################ T_base = dc.v('T', range(0, jmax + 1), 0, 0, 0) - dc.v( 'T', 'river', range(0, jmax + 1), 0, 0, 0) - dc.v( 'T', 'river_river', range(0, jmax + 1), 0, 0, 0) - dc.v( 'T', 'diffusion_river', range(0, jmax + 1), 0, 0, 0) F_base = dc.v('F', range(0, jmax + 1), 0, 0, 0) - dc.v( 'F', 'diffusion_river', range(0, jmax + 1), 0, 0, 0) # loop self.timer.tic() qq = 1 # counter for saving for i, Q in enumerate(Qarray[1:]): # quantities at old time step Told = copy(T) Fold = copy(F) alpha1old = copy(alpha1) alpha2old = copy(alpha2) # Update transport terms and hatc2 & load new transport terms T_riv, T_rivriv, T_difriv, F_difriv = self.update_transport(Q) ur = self.uQ[:, -1] * Q hatc2 = self.update_hatc2(ur) T = T_base + T_riv + T_rivriv + T_difriv F = F_base + F_difriv # Make one time step and iterate over non-linearity self.dt = t[i + 1] - t[i] alpha1 = np.trapz(c00 + hatc2, x=-self.zarr, axis=1) if alpha1[-1] == 0: alpha1[-1] = alpha1[-2] alpha2 = c04_int / alpha1 + 1e-3 X = self.timestepping(T, F, alpha1, alpha2, Told, Fold, alpha1old, alpha2old, X, fsea, G) # save output on output timestep if t[i + 1] >= toutput[qq]: toutput[qq] = t[ i + 1] # correct output time to real time if time step and output time do not correspond d['T']['river'][:, 0, 0, qq] = T_riv d['T']['river_river'][:, 0, 0, qq] = T_rivriv d['T']['diffusion_river'][:, 0, 0, qq] = T_difriv d['F']['diffusion_river'][:, 0, 0, qq] = F_difriv f[:, 0, 0, qq] = X[:jmax + 1] S[:, 0, 0, qq] = X[jmax + 1:] qq += 1 qq = np.minimum(qq, len(toutput) - 1) # display progress if i % np.floor(len(Qarray[1:]) / 100.) == 0: percent = float(i) / len(Qarray[1:]) hashes = '#' * int(round(percent * 10)) spaces = ' ' * (10 - len(hashes)) sys.stdout.write("\rProgress: [{0}]{1}%".format( hashes + spaces, int(round(percent * 100)))) sys.stdout.flush() sys.stdout.write('\n') self.timer.toc() self.timer.disp('time integration time') ################################################################################################################ # Prepare output ################################################################################################################ d['f'] = f d['a'] = S fx = np.gradient(f, self.x, axis=0, edge_order=2) hatc0 = self.input.v('hatc0', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), [0]) hatc1 = self.input.v('hatc1', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), [0]) hatc1x = self.input.v('hatc1', 'ax', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), [0]) hatc2 = self.input.v('hatc2', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), [0]) d['c0'] = hatc0 * f d['c1'] = hatc1 * f + hatc1x * fx d['c2'] = hatc2 * f d['t'] = toutput return d
def run(self): """Run function to initiate the calculation of the sediment transport Returns: Dictionary with results. At least contains the variables listed as output in the registry """ self.logger.info('Running module Sediment') # Initiate variables self.SIGMA = self.input.v('OMEGA') self.RHOS = self.input.v('RHOS') self.DS = self.input.v('DS') self.GPRIME = self.input.v('G') * (self.RHOS - self.input.v('RHO0')) / self.input.v('RHO0') # self.ASTAR = self.input.v('astar') self.WS = self.input.v('ws0') self.KH = self.input.v('Kh') self.L = self.input.v('L') self.x = self.input.v('grid', 'axis', 'x') * self.input.v('L') self.dx = self.x[1:]-self.x[:-1] jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') self.z = self.input.v('grid', 'axis', 'z', 0, range(0, kmax+1)) self.zarr = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0]-self.input.v('R', x=self.x/self.L).reshape((len(self.x), 1)) #YMD 22-8-17 includes reference level; note that we take a reference frame z=[-H-R, 0] self.Av0 = self.input.v('Kv', range(0, jmax+1), 0, 0).reshape(jmax+1, 1) self.Av0x = self.input.d('Kv', range(0, jmax+1), 0, 0, dim='x').reshape(jmax+1, 1) self.H = (self.input.v('H', range(0, jmax+1)).reshape(jmax+1, 1) + self.input.v('R', range(0, jmax+1)).reshape(jmax+1, 1)) self.Hx = (self.input.d('H', range(0, jmax+1), dim='x').reshape(jmax+1, 1) + self.input.d('R', range(0, jmax+1), dim='x').reshape(jmax+1, 1)) self.B = self.input.v('B', range(0, jmax+1)) self.Bx = self.input.d('B', range(0, jmax+1), dim='x').reshape(jmax+1, 1) self.sf = self.input.v('Roughness', range(0, jmax+1), 0, 0).reshape(jmax+1, 1) self.sfx = self.input.d('Roughness', range(0, jmax+1), 0, 0, dim='x').reshape(jmax+1, 1) self.submodules_hydro = self.input.data['u1'].keys() self.submodules_sed = self.input.v('submodules') # Extract leading order surface elevation and horizontal and vertical velocities self.zeta0 = self.input.v('zeta0', 'tide', range(0, jmax+1), 0, 1).reshape(jmax+1, 1) self.u0 = self.input.v('u0', 'tide', range(0, jmax+1), range(0, kmax+1), 1) self.w0 = self.input.v('w0', 'tide', range(0, jmax+1), range(0, kmax+1), 1) # Initiate dictionary to save results d = {} ################################################################################################################ ## Calculate leading, first and second order concentration amplitudes hatc0, hatc1 and hatc2 ################################################################################################################ # Allocate space d['hatc0'] = {} d['hatc1'] = {'a': {}, 'ax': {}} d['hatc2'] = {} # Calculate leading order concentration amplitudes d['hatc0'] = self.erosion_lead() # Calculate first order concentration amplitudes for sedmod in self.submodules_sed: hatc1 = getattr(self, sedmod)() for k in hatc1.keys(): d['hatc1'][k].update(hatc1[k]) # Calculate second order concentration amplitudes d['hatc2'] = self.erosion_second() ################################################################################################################ ## Calculate Transport function T and diffusion function F ################################################################################################################ # Allocate space d['T'] = {} d['F'] = {} ## Transport T ################################################################################################# # Transport terms that are a function of the first order velocity, i.e. u1*c0 terms. for submod in self.input.getKeysOf('u1'): u1_comp = self.input.v('u1', submod, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) d['T'] = self.dictExpand(d['T'], submod, ['TM' + str(2 * n) for n in range(0, fmax + 1)]) # calculate residual Transport terms for n in (0, 2): tmp = u1_comp[:, :, n] if n==0: if submod == 'stokes': tmp = np.real(np.trapz(tmp * self.c00, x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T'][submod] = self.dictExpand(d['T'][submod], 'TM0', ['return', 'drift']) d['T'][submod]['TM0']['return'] += tmp else: tmp = np.real(np.trapz(tmp * self.c00, x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T'][submod]['TM' + str(2 * n)] += tmp elif n==2: if submod == 'stokes': tmp = np.real(np.trapz((tmp * np.conj(self.c04) + np.conj(tmp) * self.c04) / 4., x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T'][submod] = self.dictExpand(d['T'][submod], 'TM4', ['return', 'drift']) d['T'][submod]['TM4']['return'] += tmp else: tmp = np.real(np.trapz((tmp * np.conj(self.c04) + np.conj(tmp) * self.c04) / 4., x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T'][submod]['TM' + str(2 * n)] += tmp # Transport terms that are a function of the first order concentration, i.e. u0*c1 terms. for submod in d['hatc1']['a'].keys(): if submod == 'erosion': for subsubmod in d['hatc1']['a'][submod].keys(): c1_comp = d['hatc1']['a'][submod][subsubmod] d['T'] = self.dictExpand(d['T'], subsubmod, ['TM' + str(2 * n) for n in range(0, fmax + 1)]) tmp = c1_comp[:, :, 1] tmp = np.real(np.trapz((self.u0 * np.conj(tmp) + np.conj(self.u0) * tmp) / 4., x=-self.zarr, axis=1)) if subsubmod == 'stokes': if any(tmp) > 10**-14: d['T'][subsubmod] = self.dictExpand(d['T'][subsubmod], 'TM2', ['return', 'drift']) d['T'][subsubmod]['TM2']['return'] += tmp else: if any(tmp) > 10**-14: d['T'][subsubmod]['TM2'] += tmp else: c1_comp = d['hatc1']['a'][submod] d['T'] = self.dictExpand(d['T'], submod, ['TM' + str(2 * n) for n in range(0, fmax + 1)]) tmp = c1_comp[:, :, 1] tmp = np.real(np.trapz((self.u0 * np.conj(tmp) + np.conj(self.u0) * tmp) / 4., x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T'][submod]['TM2'] += tmp # Transport terms that are related to diffusion, i.e. K_h*c0 or K_h*c2 d['T'] = self.dictExpand(d['T'], 'diffusion_tide', ['TM' + str(2 * n) for n in range(0, fmax + 1)]) d['T']['diffusion_tide']['TM0'] = np.real(-np.trapz(self.KH * self.c00x, x=-self.zarr, axis=1)) d['T'] = self.dictExpand(d['T'], 'diffusion_river', ['TM' + str(2 * n) for n in range(0, fmax + 1)]) tmp = d['hatc2']['a']['erosion']['river_river'][:, :, 0] tmp, __ = np.gradient(tmp, self.x[1], edge_order=2) tmp = np.real(-np.trapz(self.KH * tmp, x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['T']['diffusion_river']['TM0'] = tmp # Transport terms that are related to Stokes drift, i.e. u0*c0*zeta0 if 'stokes' in self.submodules_hydro: for n in (0, 2): u0s = self.u0[:, 0] tmp = d['hatc0']['a']['erosion'][:, 0, n] if n==0: tmp = np.real(np.conj(u0s) * tmp * self.zeta0[:, 0] + u0s * tmp * np.conj(self.zeta0[:, 0])) / 4 elif n==2: tmp = np.real(u0s * np.conj(tmp) * self.zeta0[:, 0] + np.conj(u0s) * tmp * np.conj(self.zeta0[:, 0])) / 8 if any(tmp) > 10**-14: d['T']['stokes']['TM' + str(2 * n)]['drift'] = tmp # Transport term that is related to the river-river interaction u1river*c2river d['T'] = self.dictExpand(d['T'], 'river_river', ['TM' + str(2 * n) for n in range(0, fmax + 1)]) if self.input.v('u1', 'river') is not None: u1_comp = self.input.v('u1', 'river', range(0, jmax+1), range(0, kmax+1), 0) tmp = d['hatc2']['a']['erosion']['river_river'][:, :, 0] d['T']['river_river']['TM0'] = np.real(np.trapz(u1_comp * tmp, x=-self.zarr, axis=1)) ## Diffusion F ################################################################################################# # Diffusive part, i.e. Kh*c00 and Kh*c20 d['F'] = self.dictExpand(d['F'], 'diffusion_tide', ['FM' + str(2 * n) for n in range(0, fmax + 1)]) d['F']['diffusion_tide']['FM0'] = np.real(-np.trapz(self.KH * self.c00, x=-self.zarr, axis=1)) d['F'] = self.dictExpand(d['F'], 'diffusion_river', ['FM' + str(2 * n) for n in range(0, fmax + 1)]) tmp = d['hatc2']['a']['erosion']['river_river'][:, :, 0] tmp = np.real(-np.trapz(self.KH * tmp, x=-self.zarr, axis=1)) d['F']['diffusion_river']['FM0'] = tmp # Part of F that is related to sediment advection, i.e. u0*c1sedadv for submod in d['hatc1']['ax'].keys(): c1_comp = d['hatc1']['ax'][submod] d['F'] = self.dictExpand(d['F'], submod, ['FM' + str(2 * n) for n in range(0, fmax + 1)]) tmp = c1_comp[:, :, 1] tmp = np.real(np.trapz((self.u0 * np.conj(tmp) + np.conj(self.u0) * tmp) / 4., x=-self.zarr, axis=1)) if any(tmp) > 10**-14: d['F']['sedadv']['FM2'] += tmp ################################################################################################################ # Calculate availability ################################################################################################################ # Add all mechanisms to datacontainer dctrans = DataContainer(d) # Calculate availability d['a'] = {} d['a'] = self.availability(dctrans.v('F'), dctrans.v('T')).reshape(len(self.x), 1) ax = np.gradient(d['a'][:, 0], self.x[1], edge_order=2).reshape(len(self.x), 1) ################################################################################################################ # Calculate concentrations, i.e. a*hatc(a) + ax*hatc(ax) ################################################################################################################ d['c0'] = {} d['c1'] = {} d['c2'] = {} # Calculate a*c0(a) for submod in d['hatc0']['a'].keys(): c0_comp = d['hatc0']['a'][submod] d['c0'][submod] = {} tmp = d['a'][:, None] * c0_comp d['c0'][submod] = tmp # Calculate a*c1(a) + ax*c1(ax) for submod in d['hatc1']['a'].keys(): if submod == 'erosion': for subsubmod in d['hatc1']['a'][submod].keys(): c1_comp = d['hatc1']['a'][submod][subsubmod] d['c1'] = self.dictExpand(d['c1'], submod, subsubmod) tmp = d['a'][:, None] * c1_comp d['c1'][submod][subsubmod] = tmp elif submod == 'sedadv': c1_comp_a = d['hatc1']['a'][submod] c1_comp_ax = d['hatc1']['ax'][submod] d['c1'][submod] = {} tmp = d['a'][:, None] * c1_comp_a + ax[:, None] * c1_comp_ax d['c1'][submod] = tmp else: c1_comp = d['hatc1']['a'][submod] d['c1'][submod] = {} tmp = d['a'][:, None] * c1_comp d['c1'][submod] = tmp # Calculate a*c2(a) for submod in d['hatc2']['a']['erosion'].keys(): c2_comp = d['hatc2']['a']['erosion'][submod] d['c2'] = self.dictExpand(d['c2'], 'erosion', submod) tmp = d['a'][:, None] * c2_comp d['c2']['erosion'][submod] = tmp return d
def __init__(self, dimNames): FunctionBase.__init__(self, dimNames) self.dataContainer = DataContainer() self.valueSize = 0 return
class NumericalFunctionBase(FunctionBase): #Variables #Methods def __init__(self, dimNames): FunctionBase.__init__(self, dimNames) self.dataContainer = DataContainer() self.valueSize = 0 return def function(self, **kwargs): if len([ i for i in kwargs.keys() if i in self.dataContainer.v('grid', 'dimensions') ]) == 0: return self.__setReturnReference(kwargs.get('operation')) # evaluate function try: returnval = self.__evaluateFunction(**kwargs) except FunctionEvaluationError: returnval = self.__setReturnReference(kwargs.get('operation')) return returnval def __evaluateFunction(self, **kwargs): """Overrides the function method of FunctionBase, but is very similar. The difference is only that FunctionBase transfers kwargs to args before calling the actual functions Here we keep the kwargs as the actual functions also use this. """ requestSize = sum( [dim in kwargs for dim in self.dimNames] ) # count the number of dimensions in kwargs (this makes sure that other parameters or irrelevant dimensions are ignored) operation = kwargs.get('operation') try: kwargs.pop('operation') except: pass # direct to actual function if operation is None: returnval = self.value(**kwargs) elif operation == 'd': returnval = self.derivative(**kwargs) elif operation == 'n': returnval = -self.value(**kwargs) elif operation == 'dn': returnval = -self.derivative(**kwargs) else: raise FunctionEvaluationError return returnval def __setReturnReference(self, operation=None): '''No difference with FunctionBase, but required here to refer to its own functions ''' if not operation: returnval = self.function elif operation == 'n': returnval = self.negfunction elif operation == 'd': returnval = self.derfunction elif operation == 'dn': returnval = self.dnfunction else: raise KnownError( 'Function called with unknown operation. (This error indicates an incorrectly defined function)' ) return returnval def negfunction(self, **kwargs): """No difference with FunctionBase, but required here to refer to its own functions """ # reset operations if kwargs.get( 'operation' ) == 'n': # if the negative of a negfunction is called, return to function. kwargs.pop('operation') elif kwargs.get('operation') == 'd': kwargs['operation'] = 'dn' else: kwargs['operation'] = 'n' # evaluate returnval = self.function(**kwargs) return returnval def addGrid(self, gridData, gridName='grid'): # set own DataContainer containing grid data data = gridData.slice(gridName, excludeKey=True) self.dataContainer.addData( 'grid', data.data ) # improper use of the DataContainer by accessing its data directly return def addValue(self, value): """Add a variable 'value' to the numerical function Parameters: value (ndarray) - value to be put in the internal DataContainer """ self.dataContainer.addData('value', value) self.valueSize = len(value.shape) return def addDerivative(self, derivative, dim): self.dataContainer.merge({'derivative': {dim: derivative}}) return ### Depreciated v2.2 [dep01] ### def addSecondDerivative(self, derivative, dim): """ Depreciated v2.2 """ self.dataContainer.merge({'secondDerivative': {dim: derivative}}) return ### End ### def value(self, **kwargs): """Return the value of the variable in this numerical function. Parameters: kwargs (dict) - coordinates Returns: Array value using DataContainer interpolation. """ return self.dataContainer.v('value', **kwargs) def derivative(self, **kwargs): """Similar to .value(). Returns the derivative uploaded to the numerical function or makes a call to a numerical derivation method if no derivative is uploaded. """ # kwargs.pop('operation') # obsolete dim = kwargs.get('dim') v = self.dataContainer.v( 'derivative', dim, **kwargs) # try if analytical derivative is available if v is None: v = self.dataContainer.d( 'value', **kwargs) # else take numerical derivative return v ### Depreciated v2.2 [dep01] ### def secondDerivative(self, **kwargs): """See .derivative(). This method does the same for the second derivative Depreciated 2.2 [dep01] """ # kwargs.pop('operation') # obsolete dim = kwargs.get('dim') v = self.dataContainer.v('secondDerivative', dim, **kwargs) if v is None: v = self.dataContainer.dd('value', **kwargs) return v
def run(self): d = {} d['Scheldt_measurements'] = {} ################################################################################################################ # data ################################################################################################################ # Stations (optional) station_names = [ 'Vlissingen', 'Terneuzen', 'Hansweert', 'Bath', 'Prosperpolder', 'Liefkenshoek', 'Antwerpen', 'Temse', 'St. Amands', 'Dendermonde', 'Schoonaarde', 'Wetteren', 'Melle' ] x_station = np.asarray([ 0., 18.5, 33.8, 49.8, 54, 61.1, 75.6, 97.3, 106.8, 119.8, 130.6, 142.7, 148.8 ]) * 1000. river_sections = { 'Western Scheldt': [0, 1, 2, 3], 'Lower Sea Scheldt': [4, 5, 6], 'Upper Sea Scheldt': [7, 8, 9, 10, 11, 12] } # Stations (optional) L = 160000. # Water Level Measurements (mandatory) x_waterlevel = np.asarray([ 0., 18.5, 33.8, 49.8, 54, 61.1, 75.6, 97.3, 106.8, 119.8, 130.6, 142.7, 148.8 ]) * 1000. # x-coordinate of the measurement locations (in m) phaseM2mouth = 0. # Phase of the M2 tidal water level at the mouth (x=0). M2amp = np.asarray([ 1.77, 1.98, 2.03, 2.18, 2.19, 2.26, 2.31, 2.28, 2.22, 1.69, 1.31, 1.09, 1.02 ]) # M2 amplitude (in m) M2phase = np.asarray([ 0, 10.4, 20.5, 31.1, 33.1, 35.6, 44.3, 62.7, 73.4, 93.3, 116.4, 143.4, 157.4 ]) - phaseM2mouth # M2 phase (in deg) M4amp = np.asarray([ 0.14, 0.12, 0.11, 0.11, 0.12, 0.12, 0.13, 0.16, 0.24, 0.25, 0.24, 0.21, 0.22 ]) # M4 amplitude (in m) M4phase = np.asarray([ -1.3, 12.3, 39.4, 58.7, 62.2, 65.1, 74.6, 88.2, 101.7, 128.7, 164.3, 212.6, 242.9 ]) - 2 * phaseM2mouth # M4 amplitude (in m) # Velocity measurements (optional) x_station_vel = np.asarray( [17, 28, 40, 41, 63, 74, 85, 102, 120, 132, 140]) * 1000. M0vel = np.asarray([ -0.096, -0.09, -0.011, -0.040, -0.007, -0.1, 0.005, -0.011, 0.117, -0.144, 0.037 ]) # subtidal velocity M2velamp = np.asarray([ 1., 1.096, 0.785, 0.818, 0.332, 0.813, 0.56, 0.627, 0.798, 0.680, 0.190 ]) M2velphase = np.asarray([ 301, 285, 164, 176, 243, 298, 344, 291, 103, 283, 98 ]) - phaseM2mouth M4velamp = np.asarray([ 0.109, 0.069, 0.112, 0.066, 0.033, 0.079, 0.085, 0.154, 0.226, 0.254, 0.084 ]) M4velphase = np.asarray([ 311, 281, 69, 67, 234, 28, 329, 248, 27, 221, 22 ]) - 2 * phaseM2mouth ################################################################################################################ # process data ################################################################################################################ water_level = np.zeros((len(x_waterlevel), 3), dtype=complex) water_level[:, 0] = np.nan water_level[:, 1] = M2amp * np.exp(-M2phase / 180. * np.pi * 1j) water_level[:, 2] = M4amp * np.exp(-M4phase / 180. * np.pi * 1j) u_comp = np.zeros((len(x_station_vel), 3), dtype=complex) u_comp[:, 0] = M0vel u_comp[:, 1] = M2velamp * np.exp(-M2velphase / 180. * np.pi * 1j) u_comp[:, 2] = M4velamp * np.exp(-M4velphase / 180. * np.pi * 1j) ################################################################################################################ # grid ################################################################################################################ grid = {} grid['gridtype'] = 'Regular' grid['dimensions'] = ['x', 'f'] grid['axis'] = {} grid['maxIndex'] = {} grid['low'] = {} grid['high'] = {} grid['contraction'] = [[], []] grid['high']['x'] = L grid['low']['x'] = 0. grid['high']['f'] = None grid['low']['f'] = None grid['axis']['f'] = np.asarray([0, 1, 2]).reshape((1, 3)) grid['maxIndex']['f'] = 2 grid_waterlevel = grid grid_velocity = copy.deepcopy(grid) grid_waterlevel['axis']['x'] = x_waterlevel / grid['high']['x'] grid_waterlevel['maxIndex']['x'] = len(x_waterlevel) - 1 grid_velocity['axis']['x'] = x_station_vel / grid['high']['x'] grid_velocity['maxIndex']['x'] = len(x_station_vel) - 1 grid_waterlevel = DataContainer({'grid': grid_waterlevel}) grid_velocity = DataContainer({'grid': grid_velocity}) ################################################################################################################ # load to dictionary ################################################################################################################ # stations d['Scheldt_measurements']['x_stations'] = x_station d['Scheldt_measurements']['stations'] = station_names d['Scheldt_measurements']['sections'] = river_sections # water level nf = nifty.functionTemplates.NumericalFunctionWrapper( water_level, grid_waterlevel) d['Scheldt_measurements']['zeta'] = nf.function d['Scheldt_measurements']['x_waterlevel'] = x_waterlevel # velocity nfu2 = nifty.functionTemplates.NumericalFunctionWrapper( u_comp, grid_velocity) # now saved without phase data d['Scheldt_measurements']['x_velocity'] = x_station_vel d['Scheldt_measurements']['u_comp'] = nfu2.function return d
def run(self): self.logger.info('Running module StaticAvailability') ################################################################################################################ ## Init ################################################################################################################ jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') c0 = self.input.v('hatc0', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) c1_a0 = self.input.v('hatc1', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) c1_a0x = self.input.v('hatc1', 'ax', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) if isinstance(c1_a0x, bool): c1_a0x = np.zeros((jmax + 1, kmax + 1, fmax + 1)) d = {} c0_int = ny.integrate(c0, 'z', kmax, 0, self.input.slice('grid')) B = self.input.v('B', range(0, jmax + 1), [0], [0]) u0 = self.input.v('u0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) zeta0 = self.input.v('zeta0', range(0, jmax + 1), [0], range(0, fmax + 1)) Kh = self.input.v('Kh', range(0, jmax + 1), [0], [0]) ################################################################################################################ ## Second order closure ################################################################################################################ u1 = self.input.v('u1', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) d['T'] = {} d['F'] = {} T0 = 0 F0 = 0 ## Transport T ############################################################################################ ## T.1. - u0*c1_a0 # Total c1a_f0 = c1_a0 T0 += ny.integrate(ny.complexAmplitudeProduct(u0, c1a_f0, 2), 'z', kmax, 0, self.input.slice('grid')) # Decomposition for submod in self.input.getKeysOf('hatc1', 'a'): if submod == 'erosion': for subsubmod in self.input.getKeysOf('hatc1', 'a', 'erosion'): c1_a0_comp = self.input.v('hatc1', 'a', submod, subsubmod, range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) c1a_f0_comp_res = c1_a0_comp d['T'] = self.dictExpand( d['T'], subsubmod, ['TM' + str(2 * n) for n in range(0, fmax + 1) ]) # add submod index to dict if not already # transport with residual availability for n in range(0, fmax + 1): tmp = np.zeros(c1a_f0_comp_res.shape, dtype=complex) tmp[:, :, n] = c1a_f0_comp_res[:, :, n] tmp = ny.integrate( ny.complexAmplitudeProduct(u0, tmp, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T'][subsubmod]['TM' + str(2 * n)] += tmp else: c1_a0_comp = self.input.v('hatc1', 'a', submod, range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) c1a_f0_comp_res = c1_a0_comp d['T'] = self.dictExpand( d['T'], submod, ['TM' + str(2 * n) for n in range(0, fmax + 1) ]) # add submod index to dict if not already # transport with residual availability for n in range(0, fmax + 1): tmp = np.zeros(c1a_f0_comp_res.shape, dtype=complex) tmp[:, :, n] = c1a_f0_comp_res[:, :, n] tmp = ny.integrate(ny.complexAmplitudeProduct(u0, tmp, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T'][submod]['TM' + str(2 * n)] += tmp ## T.2. - u1*c0 # Total T0 += ny.integrate(ny.complexAmplitudeProduct(u1, c0, 2), 'z', kmax, 0, self.input.slice('grid')) # Decomposition for submod in self.input.getKeysOf('u1'): u1_comp = self.input.v('u1', submod, range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) d['T'] = self.dictExpand( d['T'], submod, ['TM' + str(2 * n) for n in range(0, fmax + 1) ]) # add submod index to dict if not already # transport with residual availability for n in range(0, fmax + 1): tmp = np.zeros(u1_comp.shape, dtype=complex) tmp[:, :, n] = u1_comp[:, :, n] if submod == 'stokes': tmp = ny.integrate(ny.complexAmplitudeProduct(tmp, c0, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T'][submod] = self.dictExpand( d['T'][submod], 'TM' + str(2 * n), ['return', 'drift']) d['T'][submod]['TM0']['return'] += tmp else: tmp = ny.integrate(ny.complexAmplitudeProduct(tmp, c0, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T'][submod]['TM' + str(2 * n)] += tmp ## T.5. - u0*c0*zeta0 # Total T0 += ny.complexAmplitudeProduct( ny.complexAmplitudeProduct(u0[:, [0], :], c0[:, [0], :], 2), zeta0, 2) # Decomposition uzeta = ny.complexAmplitudeProduct(u0[:, [0], :], zeta0, 2) d['T'] = self.dictExpand( d['T'], 'stokes', ['TM' + str(2 * n) for n in range(0, fmax + 1)]) # transport with residual availability for n in range(0, fmax + 1): tmp = np.zeros(c0[:, [0], :].shape, dtype=complex) tmp[:, :, n] = c0[:, [0], n] tmp = ny.complexAmplitudeProduct(uzeta, tmp, 2)[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T']['stokes']['TM' + str(2 * n)]['drift'] += tmp ## T.6. - u1riv*c2rivriv c2 = self.input.v('hatc2', 'a', 'erosion', 'river_river', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) u1riv = self.input.v('u1', 'river', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) if u1riv is not None: d['T'] = self.dictExpand( d['T'], 'river_river', 'TM0') # add submod index to dict if not already tmp = ny.integrate(ny.complexAmplitudeProduct(u1riv, c2, 2), 'z', kmax, 0, self.input.slice('grid')) if any(abs(tmp[:, 0, 0])) > 10**-14: d['T']['river_river']['TM0'] = tmp[:, 0, 0] T0 += tmp ## T.7. - diffusive part # Total c0x = self.input.d('hatc0', 'a', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), dim='x') T0 += -Kh * ny.integrate(c0x, 'z', kmax, 0, self.input.slice('grid')) c2x = self.input.d('hatc2', 'a', 'erosion', 'river_river', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), dim='x') T0 += -Kh * ny.integrate(c2x, 'z', kmax, 0, self.input.slice('grid')) # Decomposition d['T'] = self.dictExpand(d['T'], 'diffusion_tide', ['TM0']) d['T'] = self.dictExpand(d['T'], 'diffusion_river', ['TM0']) # transport with residual availability tmp = -(Kh * ny.integrate(c0x, 'z', kmax, 0, self.input.slice('grid')))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T']['diffusion_tide']['TM0'] = tmp tmp = -(Kh * ny.integrate(c2x, 'z', kmax, 0, self.input.slice('grid')))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['T']['diffusion_river']['TM0'] = tmp ## Diffusion F ############################################################################################ ## F.1. - u0*C1ax*f0 # Total F0 += ny.integrate(ny.complexAmplitudeProduct(u0, c1_a0x, 2), 'z', kmax, 0, self.input.slice('grid')) # Decomposition for submod in self.input.getKeysOf('hatc1', 'ax'): c1_ax0_comp = self.input.v('hatc1', 'ax', submod, range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) d['F'] = self.dictExpand( d['F'], submod, ['FM' + str(2 * n) for n in range(0, fmax + 1) ]) # add submod index to dict if not already # transport with residual availability for n in range(0, fmax + 1): tmp = np.zeros(u0.shape, dtype=complex) tmp[:, :, n] = u0[:, :, n] tmp = ny.integrate( ny.complexAmplitudeProduct(tmp, c1_ax0_comp, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['F'][submod]['FM' + str(2 * n)] += tmp ## F.3. - diffusive part # Total F0 += -Kh * ny.integrate(c0, 'z', kmax, 0, self.input.slice('grid')) F0 += -Kh * ny.integrate(c2, 'z', kmax, 0, self.input.slice('grid')) # Decomposition d['F'] = self.dictExpand(d['F'], 'diffusion_tide', ['FM0']) d['F'] = self.dictExpand(d['F'], 'diffusion_river', ['FM0']) # transport with residual availability tmp = -(Kh * ny.integrate(c0, 'z', kmax, 0, self.input.slice('grid')))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['F']['diffusion_tide']['FM0'] = tmp tmp = -(Kh * ny.integrate(c2, 'z', kmax, 0, self.input.slice('grid')))[:, 0, 0] if any(abs(tmp)) > 10**-14: d['F']['diffusion_river']['FM0'] = tmp ## Solve ################################################################################################ ## Add all mechanisms & compute a0c from src.DataContainer import DataContainer dc = DataContainer(d) dc.merge(self.input.slice('grid')) T_til = np.real(dc.v('T', range(0, jmax + 1))) F_til = np.real(dc.v('F', range(0, jmax + 1))) # DEBUG: CHECKS IF COMPOSITE T, F == total T, F # print np.max(abs((dc.v('T', range(0, jmax+1))-T0[:, 0, 0])/(T0[:, 0, 0]+10**-10))) # print np.max(abs((dc.v('F', range(0, jmax+1))-F0[:, 0, 0])/(F0[:, 0, 0]+10**-10))) integral = -ny.integrate(T_til / (F_til - 10**-6), 'x', 0, range(0, jmax + 1), self.input.slice('grid')) if self.input.v('Qsed') is None: G = 0 else: G = self.input.v('Qsed') / B[-1, 0, 0] P = ny.integrate(G / (F_til - 10**-6) * np.exp(-integral), 'x', 0, range(0, jmax + 1), self.input.slice('grid')) ################################################################################################################ # Boundary condition 1 ################################################################################################################ if self.input.v('sedbc') == 'astar': astar = self.input.v('astar') k = astar * ny.integrate(B[:, 0, 0], 'x', 0, jmax, self.input.slice('grid')) / ny.integrate( B[:, 0, 0] * np.exp(integral), 'x', 0, jmax, self.input.slice('grid')) f0 = (k - P) * np.exp(integral) f0x = (-T_til * f0 - G) / (F_til - 10**-6) ################################################################################################################ # Boundary condition 2 ################################################################################################################ elif self.input.v('sedbc') == 'csea': csea = self.input.v('csea') c000 = np.real(c0_int[0, 0, 0]) k = csea / c000 * (self.input.v('grid', 'low', 'z', 0) - self.input.v('grid', 'high', 'z', 0)) f0 = (k - P) * np.exp(integral) f0x = (-T_til * f0 - G) / (F_til - 10**-6) else: from src.util.diagnostics.KnownError import KnownError raise KnownError( 'sediment boundary sedbc not known: use astar or csea') ################################################################################################################ # Store in dict ################################################################################################################ d['a'] = f0 d['c0'] = c0 * f0.reshape((jmax + 1, 1, 1)) d['c1'] = c1_a0 * f0.reshape((jmax + 1, 1, 1)) + c1_a0x * f0x.reshape( (jmax + 1, 1, 1)) d['c2'] = c2 * f0.reshape((jmax + 1, 1, 1)) return d
def run(self): """Run function to initiate the calculation of the sediment concentration based on dynamic erodibility. Hereby, we solve the following three equations: S_t = - [Flux_x + Flux * (B_x/B)] (1) Flux = T*f + F*f_x (2) f = f(Stilde) (3) with: S = sediment stock, which is the total amount of sediment in the water column and the erodible bottom Flux = sediment transport f = relative sediment erodibility B = estuary width T = transport function F = diffusion function Stilde = S / Chat, with Chat is the subtidal carrying capacity Returns: Dictionary with results. At least contains the variables listed as output in the registry """ self.logger.info('Running module DynamicAvailability') ## Initiate variables # general variables self.RHOS = self.input.v('RHOS') self.DS = self.input.v('DS') self.WS = self.input.v('ws0') self.GPRIME = self.input.v('G') * ( self.RHOS - self.input.v('RHO0')) / self.input.v('RHO0') self.Mhat = self.input.v('Mhat') self.CSEA = self.input.v('csea') self.FCAP = self.input.v('fcap') self.P = self.input.v('p') self.TOL = self.input.v('tol') self.ASTAR = self.input.v('astar') self.Kh = self.input.v('Kh') self.L = self.input.v('L') self.x = self.input.v('grid', 'axis', 'x') * self.L self.dx = (self.x[1:] - self.x[:-1]).reshape(len(self.x) - 1, 1) jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') self.z = self.input.v('grid', 'axis', 'z', 0, range(0, kmax + 1)) self.zarr = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0] self.H = (self.input.v('H', range(0, jmax + 1)).reshape(jmax + 1, 1) + self.input.v('R', range(0, jmax + 1)).reshape(jmax + 1, 1)) self.Hx = (self.input.d('H', range(0, jmax + 1), dim='x').reshape( jmax + 1, 1) + self.input.d('R', range(0, jmax + 1), dim='x').reshape(jmax + 1, 1)) self.B = self.input.v('B', range(0, jmax + 1)).reshape(jmax + 1, 1) self.Bx = self.input.d('B', range(0, jmax + 1), dim='x').reshape(jmax + 1, 1) self.sf = self.input.v('Roughness', range(0, jmax + 1), 0, 0).reshape(jmax + 1, 1) self.Av0 = self.input.v('Av', range(0, jmax + 1), 0, 0).reshape(jmax + 1, 1) # velocity self.u1river = np.real( self.input.v('u1', 'river', range(0, jmax + 1), range(0, kmax + 1), 0)) self.Q_fromhydro = -np.trapz(self.u1river[-1, :], x=-self.zarr[-1, :]) * self.B[-1] # c hat self.c00 = np.real( self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1), 0)) self.c04 = self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1), 2) ## Compute transport (in superclass) d = self.compute_transport() dc = DataContainer(d) self.Fc = (dc.v('F', range(0, jmax + 1)) - dc.v('F', 'diffusion_river', range(0, jmax + 1))).reshape( jmax + 1, 1) self.Tc = (dc.v('T') - (dc.v('T', 'river', range(0, jmax + 1)) + dc.v('T', 'river_river', range(0, jmax + 1)) + dc.v('T', 'diffusion_river', range(0, jmax + 1)))).reshape( len(self.x), 1) self.TQ = dc.v('T', 'river', range(0, jmax + 1)).reshape( jmax + 1, 1) / self.Q_fromhydro ## User input #TODO: make a consistent and effective script that handles user input of the discharge time series or any other time-dependent variable #load time serie Q self.dt = self.interpretValues(self.input.v('dt')) if self.input.v('t') is not None: self.t = self.interpretValues(self.input.v('t')) self.Q = self.interpretValues(self.input.v('Q')) ## Run self.logger.info('Running time-integrator') vars = self.implicit() ## Collect output d = {} for key, value in vars.iteritems(): d[key] = value return d
def run(self): """invoke the saveData() method to save by using Pickle. Returns: Empty dictionary. """ self.logger.info('Saving output') ################################################################################################################ # Make all variables from config, input and modules available (note, config not available in output module, see Program.py) ################################################################################################################ # read input file reader = Reader() reader.open(self.input.v('inputFile')) data = reader.read('module') reader.close() # merge the datacontainers of all modules & make the module tags into a list of modules inputvars = DataContainer() module = [] for d in data: module.append(d.v('module')) inputvars.merge(d) inputvars.addData('module', module) # merge input vars with self.input in hierarchy config, input, input for this module, vars calculated in other modules (low - high) # + make a list of all keys of input and config vars; these are saved always and later appended by selected module calc. vars. data = self.__loadConfig() data.merge(inputvars) outputKeys = self.__checkInputOverrides( data ) # checks if input is overwritten and provides the keys of not or correctly overwritten input vars data.merge(self.input) del inputvars, reader # now all variables from config, input and modules are in 'data' ################################################################################################################ # Isolate part of DC to write; put this in saveData ################################################################################################################ saveData = DataContainer() # vars to save outputVariables = toList(self.input.v('requirements')) outputKeys = list( set(outputKeys + self.__getSubmoduleRequirements(outputVariables)) ) # convert the requested output variables to key tuples including submodule requirements for key in outputKeys: if len(key) > 1: saveData.merge({key[0]: data.slice(*key).data}) else: saveData.merge(data.slice(*key)) # add grid and outputgrid if available; needed for interpolating data to outputgrid later saveData.merge(self.input.slice('grid')) saveData.merge(self.input.slice(self.outputgridName)) # add reference level to outputgrid if self.input.v('R') is not None: self.input.merge({ self.outputgridName: { 'low': { 'z': self.input.v('R', x=self.input.v(self.outputgridName, 'axis', 'x')) } } }) # add reference level to outputgrid # make a deepcopy of the data to be saved # NB. very memory inefficient, but needed not to overwrite existing data saveData = deepcopy(saveData) ################################################################################################################ # Convert data using output grid (if this is provided) ################################################################################################################ grid = saveData.slice('grid') outputgrid = saveData.slice(self.outputgridName) saveAnalytical = toList(self.input.v('saveAnalytical')) or [] dontConvert = toList(self.input.v('dontConvert')) or [] if 'all' in saveAnalytical: saveAnalytical = outputVariables if 'all' in dontConvert: dontConvert = outputVariables self._convertData(saveData, grid, outputgrid, saveAnalytical, dontConvert) # rename the outputgrid to grid and replace the original grid in saveData saveData.addData('grid', saveData.data[self.outputgridName]) saveData.data.pop(self.outputgridName) ################################################################################################################ # Make the output directory if it doesnt exist ################################################################################################################ cwdpath = cfm.CWD # path to working directory self.path = os.path.join(cwdpath, self.input.v('path')) if not self.path[-1] == '/': self.path += '/' if not os.path.exists(self.path): os.makedirs(self.path) ################################################################################################################ # set file name and save data ################################################################################################################ filename = self.__makeFileName() # write filepath = (self.path + filename + self.ext) try: with open(filepath, 'wb') as fp: pickle.dump(saveData.data, fp, protocol=pickle.HIGHEST_PROTOCOL) except: raise ################################################################################################################ # return ################################################################################################################ d = {} d['outputDirectory'] = self.path return d