def __init__(self, raw, seg, gt=None, patchSize=[100, 100], **kwargs): #raw input data self.raw = numpy.squeeze(raw) self.seg = numpy.squeeze(seg) self.gt = numpy.squeeze(gt) # shorthands self.shape = self.raw.shape # settings self.patchSize = patchSize # apply paddings ps = self.patchSize padding = ((ps[0], ps[0]), (ps[1], ps[1])) pad = partial(numpy.pad, pad_width=padding) self.paddingMask = pad(numpy.zeros(self.shape), mode='constant', constant_values=1) self.paddedRaw = pad(self.raw, mode='reflect') self.paddedSeg = vigra.analysis.labelImage( pad(self.seg, mode='reflect')).squeeze() self.paddedGt = None if self.gt is not None: self.paddedGt = vigra.analysis.labelImage( pad(self.gt, mode='reflect')).squeeze() #self.paddedGt = pad(self.gt + 1, mode='constant', constant_values=0) # compute cgp self.tGrid = ncgp.TopologicalGrid2D(self.paddedSeg) self.tShape = self.tGrid.topologicalGridShape self.numberOfCells = self.tGrid.numberOfCells self.fGrid = ncgp.FilledTopologicalGrid2D(self.tGrid) self.cellGrids = [ self.fGrid.cellMask([1, 0, 0]), self.fGrid.cellMask([0, 1, 0]), None ] self.cellGrids[0][ self.cellGrids[0] != 0] -= self.fGrid.cellTypeOffset[0] self.cellGrids[1][ self.cellGrids[1] != 0] -= self.fGrid.cellTypeOffset[1] self.cellMasks = [numpy.clip(x, 0, 1) for x in self.cellGrids[0:2]] + [None] rawT = vigra.sampling.resize(self.paddedRaw, self.tShape) #rawT[self.cellMasks[1]!=0] = 0 self.cellsBounds = self.tGrid.extractCellsBounds() self.cellsGeometry = self.tGrid.extractCellsGeometry(fill=True) self.cells1Bounds = self.cellsBounds[1] self.cells1Geometry = self.cellsGeometry[1] # center of mass self.cell1CentersOfMass = self.cells1Geometry.centersOfMass() print(self.cell1CentersOfMass) # compute gt ol = Overlap(self.numberOfCells[2], self.paddedSeg, self.paddedGt) cell1Probs = ol.differentOverlaps(numpy.array(self.cells1Bounds)) with nifty.Timer("makeCellImage"): probImg = ncgp.makeCellImage(rawT, self.cellGrids[1], cell1Probs * 255.0) vigra.imshow(probImg.astype('uint8'), cmap='gist_heat') vigra.show() if False: vigra.imshow(self.paddingMask) vigra.show() vigra.imshow(self.paddedRaw) vigra.show() vigra.segShow(self.paddedRaw, self.paddedSeg) vigra.show() vigra.segShow(self.paddedRaw, self.paddedGt) vigra.show()
class EcologyCore: # Variables logger = logging.getLogger(__name__) time = [ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer()] DT = 24*3600.*10#0.05 # Methods def __init__(self, input): self.input = input return def main(self, components, ws, Kv, Kh, Csea, QC, S, Gamma, Gamma_factor, source): jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') taumax = self.input.v('taumax') or 1 if False:#hasattr(self, 'X'): #DEBUG X = self.X spinup = False else: X = np.zeros((jmax+1, len(components))) spinup = True # time integration and initial condition Chat_prim = np.zeros((jmax+1, kmax+1, len(components))) Chat_int = np.zeros((jmax+1, len(components))) Ts = np.zeros((jmax+1, len(components))) Fs = np.zeros((jmax+1, len(components))) Hs = np.zeros((jmax+1, len(components))) Chat = np.zeros((jmax+1, kmax+1, len(components))) ################################################################################################################ # Compute transport rates & potential concentrations ################################################################################################################ dc = self.input.slice('grid') for i, comp_name in enumerate(components): T, F, Hs[:, i], Chat[:, :, i] = self.component(ws[i], Kv[i], Kh[i]) dc.merge({comp_name: {'T': T}}) dc.merge({comp_name: {'F': F}}) Ts[:, i] = dc.v(comp_name, 'T', range(0, jmax+1)) Fs[:, i] = dc.v(comp_name, 'F', range(0, jmax+1)) # integrals Chat_prim[:, :, i] = -ny.primitive(np.real(Chat[:, :, i]), 'z', 0, kmax, self.input.slice('grid')) # primitive counted from surface Chat_int[:, i] = np.sum(Chat_prim[:, :, i], axis=1) ## process growth function so that no duplicate computations are done Gamma_flat = [item for sublist in Gamma for item in sublist] Gamma_list = list(set(Gamma_flat)) Gamma_index = [[Gamma_list.index(i) for i in j] for j in Gamma] ################################################################################################################ # Initial conditions ################################################################################################################ if spinup: for i, comp_name in enumerate(components): if i==0: P0 = Csea[i]*np.exp(-10*np.linspace(0, 1, jmax+1)) H = self.input.v('grid', 'low', 'z', range(0, jmax+1)) - self.input.v('grid', 'high', 'z', range(0, jmax+1)) X[:, i] = P0/np.real(ny.integrate(Chat[:, :, i], 'z', kmax, 0, self.input.slice('grid'))[:, 0])*H else: # initial condition (equilibrium without growth) integrand = ny.integrate(Ts[:, i]/(Fs[:, i]), 'x', 0, range(0, jmax+1), self.input.slice('grid')) P = QC[i]/(Fs[:, i])*np.exp(integrand.reshape((jmax+1, 1))*np.ones((1, jmax+1))-integrand.reshape((1, jmax+1))) Pint = ny.integrate(P.reshape((jmax+1, 1, 1, jmax+1)), 'x', 0, range(0, jmax+1), self.input.slice('grid')) Pint = Pint[range(0, jmax+1), 0, 0, range(0, jmax+1)] C0 = np.exp(-integrand)*Csea[i] + Pint X[:, i] = C0/Chat_int[:, i]*H self.Xprev = np.ones(X.shape)*np.inf ################################################################################################################ # Time integration ################################################################################################################ init_growth = True ctd = True # set time step if not spinup and self.input.v('dtau'): dtau = self.input.v('dtau')*24*3600. tau = np.linspace(0, dtau, np.ceil(dtau/self.DT)+1) i_tau_now = 0 dt = tau[1]-tau[0] else: dt = self.DT spinup = True # run time stepping dind = 0 # index for the iteration number self.dif_prev = np.inf # difference in previous step (only in spin-up) while ctd: dind +=1 ## Growth functions Gamma_eval = [fun(Chat, Chat_prim, Chat_int, X[:, :], init_growth) for fun in Gamma_list] init_growth = False Gamma_sum = [self.sumdict(copy(j)) for j in Gamma_eval] Gamma = [[Gamma_sum[i] for i in j] for j in Gamma_index] for i, comp_name in enumerate(components): G = sum([a*b for a,b in zip(Gamma_factor[i], Gamma[i])]) G += source[:, i] X[:, i] = cSolverTime(Ts[:, i], Fs[:, i], np.zeros(jmax+1), G, Hs[:, i], Hs[:, i]*X[:, i], X[0, i], 'flux', QC[i], dt, X[:, i], self.input) if spinup: dif = self.DT/dt*np.linalg.norm((X - self.Xprev)/(X+0.001*np.max(X)), np.inf) print dind, dif ## DEBUG # if np.max(X[:, 0]) > 50/1000. and dind > 100: # print 'exit simulation; non-realistic result' # ctd = False # X = np.nan*X ## END # print dif if dif < 10**-5 or dind>2000:#10**-8: ctd = False elif self.dif_prev < dif and dind > 100: # adjust time step if diffence increases after 200th iteration (only in spin-up) dt = dt/2. dind = 0 print 'timestep: ' + str(dt) else: self.Xprev = copy(X) self.dif_prev = dif else: i_tau_now += 1 if i_tau_now == len(tau)-1: ctd = False ################################################################################################################ ## Return ################################################################################################################ self.X = copy(X) Gamma = [[Gamma_eval[i] for i in j] for j in Gamma_index] # Gamma2 = [0]*len(Gamma) # for i in range(0, len(Gamma)): # for j in range(1, len(Gamma[i])): # mergeDicts(Gamma[i][0], Gamma[i][j]) # Gamma2[i] = Gamma[i][0] d = {} d['Ceco'] = {} d['Teco'] = {} d['Feco'] = {} d['Geco'] = {} for i, comp_name in enumerate(components): d['Ceco'][comp_name] = Chat[:, :, i]*X[:, i].reshape(jmax+1, 1) d['Geco'][comp_name] = {} for j in range(0, len(Gamma[i])): d['Geco'][comp_name].update(Gamma[i][j]) # d['Geco'][comp_name] = mergeDicts(d['Geco'][comp_name], Gamma[i][j]) d['Teco'][comp_name] = dc.data[comp_name]['T'] d['Feco'][comp_name] = dc.data[comp_name]['F'] return d def update(self, dlist_old, dlist_new): return [mergeDicts(dlist_old[j], dlist_new[j]) for j in range(0, len(dlist_old))] def sumdict(self, d): for k in d.keys(): if isinstance(d[k], dict): d[k] = self.sumdict(d[k]) return sum(d.values()) def component(self, ws, Kv, Kh): jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') z = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0] depth = (self.input.v('grid', 'low', 'z', range(0, jmax+1)) - self.input.v('grid', 'high', 'z', range(0, jmax+1))).reshape((jmax+1, 1)) B = self.input.v('B', range(0, jmax+1)) u0 = self.input.v('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) w0 = self.input.v('w0', 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)) ################################################################################################################ # Leading order ################################################################################################################ Chat = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex) if ws[0,0] != 0: k = depth*ws[:, [-1]]/Kv[:, [-1]]*(1-np.exp(-ws[:, [-1]]/Kv[:, [-1]]*depth))**-1. else: k = 1 Chat[:, :, 0] = k*np.exp(-ws[:, [-1]]/Kv[:, [-1]]*(z+depth)) # k is such that depth-av Chat = 1. Chatx = ny.derivative(Chat, 'x', self.input.slice('grid')) Chatz = -(ws[:, [-1]]/Kv[:, [-1]]).reshape((jmax+1, 1, 1))*Chat ################################################################################################################ # First order ################################################################################################################ F = np.zeros((jmax+1, kmax+1, 2*fmax+1, 2), dtype=complex) Fsurf = np.zeros((jmax+1, 1, 2*fmax+1, 2), dtype=complex) Fbed = np.zeros((jmax+1, 1, 2*fmax+1, 2), dtype=complex) ## forcing terms # advection F[:, :, fmax:, 0] = -ny.complexAmplitudeProduct(u0, Chatx, 2) - ny.complexAmplitudeProduct(w0, Chatz, 2) F[:, :, fmax:, 1] = -ny.complexAmplitudeProduct(u0, Chat, 2) ## solve Chat1, _ = pFunction(1, ws, Kv, F[:, :, fmax+1], Fsurf[:, :, fmax+1], Fbed[:, :, fmax+1], self.input) Chat1 = ny.eliminateNegativeFourier(Chat1, 2) ################################################################################################################ # Closure ################################################################################################################ # transport T = {} T['adv'] = {} T['adv']['tide'] = np.real(ny.integrate(ny.complexAmplitudeProduct(u0, Chat1[:, :, :, 0], 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B) for key in self.input.getKeysOf('u1'): utemp = self.input.v('u1', key, range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) try: T['adv'][key] += np.real(ny.integrate(ny.complexAmplitudeProduct(utemp, Chat, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B) except: T['adv'][key] = np.real(ny.integrate(ny.complexAmplitudeProduct(utemp, Chat, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B) T['dif'] = - np.real(ny.integrate(ny.complexAmplitudeProduct(Kh, Chatx, 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B) T['noflux'] = np.real(ny.complexAmplitudeProduct(ny.complexAmplitudeProduct(u0[:, [0], :], Chat[:, [0], :], 2), zeta0, 2)[:, 0, 0]*B) F = {} F['adv'] = {} F['adv']['tide'] = np.real(ny.integrate(ny.complexAmplitudeProduct(u0, Chat1[:, :, :, -1], 2), 'z', kmax, 0, self.input.slice('grid'))[:, 0, 0]*B) F['dif'] = - np.real(Kh[:, 0]*depth[:, 0]*B) H1 = np.real(depth[:, 0]*B) return T, F, H1, Chat[:, :, 0]
class DynamicAvailability(EquilibriumAvailability): # Variables logger = logging.getLogger(__name__) theta = 1. # theta=0 is Forward Euler, theta=1 is Backward Euler and theta=0.5 is Crank-Nicolson TOL = 1.e-10 MAXITER = 100 timer = ny.Timer() # Methods def __init__(self, input): EquilibriumAvailability.__init__(self, input) self.input = input return 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 update_transport(self, Q): """Update transport terms T and F for time dependent river discharge forcing Q. Parameters: Q - river discharge Q Returns: T - advection function F - diffusion function A - variable appearing the the Exner equation, i.e. A = (BF)_x / B C20 - second-order sediment concentration """ # T - river T_riv = self.TQ * Q # T - river_river ur = self.uQ * Q hatc2 = self.update_hatc2(ur[:, -1]) T_rivriv = np.real(np.trapz(ur * hatc2, x=-self.zarr, axis=1)) # T - diffusion river hatc2x = np.gradient(hatc2, self.x, axis=0, edge_order=2) T_difriv = -self.Kh * np.real(np.trapz(hatc2x, x=-self.zarr, axis=1)) # F - diffusion river F_difriv = -self.Kh * np.real(np.trapz(hatc2, x=-self.zarr, axis=1)) return T_riv, T_rivriv, T_difriv, F_difriv def update_hatc2(self, u_riv_bed): """Update shear stress for hatc2 based on varying river discharge""" jmax = self.input.v('grid', 'maxIndex', 'x') RHOS = self.input.v('RHOS') RHO0 = self.input.v('RHO0') DS = self.input.v('DS') GPRIME = self.input.v('G') * (RHOS - RHO0) / RHO0 # HR = (self.input.v('H', range(0, jmax + 1)).reshape(jmax + 1, 1) + self.input.v('R', range(0, jmax + 1)).reshape(jmax + 1, 1)) WS = self.input.v('ws0', range(0, jmax + 1), [0], 0) Kv0 = self.input.v('Kv', range(0, jmax + 1), 0, 0).reshape(jmax + 1, 1) if self.input.v('friction') is not None: sf = self.input.v(self.input.v('friction'), range(0, jmax + 1), 0, 0).reshape(jmax + 1, 1) else: sf = self.input.v('Roughness', range(0, jmax + 1), 0, 0).reshape(jmax + 1, 1) finf = self.input.v('finf') # shear stress T = np.linspace(0, 2 * np.pi, 100) utid = np.zeros((jmax + 1, len(T)), dtype='complex') ucomb = np.zeros((jmax + 1, len(T)), dtype='complex') for i, t in enumerate(T): utid[:, i] = 0.5 * (self.u0tide_bed * np.exp(1j * t) + np.conj(self.u0tide_bed) * np.exp(-1j * t)) ucomb[:, i] = u_riv_bed + 0.5 * (self.u0tide_bed * np.exp( 1j * t) + np.conj(self.u0tide_bed) * np.exp(-1j * t)) uabs_tid = np.mean(np.abs(utid), axis=1) uabs_tot = np.mean(np.abs(ucomb), axis=1) uabs_eps = (uabs_tot - uabs_tid).reshape(jmax + 1, 1) # erosion if self.input.v('erosion_formulation') == 'Partheniades': Ehat = finf * sf * (uabs_eps) * RHO0 else: Ehat = (WS * finf * RHOS * sf / (GPRIME * DS)) * (uabs_eps) hatc2 = np.real(Ehat / WS * np.exp(-WS * (HR + self.zarr) / Kv0)) return hatc2 def init_stock(self, f, alpha1, alpha2): """Compute stock given f, alpha1 and alpha2. For f=1, S equals Smax, which is S corresponding to f=0.999. """ # Establish initial minimum stock Smax, such that f=0.999 Smax = np.array([0.999]) # initial guess F = self.erodibility_stock_relation(alpha2[[0]], Smax) - np.array( [0.999]) while max(abs(F)) > 10**-4: dfdS = self.erodibility_stock_relation_der(alpha2[[0]], Smax) Smax = Smax - F / dfdS F = self.erodibility_stock_relation(alpha2[[0]], Smax) - np.array( [0.999]) # Newton-Raphson iteration towards actual Shat # init Shat = f F = self.erodibility_stock_relation(alpha2, Shat) - f i = 0 while max(abs(F)) > self.TOL and i < 50: i += 1 dfdS = self.erodibility_stock_relation_der(alpha2, Shat) Shat = Shat - F / (dfdS + 10**-12) F = self.erodibility_stock_relation(alpha2, Shat) - f if i == 50: f = self.erodibility_stock_relation(alpha2, Shat) Shat = np.minimum(Shat, Smax) return Shat * alpha1 def timestepping(self, T, F, alpha1, alpha2, Told, Fold, alpha1old, alpha2old, Xold, fsea, G): """ """ jmax = self.input.v('grid', 'maxIndex', 'x') A = np.zeros((4, jmax + 1)) rhs = np.zeros((jmax + 1)) Sold = Xold[jmax + 1:] hatSold = Sold / alpha1old fold = Xold[:jmax + 1] h = self.erodibility_stock_relation(alpha2old, hatSold) hder = self.erodibility_stock_relation_der(alpha2old, hatSold) hda2 = self.erodibility_stock_relation_da2(alpha2old, hatSold) beta = h - hder * hatSold + hda2 * (alpha2 - alpha2old) Tx = np.gradient(T, self.x, edge_order=2) Fx = np.gradient(F, self.x, edge_order=2) dif = self.B * F adv = self.B * T + self.Bx * F + self.B * Fx BTx = self.B * Tx + self.Bx * T Txold = np.gradient(Told, self.x, edge_order=2) Fxold = np.gradient(Fold, self.x, edge_order=2) dif_old = self.B * Fold adv_old = self.B * Told + self.Bx * Fold + self.B * Fxold BTx_old = self.B * Txold + self.Bx * Told # interior A[0, 2:] = +self.theta * np.minimum(adv[1:-1], 0) * hder[2:] / ( alpha1[2:] * self.dx[1:]) + self.theta * dif[1:-1] / ( 0.5 * (self.dx[1:] + self.dx[:-1])) * hder[2:] / alpha1[2:] / self.dx[1:] A[1, 1:-1] = self.B[1:-1]/self.dt + self.theta*BTx[1:-1]*hder[1:-1]/alpha1[1:-1] + \ self.theta*np.maximum(adv[1:-1], 0)*hder[1:-1]/(alpha1[1:-1]*self.dx[:-1]) - self.theta*np.minimum(adv[1:-1], 0)*hder[1:-1]/(alpha1[1:-1]*self.dx[1:]) \ - self.theta*dif[1:-1]/(0.5*(self.dx[1:]+self.dx[:-1]))*hder[1:-1]/alpha1[1:-1]*(1./self.dx[1:]+1./self.dx[:-1]) A[2, :-2] = -self.theta * np.maximum(adv[1:-1], 0) * hder[:-2] / ( alpha1[:-2] * self.dx[:-1]) + self.theta * dif[1:-1] / ( 0.5 * (self.dx[1:] + self.dx[:-1])) * hder[:-2] / alpha1[:-2] / self.dx[:-1] rhs[1:-1] = self.B[1:-1]/self.dt*Sold[1:-1] - self.theta*BTx[1:-1]*beta[1:-1] - self.theta*np.maximum(adv[1:-1], 0)*(beta[1:-1]-beta[:-2])/self.dx[:-1] - self.theta*np.minimum(adv[1:-1], 0)*(beta[2:]-beta[1:-1])/self.dx[1:] \ -self.theta*dif[1:-1]*((beta[2:]-beta[1:-1])/self.dx[1:] - (beta[1:-1]-beta[:-2])/self.dx[:-1])/(0.5*(self.dx[1:]+self.dx[:-1])) \ + (1-self.theta) * (-BTx_old[1:-1]*fold[1:-1] - np.maximum(adv_old[1:-1], 0)*(fold[1:-1]-fold[:-2])/self.dx[:-1] - np.minimum(adv_old[1:-1], 0)*(fold[2:]-fold[1:-1])/self.dx[1:] \ -dif_old[1:-1]*((fold[2:]-fold[1:-1])/self.dx[1:] - (fold[1:-1]-fold[:-2])/self.dx[:-1])/(0.5*(self.dx[1:]+self.dx[:-1]))) rhs[1:-1] += -self.B[1:-1] * G[1:-1] # Quick fix for ensuring positivity (Patankar, 1980); could be neater for greater accuracy A[1, 1:-1] += -np.minimum(rhs[1:-1], 0) / (Sold[1:-1] + 1.e-6) rhs[1:-1] = np.maximum(rhs[1:-1], 0) # Boundaries # x=0 if hder[0] == 0: A[1, 0] = 1 rhs[0] = Sold[0] else: A[1, 0] = hder[0] / alpha1[0] rhs[0] = fsea - h[0] + hder[0] * hatSold[0] # x=L if hder[-1] == 0: A[1, -1] = 1 # TODO - needs correction; VIOLATION OF MASS BALANCE. This line will only apply in case Q1 = 0 rhs[-1] = Sold[-1] self.logger.warning( 'f=1 at upstream boundary. The code is not correct for this case and mass balance may be violated. Please investigate.' ) else: A[1, -1] = self.B[-1] * T[-1] * hder[-1] / alpha1[ -1] + 3. / 2. * self.B[-1] * F[-1] * hder[-1] / alpha1[ -1] / self.dx[-1] A[2, -2] = -2. * self.B[-1] * F[-1] * hder[-2] / alpha1[ -2] / self.dx[-1] A[3, -3] = 0.5 * self.B[-1] * F[-1] * hder[-3] / alpha1[ -3] / self.dx[-1] rhs[-1] = -self.B[-1] * T[-1] * beta[-1] - self.B[-1] * F[-1] * ( 3. / 2. * beta[-1] - 2. * beta[-2] + 0.5 * beta[-3]) / self.dx[-1] rhs[-1] += -self.B[-1] * G[-1] # alternative first order # A[1, -1] = self.B[-1]*T[-1]*hder[-1]/alpha1[-1] + self.B[-1]*F[-1]*hder[-1]/alpha1[-1]/self.dx[-1] # A[2, -2] = -1.*self.B[-1]*F[-1]*hder[-2]/alpha1[-2]/self.dx[-1] # rhs[-1] = -self.B[-1]*T[-1]*beta[-1] - self.B[-1]*F[-1]*(1*beta[-1] - 1.*beta[-2])/self.dx[-1] # rhs[-1] += self.B[-1]*G[-1] try: S = scipy.linalg.solve_banded((2, 1), A, rhs, overwrite_ab=False, overwrite_b=False) except: print Xold[:jmax + 1] raise KnownError('Time integration failed.') f = self.erodibility_stock_relation(alpha2, S / alpha1) X = np.concatenate((f, S), axis=0) return X def interpretValues(self, values): """inpterpret values on input as space-separated list or as pure python input Parameters values - values to evaluate Returns: values - evaluated values """ values = toList(values) # case 1: pure python: check for (, [, range, np.arange # merge list to a string valString = ' '.join([str(f) for f in values]) # try to interpret as python string if any([i in valString for i in ['(', '[', ',', '/', '*', '+', '-']]): try: valuespy = None exec('valuespy =' + valString) return valuespy except Exception as e: try: errorString = ': ' + e.message except: errorString = '' raise KnownError( 'Failed to interpret input as python command %s in input: %s' % (errorString, valString), e) # case 2: else interpret as space-separated list else: return values
blocking = nifty.tools.blocking(roiBegin=[0] * 3, roiEnd=shape, blockShape=blockShape) numberOfBlocks = blocking.numberOfBlocks nThreads = 40 if True: # now the same in python h5File = h5py.File(fileName, 'r') array = h5File[dsetName] lock = threading.Lock() with nifty.Timer("python"): val = long(0) def f(blockIndex): global val block = blocking.getBlock(blockIndex) b, e = block.begin, block.end with lock: subarray = array[b[0]:e[0], b[1]:e[1], b[2]:e[2]] _val = subarray[0, 0, 0] val += long(_val) nifty.tools.parallelForEach(range(numberOfBlocks), f=f, nWorkers=nThreads)
affinities = numpy.require(affinities, dtype='float32', requirements=['C']) # load raw import skimage.io raw_path = "/home/tbeier/src/nifty/src/python/examples/multicut/NaturePaperDataUpl/ISBI2012/raw_test.tif" #raw_path = '/home/tbeier/src/nifty/mysandbox/NaturePaperDataUpl/ISBI2012/raw_test.tif' raw = skimage.io.imread(raw_path) raw = raw[z, 0:w, 0:w] isMergeEdgeOffset = numpy.zeros(offsets.shape[0], dtype='bool') isMergeEdgeOffset[0:2] = True if True: affinities = vigra.gaussianSmoothing(vigra.taggedView(affinities, 'xyc'), 0.2) with nifty.Timer("jay"): nodeSeg = nifty.graph.agglo.pixelWiseFixation2D( mergePrios=( 1.0 - affinities ), #vigra.gaussianSmoothing(vigra.taggedView( (1.0 - affinities),'xyc'),0.01), notMergePrios= affinities, #vigra.gaussianSmoothing(vigra.taggedView( (affinities),'xyc'),0.01), offsets=offsets, isMergeEdgeOffset=isMergeEdgeOffset) #nodeSeg = nodeSeg.reshape(shape) import pylab pylab.imshow(nodeSeg) pylab.show()
class KEFittedMAW: # Variables TOLLERANCE = 1.e-3 # relative convergence criterion for Av RELAX = 0.8 # relaxation value; as RELAX*old estimate + (1-RELAX)*new estimate invfft_length = 90 LOCAL = 0.5 filterlength = 15 cmax = [] ETMloc = [] logger = logging.getLogger(__name__) timers = [ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer(), ny.Timer()] # Methods def __init__(self, input): self.input = input self.kem = KEFittedTruncated(self.input) return def stopping_criterion(self, iteration): self.iteration = iteration ## Check convergence if self.difference < self.TOLLERANCE*(1-self.RELAX):# or self.iteration>10: if self.betac == 0 and not self.input.v('BETAC') == 0: self.betac = self.input.v('BETAC') self.logger.info('\tMAW starting to include density differences, rel. difference may go up.') return False else: return True else: return False def run_init(self): self.logger.info('Running MAW turbulence model - init') self.difference = np.inf d = {} dkem = self.kem.run_init() # initialise KE model self.kem.referenceLevel = False # only let KE model compute the initial reference level self.betac = self.input.v('BETAC') # set density dependency parameter for sediment self.referenceLevel = self.input.v('referenceLevel') # include computation of reference level in computation (boolean) Av = self.input.v('Av') Kv = self.input.v('Kv') Ri = self.input.v('Ri') Roughness = self.input.v('Roughness') skin_friction = self.input.v('skin_friction') jmax = self.input.v('grid', 'maxIndex', 'x') fmax = self.input.v('grid', 'maxIndex', 'f') # Initialisation uses data that might be available, or starts clean if Av is None or Roughness is None: d.update(dkem) # use input from initial k-eps fitted run - contains Av and Roughness self.input.merge(d) if Ri is None or skin_friction is None: self.betac = 0 # start without density effect, first allow KEFitted to converge self.Rida = 0. # initially set skin friction equal to roughness data = self.input.slice('grid') data.addData('coef', self.input.v('Roughness', range(0, jmax+1), 0, range(0, fmax+1))) ss = UniformXF(['x', 'f'], data, 0.).function d['skin_friction'] = ss if Kv is None: # make eddy diffusivity Av = self.input.v('Av', range(0, jmax+1), 0, range(0, fmax+1)) data = self.input.slice('grid') data.addData('coef', Av/self.input.v('sigma_rho', range(0, jmax+1), 0, [0])) Kv = UniformXF(['x', 'f'], data, 0.).function d['Kv'] = Kv # all first-order turbulence quantities are set to zero d['Kv1'] = 0. d['Av1'] = 0. d['Roughness1'] = 0. d['skin_friction1'] = 0. d['BottomBC'] = 'PartialSlip' return d def run(self): ################################################################################################################ ## 1. Init ################################################################################################################ # self.timers[0].tic() ## prepare output message self.logger.info('Running MAW turbulence model') denstr = '' if self.betac ==0: denstr = '- not including density effects' self.logger.info('\tMAW rel. difference in Av in last iteration: %s %s' % (self.difference, denstr)) d = {} jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') G = self.input.v('G') rho0 = self.input.v('RHO0') uzmin = self.input.v('uzmin') Avold = self.input.v('Av', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) Kvold = self.input.v('Kv', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) sfold = self.input.v('Roughness', range(0, jmax+1), 0, 0) # self.timers[0].toc() ################################################################################################################ ## 2. KEFitted run ################################################################################################################ # self.timers[1].tic() d.update(self.kem.run()) self.input.merge(d) # load data resulting from KEFitted model Avmid = self.input.v('Av', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1)) Kvmid = Avmid/self.input.v('sigma_rho', range(0, jmax+1), range(0, kmax+1), [0]) sfmid = self.input.v('Roughness', range(0, jmax+1), 0, 0) # self.timers[1].toc() ################################################################################################################ ## 3. Density effects ################################################################################################################ if self.betac == 0: # no density effect included, first let KEFitted spin up Av0 = Avmid[:, :, 0] Kv0 = Kvmid[:, :, 0] sf = sfmid Cd = 1. MA_av = 1. MA_kv = 1. Ri = 0. else: ## Load data # self.timers[2].tic() cz = self.input.d('c0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('c1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('c2', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') uz = self.input.d('u0', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') + self.input.d('u1', range(0, jmax+1), range(0, kmax+1), range(0, fmax+1), dim='z') zeta0 = self.input.v('zeta0', range(0, jmax+1), [0], range(0, fmax+1)) H = self.input.v('grid', 'low', 'z', range(0, jmax+1)) - self.input.v('grid', 'high', 'z', range(0, jmax+1)) # self.timers[2].tic() ## Convert to time series # self.timers[3].tic() cz = ny.invfft2(cz, 2, 90) uz = ny.invfft2(uz, 2, 90) zeta0 = ny.invfft2(zeta0, 2, 90) Avmid = ny.invfft2(Avmid, 2, 90) Kvmid = ny.invfft2(Kvmid, 2, 90) # self.timers[3].toc() # self.timers[4].tic() uzmin = np.ones(uz.shape)*uzmin ## Compute Richardson number Ri = -G*self.betac/rho0*cz/(uz**2+uzmin**2) Rida = 1./H.reshape((jmax+1, 1, 1))*ny.integrate(Ri.reshape((jmax+1, kmax+1, 1, Ri.shape[-1])), 'z', kmax, 0, self.input.slice('grid')).reshape((jmax+1, 1, Ri.shape[-1])) # depth-average Rida += zeta0*(Ri[:, [0], :]-Rida)/H.reshape((jmax+1, 1, 1)) # depth average continued Rida0 = np.maximum(Rida, 0.) # only accept positive Ri Ribed = np.maximum(Ri[:, [-1], :], 0.) # only accept positive Ri Ribedmax = self.input.v('Ribedmax') Ribed = np.minimum(Ribed, Ribedmax) # 5-3-2018 limit near-bed Ri ## relaxation on Rida if hasattr(self, 'Rida'): # Relaxation of Ri_da using previously saved value dRida = self.Rida - Rida0 Rida = np.max((Rida0, np.min((dRida * (1 - self.RELAX), dRida * (1. + self.RELAX)), axis=0) + Rida0), axis=0) Rida = np.min((Rida, np.max((dRida * (1 - self.RELAX), dRida * (1. + self.RELAX)), axis=0) + Rida0), axis=0) self.Rida = Rida else: # No value saved if the init found an available Ri. Then start with full signal computed here (do not use saved value, as this has been truncated to frequency components) Rida = Rida0 # self.timers[4].toc() ## Compute damping functions # self.timers[5].tic() # Av MA_av = (1+10*Rida)**(-0.5) dAv = ny.fft(Avmid*MA_av, 2)[:, :, :fmax+1] - Avold Av = Avold + (1-self.RELAX)*(self.LOCAL*dAv + .5*(1-self.LOCAL)*dAv[[0]+range(0, jmax), :, :] + .5*(1-self.LOCAL)*dAv[range(1, jmax+1)+[jmax], :, :]) # Av = Avold + dAv Av0 = Av[:, :, 0] # Kv MA_kv = (1+3.33*Rida)**(-1.5) dKv = ny.fft(Kvmid*MA_kv, 2)[:, :, :fmax+1] - Kvold Kv = Kvold + (1-self.RELAX)*(self.LOCAL*dKv + .5*(1-self.LOCAL)*dKv[[0]+range(0, jmax), :, :] + .5*(1-self.LOCAL)*dKv[range(1, jmax+1)+[jmax], :, :]) # Kv = Kvold + dKv Kv0 = Kv[:, :, 0] # Sf Rfmean = np.mean(Ribed[:, 0, :]*(Kvmid*MA_kv)[:, 0, :]/(Avmid*MA_av)[:, 0, :], axis=-1) Cd = (1+5.5*Rfmean)**-2. damp_sf = Cd sf = sfmid*damp_sf dsf = sf - sfold sf = sfold + (1-self.RELAX)*(self.LOCAL*dsf + .5*(1-self.LOCAL)*dsf[[0]+range(0, jmax)] + .5*(1-self.LOCAL)*dsf[range(1, jmax+1)+[jmax]]) # self.timers[5].toc() # process for output MA_av = ny.fft(MA_av, 2)[:, :, :fmax+1] MA_kv = ny.fft(MA_kv, 2)[:, :, :fmax+1] Ri = ny.fft(Ri, 2)[:, :, :fmax+1] ################################################################################################################ ## Reference level ################################################################################################################ if self.referenceLevel == 'True': self.input.merge({'Av': Av0, 'Roughness': sf}) d['R'] = self.kem.RL.run()['R'] ################################################################################################################ ## Compute difference ################################################################################################################ Av0s = ny.savitzky_golay(Av0[:, 0], self.filterlength, 1) difference = np.max(abs(Av0s-Avold[:, 0, 0])/abs(Av0s+10**-4)) self.difference = copy.copy(difference) ############################################################################################################### # DEBUG plots ############################################################################################################### # import matplotlib.pyplot as plt # import step as st # x = ny.dimensionalAxis(self.input.slice('grid'), 'x')[:, 0,0] # # if self.betac > 0 and np.mod(self.iteration, 3)==0: # and self.difference>0.15: # st.configure() # plt.figure(1, figsize=(2,2)) # plt.subplot(1,2,1) # plt.plot(x/1000., Avold[:, 0, 0], label='old') # plt.plot(x/1000., Av0[:, 0], label='new') # plt.ylim(0, np.maximum(np.max(Av0[:, 0]), np.max(Avold[:, 0, 0]))) # plt.legend() # # plt.subplot(1,2,2) # plt.plot(x/1000., Avold[:, 0, 0]-Av0[:, 0]) # plt.twinx() # plt.plot(x/1000., self.input.v('f', range(0, jmax+1)), color='grey') # plt.ylim(0, 1.) # # st.save('plot_'+str(len(x))+'_'+str(self.iteration)) # # plt.figure(2, figsize=(1, 2)) # ws = self.input.v('ws0', range(0, jmax+1), 0, 0) # plt.plot(x/1000., ws) # # st.save('ws_'+str(len(x))+'_'+str(self.iteration)) ################################################################################################################ ## Prepare Output ################################################################################################################ # self.timers[6].tic() x = ny.dimensionalAxis(self.input.slice('grid'),'x')[:, 0,0] nf = ny.functionTemplates.NumericalFunctionWrapper(ny.savitzky_golay(Av0[:, 0], self.filterlength, 1).reshape((jmax+1, 1)), self.input.slice('grid')) nf.addDerivative(ny.savitzky_golay(ny.derivative(Av0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'x') nf.addDerivative(ny.savitzky_golay(ny.secondDerivative(Av0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'xx') d['Av'] = nf.function nf2 = ny.functionTemplates.NumericalFunctionWrapper(ny.savitzky_golay(Kv0[:, 0], self.filterlength, 1).reshape((jmax+1, 1)), self.input.slice('grid')) nf2.addDerivative(ny.savitzky_golay(ny.derivative(Kv0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'x') nf2.addDerivative(ny.savitzky_golay(ny.secondDerivative(Kv0[:, 0], 'x', self.input), self.filterlength, 1).reshape((jmax+1, 1)), 'xx') d['Kv'] = nf2.function d['Roughness'] = sf d['skin_friction'] = sfmid d['dampingFunctions'] = {} d['dampingFunctions']['Roughness'] = Cd d['dampingFunctions']['Av'] = MA_av d['dampingFunctions']['Kv'] = MA_kv d['Ri'] = Ri # self.timers[6].toc() ## Timers # self.timers[0].disp('0 init MAW') # self.timers[1].disp('1 KEFitted') # self.timers[2].disp('2 load data') # self.timers[3].disp('3 invfft') # self.timers[4].disp('4 Ri') # self.timers[5].disp('5 Compute Av, Kv, sf') # self.timers[6].disp('6 Load in dict') return d
class SedimentCapacity: # Variables logger = logging.getLogger(__name__) timer = ny.Timer() # Methods def __init__(self, input): self.input = input return def run(self): self.timer.tic() self.logger.info('Running module Sediment Capacity') ## Init d = {} self.submodulesToRun = ny.toList(self.input.v('submodules')) self.erosion_method = self.input.v('erosion_formulation') self.frictionpar = self.input.v( 'friction' ) # friction parameter used for the erosion, by default the total roughness if self.frictionpar == None: self.frictionpar = 'Roughness' jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') self.Kv = self.input.v('Kv', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) self.ws = self.input.v('ws0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) ## Run orders d.update(self.leading_order(d)) d.update(self.first_order(d)) d.update(self.second_order_river(d)) self.timer.toc() self.timer.disp('time sediment capacity') self.timer.reset() # d['hatc0']['a']['erosion'][:, :, 0] += 1e-4 return d def leading_order(self, d): jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') ftot = 2 * fmax + 1 ################################################################################################################ # Forcing terms ################################################################################################################ F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex) Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex) Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex) # erosion E = erosion(self.ws, 0, self.input, self.erosion_method, friction=self.frictionpar) Fbed[:, :, fmax:, 0] = -E ################################################################################################################ # Solve equation ################################################################################################################ # Coupled system c, cMatrix = cFunction(self.ws, self.Kv, F, Fsurf, Fbed, self.input, hasMatrix=False) c = c.reshape((jmax + 1, kmax + 1, ftot)) hatc0 = ny.eliminateNegativeFourier(c, 2) # Uncoupled system # hatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex) # hatc0[:, :, 0] = cFunctionUncoupled(self.ws, self.Kv, F, Fsurf, Fbed, self.input, 0).reshape((jmax+1, kmax+1)) # hatc0[:, :, 2] = cFunctionUncoupled(self.ws, self.Kv, F, Fsurf, Fbed, self.input, 2).reshape((jmax+1, kmax+1)) # correction at the bed (optional) # cbed00 = E[:, -1, 0]/self.ws[:, -1, 0] # frac = cbed00/hatc0[:, -1, 0] # hatc0 = hatc0*frac.reshape((jmax+1, 1, 1)) ## analytical solutions # ahatc0 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex) # ahatc02 = np.zeros((jmax+1, kmax+1, fmax+1), dtype=complex) # z = ny.dimensionalAxis(self.input.slice('grid'), 'z')[:, :, 0] # self.ws = self.ws[:, 0, 0] # self.Kv = self.Kv[:, 0, 0] # OMEGA = self.input.v('OMEGA') # H = self.input.v('H', range(0, jmax+1)) # # # M0 # ahatc0[:, :, 0] = (E[:, 0, 0]/self.ws).reshape((jmax+1, 1))*np.exp(-(self.ws/self.Kv).reshape((jmax+1, 1))*(z+H.reshape((jmax+1, 1)))) # # # # M4 # # r1 = -self.ws/(2.*self.Kv)+np.sqrt(self.ws**2+8*1j*OMEGA*self.Kv)/(2*self.Kv) # r2 = -self.ws/(2.*self.Kv)-np.sqrt(self.ws**2+8*1j*OMEGA*self.Kv)/(2*self.Kv) # k2 = -E[:, 0, 2]*(self.Kv*(-r1*(self.ws+self.Kv*r2)/(self.ws+self.Kv*r1)*np.exp(-r1*H) + r2*np.exp(-r2*H)))**-1. # k1 = -k2*(self.ws+self.Kv*r2)/(self.ws+self.Kv*r1) # ahatc0[:, :, 2] = k1.reshape((jmax+1, 1))*np.exp(r1.reshape((jmax+1, 1))*z) + k2.reshape((jmax+1, 1))*np.exp(r2.reshape((jmax+1, 1))*z) # import step as st # import matplotlib.pyplot as plt # # st.configure() # plt.figure(1, figsize=(1,3)) # plt.subplot(1,3,1) # plt.plot(np.real(ahatc0[0, :, 0]), z[0, :], label='analytical') # plt.plot(np.real(hatc0[0, :, 0]), z[0, :], label='numerical') # plt.xlim(0, np.max(np.maximum(abs(ahatc0[0, :, 0]), abs(hatc0[0, :, 0])))*1.05) # # plt.subplot(1,3,2) # plt.plot(np.abs(ahatc0[0, :, 2]), z[0, :], label='analytical') # # plt.plot(np.abs(ahatc02[0, :, 2]), z[0, :], label='analytical2') # plt.plot(np.abs(hatc0[0, :, 2]), z[0, :], label='numerical') # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05) # plt.legend() # # plt.subplot(1,3,3) # plt.plot(np.imag(ahatc0[0, :, 2]), z[0, :], label='analytical') # # plt.plot(np.imag(ahatc02[0, :, 2]), z[0, :], label='analytical2') # plt.plot(np.imag(hatc0[0, :, 2]), z[0, :], label='numerical') # # plt.xlim(np.min(np.minimum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05, np.max(np.maximum(abs(ahatc0[0, :, 2]), abs(hatc0[0, :, 2])))*1.05) # plt.legend() # st.show() d['hatc0'] = {} d['hatc0']['a'] = {} d['hatc0']['a']['erosion'] = hatc0 d['cMatrix'] = cMatrix return d def first_order(self, d): jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') ftot = 2 * fmax + 1 OMEGA = self.input.v('OMEGA') ################################################################################################################ # Forcing terms ################################################################################################################ if 'sedadv' in self.submodulesToRun and 'sedadv_ax' not in self.submodulesToRun: self.submodulesToRun.append('sedadv_ax') # determine number of submodules nRHS = len(self.submodulesToRun) if 'erosion' in self.submodulesToRun: keysu1 = self.input.getKeysOf('u1') try: keysu1.remove( 'mixing' ) # flow due to 'mixing' should not be included in the erosion term except: pass self.submodulesToRun.remove( 'erosion') # move to the end of the list self.submodulesToRun.append('erosion') nRHS = nRHS - 1 + len(self.input.getKeysOf('u1')) F = np.zeros([jmax + 1, kmax + 1, ftot, nRHS], dtype=complex) Fsurf = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex) Fbed = np.zeros([jmax + 1, 1, ftot, nRHS], dtype=complex) self.input.merge(d) c0 = self.input.v('hatc0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) cx0 = self.input.d('hatc0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), dim='x') cz0 = self.input.d('hatc0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1), dim='z') # 1. Erosion if 'erosion' in self.submodulesToRun: # erosion due to first-order bed shear stress # E = erosion(self.ws, Av, 1, self.input, self.erosion_method) # 24-04-2017 Obsolete # Fbed[:, :, fmax:, self.submodulesToRun.index('erosion')] = -E # 24-04-2017 Obsolete for submod in keysu1: E = erosion(self.ws, 1, self.input, self.erosion_method, submodule=(None, submod), friction=self.frictionpar) Fbed[:, :, fmax:, len(self.submodulesToRun) - 1 + keysu1.index(submod)] = -E # 2. Advection if 'sedadv' in self.submodulesToRun: u0 = self.input.v('u0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) w0 = self.input.v('w0', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) eta = ny.complexAmplitudeProduct( u0, cx0, 2) + ny.complexAmplitudeProduct(w0, cz0, 2) F[:, :, fmax:, self.submodulesToRun.index('sedadv')] = -eta F[:, :, fmax:, self.submodulesToRun. index('sedadv_ax')] = -ny.complexAmplitudeProduct(u0, c0, 2) # 3. First-order fall velocity if 'fallvel' in self.submodulesToRun: # surface and internal terms ws1 = self.input.v('ws1', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) ksi = ny.complexAmplitudeProduct(ws1, c0, 2) ksiz = ny.derivative(ksi, 'z', self.input.slice('grid')) F[:, :, fmax:, self.submodulesToRun.index('fallvel')] = ksiz Fsurf[:, 0, fmax:, self.submodulesToRun.index('fallvel')] = -ksi[:, 0, :] # adjustment to erosion; only if erosion depends on the settling velocity if self.erosion_method == 'Chernetsky': E = erosion(ws1, 0, self.input, self.erosion_method, friction=self.frictionpar) Fbed[:, :, fmax:, self.submodulesToRun.index('fallvel')] = -E # 4. First-order eddy diffusivity if 'mixing' in self.submodulesToRun: # surface, bed and internal terms Kv1 = self.input.v('Kv1', range(0, jmax + 1), range(0, kmax + 1), range(0, fmax + 1)) psi = ny.complexAmplitudeProduct(Kv1, cz0, 2) psiz = ny.derivative(psi, 'z', self.input.slice('grid')) F[:, :, fmax:, self.submodulesToRun.index('mixing')] = psiz Fsurf[:, 0, fmax:, self.submodulesToRun.index('mixing')] = -psi[:, 0, :] Fbed[:, 0, fmax:, self.submodulesToRun.index('mixing')] = -psi[:, -1, :] # adjustment to erosion E = erosion(self.ws, 1, self.input, self.erosion_method, submodule=(None, 'mixing'), friction=self.frictionpar) Fbed[:, :, fmax:, self.submodulesToRun.index('mixing')] = -E # 5. No-flux surface correction if 'noflux' in self.submodulesToRun: zeta0 = self.input.v('zeta0', range(0, jmax + 1), [0], range(0, fmax + 1)) D = np.zeros((jmax + 1, 1, fmax + 1, fmax + 1), dtype=complex) D[:, :, range(0, fmax + 1), range(0, fmax + 1)] = np.arange(0, fmax + 1) * 1j * OMEGA Dc0 = ny.arraydot(D, c0[:, [0], :]) chi = ny.complexAmplitudeProduct(Dc0, zeta0, 2) Fsurf[:, :, fmax:, self.submodulesToRun.index('noflux')] = -chi ################################################################################################################ # Solve equation ################################################################################################################ cmatrix = self.input.v('cMatrix') if cmatrix is not None: c, cMatrix = cFunction(None, cmatrix, F, Fsurf, Fbed, self.input, hasMatrix=True) else: c, cMatrix = cFunction(self.ws, self.Kv, F, Fsurf, Fbed, self.input, hasMatrix=False) c = c.reshape((jmax + 1, kmax + 1, ftot, nRHS)) c = ny.eliminateNegativeFourier(c, 2) ################################################################################################################ # Prepare output ################################################################################################################ d['hatc1'] = {} d['hatc1']['a'] = {} d['hatc1']['ax'] = {} for i, submod in enumerate(self.submodulesToRun): if submod == 'sedadv_ax': d['hatc1']['ax']['sedadv'] = c[:, :, :, i] elif submod == 'erosion': d['hatc1']['a']['erosion'] = {} for j, subsubmod in enumerate(keysu1): d['hatc1']['a']['erosion'][ subsubmod] = c[:, :, :, len(self.submodulesToRun) - 1 + j] else: d['hatc1']['a'][submod] = c[:, :, :, i] if 'sedadv' not in self.submodulesToRun: d['hatc1']['ax'] = 0 return d def second_order_river(self, d): jmax = self.input.v('grid', 'maxIndex', 'x') kmax = self.input.v('grid', 'maxIndex', 'z') fmax = self.input.v('grid', 'maxIndex', 'f') ftot = 2 * fmax + 1 ################################################################################################################ # Forcing terms ################################################################################################################ F = np.zeros([jmax + 1, kmax + 1, ftot, 1], dtype=complex) Fsurf = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex) Fbed = np.zeros([jmax + 1, 1, ftot, 1], dtype=complex) # erosion if self.input.v('u1', 'river') is not None: E = erosion(self.ws, 2, self.input, self.erosion_method, submodule=(None, 'river', None), friction=self.frictionpar) Fbed[:, :, fmax:, 0] = -E ################################################################################################################ # Solve equation ################################################################################################################ cmatrix = self.input.v('cMatrix') if cmatrix is not None: c, cMatrix = cFunction(None, cmatrix, F, Fsurf, Fbed, self.input, hasMatrix=True) else: c, cMatrix = cFunction(self.ws, self.Kv, F, Fsurf, Fbed, self.input, hasMatrix=False) c = c.reshape((jmax + 1, kmax + 1, ftot)) else: c = np.zeros((jmax + 1, kmax + 1, ftot)) d['hatc2'] = {} d['hatc2']['a'] = {} d['hatc2']['a']['erosion'] = {} d['hatc2']['a']['erosion'][ 'river_river'] = ny.eliminateNegativeFourier(c, 2) return d