def loadPETQ(self): """ Lädt Klima und Abfluss aus den entsprechenden Dateien fnQ, fnT, fnP MP111 - Änderungsbedarf: Eigentlich keiner Verständlichkeit: gut Reference: http://fb09-pasig.umwelt.uni-giessen.de/cmf/wiki/CmfTutTestData """ # Fester Modell-Startpunkt begin = datetime.datetime(1979, 1, 1) step = datetime.timedelta(days=1) # Leere Zeitreihen P = cmf.timeseries(begin, step) P.extend(float(Pstr) for Pstr in open(fnP)) Q = cmf.timeseries(begin, step) Q.extend(float(Qstr) for Qstr in open(fnQ)) # Convert m3/s to mm/day Q *= 86400 * 1e3 / (562 * 1e6) T = cmf.timeseries(begin, step) Tmin = cmf.timeseries(begin, step) Tmax = cmf.timeseries(begin, step) # Durchlaufen der Zeilen in der Datei for line in open(fnT): columns = line.split('\t') if len(columns) == 3: Tmax.add(float(columns[0])) Tmin.add(float(columns[1])) T.add(float(columns[2])) return P, T, Tmin, Tmax, Q
def loadPETQ(self): """ Loads climata and discharge data from the corresponding files fnQ, fnT and fnP """ # Fixed model starting point # Change this if you want a warm up period other than a year begin = self.begin - relativedelta(years=1) step = datetime.timedelta(days=1) # empty time series prec = cmf.timeseries(begin, step) prec.extend(float(Pstr.strip("\n")) for Pstr in open(fnP)) discharge = cmf.timeseries(begin, step) discharge.extend(float(Qstr.strip("\n")) for Qstr in open(fnQ)) # Convert m3/s to mm/day area_catchment = 562.41 # Change this when catchment changes!!! discharge *= 86400 * 1e3 / (area_catchment * 1e6) temp = cmf.timeseries(begin, step) temp_min = cmf.timeseries(begin, step) temp_max = cmf.timeseries(begin, step) # Go through all lines in the file for line in open(fnT): columns = line.strip("\n").split('\t') if len(columns) == 3: temp_max.add(float(columns[0])) temp_min.add(float(columns[1])) temp.add(float(columns[2])) return prec, temp, temp_min, temp_max, discharge
def loadPETQ(self): """ Loads climata and discharge data from the corresponding files fnQ, fnT and fnP """ # Fixed model starting point begin = datetime.datetime(1979,1,1) step = datetime.timedelta(days=1) # empty time series P = cmf.timeseries(begin, step) P.extend(float(Pstr) for Pstr in open(fnP)) Q = cmf.timeseries(begin,step) Q.extend(float(Qstr) for Qstr in open(fnQ)) # Convert m3/s to mm/day Q *= 86400 * 1e3 / (2976.41 * 1e6) T = cmf.timeseries(begin,step) Tmin = cmf.timeseries(begin,step) Tmax = cmf.timeseries(begin,step) # Go through all lines in the file for line in open(fnT): columns = line.split('\t') if len(columns) == 3: Tmax.add(float(columns[0])) Tmin.add(float(columns[1])) T.add(float(columns[2])) return P,T,Tmin,Tmax,Q
def runmodel(self, verbose=False): """ Startet das Modell verbose = Wenn verbose = True, dann wird zu jedem Tag etwas ausgegeben MP111 - Änderungsbedarf: Gering, kann so bleiben, kann aber auch um andere Ergebniszeitreihen ergänzt werden. Achtung, falls ihr mehrere Outlets benutzt Verständlichkeit: gut Reference: http://fb09-pasig.umwelt.uni-giessen.de/cmf/wiki/CmfTutFluxes """ # Erzeugt ein neues Lösungsverfahren solver = cmf.ImplicitEuler(self.project, 1e-9) # Verkürzte schreibweise für die Zelle - spart tippen c = self.project[0] # Neue Zeitreihe für Modell-Ergebnisse (res - result) resQ = cmf.timeseries(self.begin, cmf.day) # Starte den solver und rechne in Tagesschritten for t in solver.run(self.project.meteo_stations[0].T.begin, self.end, cmf.day): # Fülle die Ergebnisse if t >= self.begin: resQ.add(self.outlet.waterbalance(t)) # Gebe eine Statusmeldung auf den Bildschirm aus, # dann weiß man wo der solver gerade ist if verbose: print(t, 'Q=%5.3f, P=%5.3f' % (resQ[t], c.get_rainfall(t))) # Gebe die gefüllten Ergebnis-Zeitreihen zurück return resQ
def runmodel(self, verbose=False): """ starts the model if verboose = True --> give something out for every day """ try: # Creates a solver for the differential equations solver = cmf.CVodeIntegrator(self.project, 1e-8) solver.LinearSolver = 0 solver.max_step = cmf.h # New time series for model results (res - result) sim_dis = cmf.timeseries(self.begin, cmf.day) # starts the solver and calculates the daily time steps end = self.end if verbose: print("Start running") for t in solver.run(self.project.meteo_stations[0].T.begin, end, cmf.day): # Fill the results # print(t) if t >= self.begin: sim_dis.add(self.outlet.waterbalance(t)) # Return the filled result time series if verbose: print("Finished running") return sim_dis except RuntimeError: return np.array(self.Q[self.begin:self.end]) * np.nan
def run_model(self): """ Starts the model. Used by spotpy """ print("Start running model") try: # Create a solver for differential equations solver = cmf.CVodeIntegrator(self.project, 1e-9) solver.LinearSolver = 0 self.solver = solver # New time series for model results resQ = cmf.timeseries(self.begin, cmf.day) # starts the solver and calculates the daily time steps end = self.end # datetime.datetime(1979,1,7,9) tstart = time.time() tmax = 300 for t in solver.run(self.project.meteo_stations[0].T.begin, end, cmf.day): # Fill the results (first year is included but not used to # calculate the NS) print(t) if t >= self.begin: resQ.add(self.outlet.waterbalance(t)) if time.time() - tstart > tmax: raise RuntimeError( 'Took more than {:0.1f}min to run'.format(tmax / 60)) print("Finished running model") return resQ # Return an nan - array when a runtime error occurs except RuntimeError as error: print(error) print("FInished running model") return np.array(self.Q[self.begin:self.end + datetime.timedelta(days=1)]) * np.nan
def runmodel(self, verbose=False): """ Runs the model and saves the results """ solver = cmf.CVodeIntegrator(self.project, 1e-9) c = self.project[0] # result timeseries res_q = cmf.timeseries(self.begin, cmf.day) tstart = datetime.datetime.now() # start solver and calculate in daily steps for t in solver.run(self.data.begin, self.end, cmf.day): if t > self.begin: # append results, when spin up time is over res_q.add(self.outlet.waterbalance(t)) # Give the status the screen to let us know what is going on if verbose: print(t, 'P={:5.3f}'.format(c.get_rainfall(t))) if datetime.datetime.now() - tstart > datetime.timedelta(minutes=self.max_run_minutes): print('Cancelled, since it took more than {} minutes'.format(self.max_run_minutes)) for t in cmf.timerange(solver.t, self.end, cmf.day): res_q.add(np.nan) return res_q
def run_model(self): """ Starts the model. Used by spotpy """ try: # Create a solver for differential equations solver = cmf.CVodeIntegrator(self.project, 1e-8) # New time series for model results resQ = cmf.timeseries(self.begin, cmf.day) # starts the solver and calculates the daily time steps end = self.end for t in solver.run(self.project.meteo_stations[0].T.begin, end, cmf.day): # Fill the results (first year is included but not used to # calculate the NS) if t >= self.begin: resQ.add(self.outlet.waterbalance(t)) return resQ # Return an nan - array when a runtime error occurs except RuntimeError: return np.array(self.Q[self.begin:self.end + datetime.timedelta(days=1)]) * np.nan
def create_result_structure(self): """ Creates the container to store the results in. Called, when the run time loop starts """ outflow = cmf.timeseries(self.data.begin, cmf.day) outflow.add(self.outlet(self.data.begin)) return outflow
def create_time_series(analysis_length, time_step=1.0): # Start date is the 1st of January 2017 at 00:00 start = cmf.Time(1, 1, 2017, 0, 0) step = cmf.h * time_step # Create time series return cmf.timeseries(begin=start, step=step, count=analysis_length)
def load_data(discharge_file, temperature_file, precipitation_file, area_catchment): """ Loads climata and discharge data from the corresponding files discharge_file, temperature_file and precipitation_file """ # Fixed model starting point begin = datetime.datetime(1979, 1, 1) step = datetime.timedelta(days=1) # empty time series precipitation = cmf.timeseries(begin, step) if os.name == "nt": cwd = os.getcwd() + os.sep else: cwd = os.getcwd() + os.sep + "acme" + os.sep + "tests" + os.sep print("Current Working Directory = " + cwd) with open(cwd + precipitation_file) as precipitation_file_file: precipitation.extend( float(precipitation_str) for precipitation_str in precipitation_file_file) discharge = cmf.timeseries(begin, step) with open(cwd + discharge_file) as discharge_file_file: discharge.extend( float(discharge_str) for discharge_str in discharge_file_file) # Convert m3/s to mm/day discharge *= 86400 * 1e3 / (area_catchment * 1e6) temperature_avg = cmf.timeseries(begin, step) temperature_min = cmf.timeseries(begin, step) temperature_max = cmf.timeseries(begin, step) # Go through all lines in the file with open(cwd + temperature_file) as temperature_file_file: for line in temperature_file_file: columns = line.split('\t') if len(columns) == 3: temperature_max.add(float(columns[0])) temperature_min.add(float(columns[1])) temperature_avg.add(float(columns[2])) return precipitation, temperature_avg, temperature_min,\ temperature_max, discharge
def run(self, begin=None, end=None): begin = begin or self.rainstation.data.begin end = end or self.rainstation.data.end solver = cmf.CVodeIntegrator(self.project, 1e-9) outlet = cmf.timeseries(begin, cmf.day) outlet.add(self.outlet(begin)) for t in solver.run(begin, end, cmf.day): outlet.add(self.outlet.add) print(t) return outlet
def loadPETQ(self): """ Loads climata and discharge data from the corresponding files fnQ, fnT and fnP """ # Fixed model starting point begin = self.begin - relativedelta(years=1) step = datetime.timedelta(days=1) # empty time series prec = cmf.timeseries(begin, step) prec.extend(float(Pstr.strip("\n")) for Pstr in open(fnP)) discharge = cmf.timeseries(begin, step) discharge.extend(float(Qstr.strip("\n")) for Qstr in open(fnQ)) # Convert m3/s to mm/day area_catchment = 562.41 # 86400 = seconds per day discharge *= 86400 * 1e3 / (area_catchment * 1e6) temp = cmf.timeseries(begin, step) temp_min = cmf.timeseries(begin, step) temp_max = cmf.timeseries(begin, step) # Wind wind = cmf.timeseries(begin, step) wind.extend(float(wind_str.strip("\n")) for wind_str in open(fnWind)) # Sun sun = cmf.timeseries(begin, step) sun.extend(float(sun_str.strip("\n")) for sun_str in open(fnSun)) # relative Humidity rel_hum = cmf.timeseries(begin, step) rel_hum.extend( float(rel_hum_str.strip("\n")) for rel_hum_str in open(fnRelHum)) # Go through all lines in the file for line in open(fnT): columns = line.strip("\n").split('\t') if len(columns) == 3: temp_max.add(float(columns[0])) temp_min.add(float(columns[1])) temp.add(float(columns[2])) return prec, temp, temp_min, temp_max, discharge, wind, sun, \ rel_hum
def runmodel(self, verbose=False): """ starts the model if verboose = True --> give something out for every day """ try: # Creates a solver for the differential equations #solver = cmf.ImplicitEuler(self.project,1e-8) solver = cmf.CVodeIntegrator(self.project, 1e-8) # usually the CVodeIntegrator computes the jakobi matrix only # partially to save computation time. But in models with low spatial # complexity this leads to a longer computational time # therefore the jakob matrix is computed completely to speed things up # this is done by LinearSolver = 0 solver.LinearSolver = 0 c = self.project[0] solver.max_step = cmf.h # New time series for model results (res - result) resQ = cmf.timeseries(self.begin, cmf.day) # starts the solver and calculates the daily time steps end = self.end if self.with_valid_data: end = datetime.datetime(1988, 12, 31) for t in solver.run(self.project.meteo_stations[0].T.begin, end, cmf.day): # Fill the results if t >= self.begin: resQ.add(self.outlet.waterbalance(t)) # Print a status report if verbose: print(t, 'Q=%5.3f, P=%5.3f' % (resQ[t], c.get_rainfall(t))) # Print that one year was calculated, so one knows the model is still working #### comment this out if run on supercomputer to avoid spam ###### #if t % cmf.year == cmf.year - cmf.year: # print("Finished one year") # Return the filled result time series return resQ except RuntimeError: return np.array(self.Q[self.begin:self.end + datetime.timedelta(days=1)]) * np.nan
def runmodel(self, verbose=False): """ Runs the model and saves the results """ solver = cmf.ImplicitEuler(self.project, 1e-9) c = self.project[0] # result timeseries res_q = cmf.timeseries(self.begin, cmf.day) # start solver and calculate in daily steps for t in solver.run(self.data.begin, self.end, cmf.day): # append results res_q.add(self.outlet.waterbalance(t)) # Give the status the screen to let us know what is going on if verbose: print(t, 'P={:5.3f}'.format(c.get_rainfall(t))) return res_q
def load_meteo(project): """Loads the meteorology from a csv file. This is just one example for access your meteo data. Thanks to Python, there is no problem to access most type of datasets, including relational databases, hdf / netcdf files or what ever else. """ # Create a timeseries for rain - timeseries objects in cmf is a kind of extensible array of # numbers, with a begin date, a timestep. begin = datetime(1980, 1, 3) rain = cmf.timeseries(begin=begin, step=timedelta(days=1)) # Create a meteo station meteo = project.meteo_stations.add_station(name='Giessen', position=(0, 0, 0)) # Meteorological timeseries, if you prefer the beginning of the timeseries # read in from file, just go ahead, it is only a bit of Python programming meteo.Tmax = cmf.timeseries(begin=begin, step=timedelta(days=1)) meteo.Tmin = cmf.timeseries(begin=begin, step=timedelta(days=1)) meteo.rHmean = cmf.timeseries(begin=begin, step=timedelta(days=1)) meteo.Windspeed = cmf.timeseries(begin=begin, step=timedelta(days=1)) meteo.Sunshine = cmf.timeseries(begin=begin, step=timedelta(days=1)) # Load climate data from csv file # could be simplified with numpy's csvfile = open('data/climate.csv') csvfile.readline() # Read the headers, and ignore them for line in csvfile: # split the line in to columns using commas columns = line.split(',') # Get the values, but ignore the date, we have begin and steo # of the data file hardcoded # If you don't get this line - it is standard Python, I would recommend the official Python.org tutorial for timeseries, value in zip([ rain, meteo.Tmax, meteo.Tmin, meteo.rHmean, meteo.Windspeed, meteo.Sunshine ], [float(col) for col in columns[1:]]): # Add the value from the file to the timeseries timeseries.add(value) meteo.T = (meteo.Tmax + meteo.Tmin) * 0.5 # Create a rain gauge station project.rainfall_stations.add('Giessen', rain, (0, 0, 0)) # Use the rainfall for each cell in the project project.use_nearest_rainfall() # Use the meteorological station for each cell of the project project.use_nearest_meteo()
def first_simple_model(): import cmf import datetime p = cmf.project() # Create W1 in project p W1 = p.NewStorage(name="W1",x=0,y=0,z=0) # Create W2 in project p without any volume as an initial state W2 = p.NewStorage(name="W2",x=10,y=0,z=0) # Create a linear storage equation from W1 to W2 with a residence time tr of one day q = cmf.kinematic_wave(source=W1,target=W2,residencetime=1.0) # Set the initial state of w1 to 1m³ of water. W1.volume = 1.0 # Create Outlet Out = p.NewOutlet(name="Outlet",x=20,y=0,z=0) qout = cmf.kinematic_wave(source=W2,target=Out,residencetime=2.0) # Create a Neumann Boundary condition connected to W1 In = cmf.NeumannBoundary.create(W1) # Create a timeseries with daily alternating values. In.flux = cmf.timeseries(begin = datetime.datetime(2012,1,1), step = datetime.timedelta(days=1), interpolationmethod = 0) for i in range(10): # Add 0.0 m3/day for even days, and 1.0 m3/day for odd days In.flux.add(i % 2) # Create an integrator for the ODE represented by project p, with an error tolerance of 1e-9 solver = cmf.RKFIntegrator(p,1e-9) # Set the intitial time of the solver solver.t = datetime.datetime(2012,1,1) # Iterate the solver hourly through the time range and return for each time step the volume in W1 and W2 result = [[W1.volume,W2.volume] for t in solver.run(datetime.datetime(2012,1,1),datetime.datetime(2012,1,7),datetime.timedelta(hours=1))] import pylab as plt plt.plot(result) plt.xlabel('hours') plt.ylabel('Volume in $m^3$') plt.legend(('W1','W2')) plt.show()
def runmodel(self): """ Runs the models and saves the results. :return: Simulated discharge """ solver = cmf.CVodeIntegrator(self.project, 1e-9) # Result timeseries res_q = cmf.timeseries(self.begin, cmf.day) try: # Start solver and calculate in daily steps for t in solver.run(self.data.begin, self.end, cmf.day): res_q.add(self.outlet.waterbalance(t)) except RuntimeError: return np.array(self.data.Q[self.data.begin:self.data.end + datetime.timedelta(days=1)]) * np.nan return res_q
def set_design_rain(self, rain_duration=15, rain_amount=27): """ Defines a uniform rainfall input. Parameters ---------- rain_duration : int, optional Rainfall duration [min]. The default is 15. rain_amount : float, optional Rainfall total [mm]. The default is 27. Returns ------- None. """ data = cmf.timeseries(self.tstart, self.dt) while data.end < self.tstart + rain_duration*cmf.min: data.add(rain_amount * cmf.day/(rain_duration* cmf.min)) data.add(0) self.rainfall_stations[0].data = data
def run_model(self, verbose = True): """ Starts the model. Used by spotpy """ cell = self.project[0] try: # Create a solver for differential equations solver = cmf.CVodeIntegrator(self.project, 1e-8) # New time series for model results resQ = cmf.timeseries(self.begin_calibration, cmf.day) # starts the solver and calculates the daily time steps end = self.end_validation for t in solver.run(self.project.meteo_stations[0].T.begin, end, cmf.day): # Fill the results (first year is included but not used to # calculate the NS) if verbose: print(t) print("storages") storages = get_storages_and_fluxes.storages_of_cell( cell.rain_source, cell) fluxes = get_storages_and_fluxes.flux_of_all_nodes_of_cell( cell.rain_source, cell, t) fluxes = \ get_storages_and_fluxes.convert_fluxes_for_fluxogram( fluxes) print(storages) print("Fluxes") print(fluxes) print("\n") if t >= self.begin_calibration: resQ.add(self.outlet.waterbalance(t)) return resQ # Return an nan - array when a runtime error occurs except RuntimeError: print("Runtime Error") return np.array(self.obs_discharge[ self.begin_calibration:self.end_validation + datetime.timedelta(days=1)])*np.nan
def read_timeseries(self, timeseries_name, convert=False): """ Loads in a timeseries and returns it :param timeseries_name: :param convert: Discharge needs to be converted. :return: timeseries """ # Fixed model starting point # Change this if you want a warm up period other than a year begin = self.begin - relativedelta(years=1) step = datetime.timedelta(days=1) timeseries = cmf.timeseries(begin, step) timeseries.extend(float(value.strip("\n")) for value in open( timeseries_name)) if convert: area_catchment = 562.41 timeseries *= 86400 * 1e3 / (area_catchment * 1e6) return timeseries
def run(until=cmf.year, dt=cmf.day): """Runs a the model, and saves the outflow""" # Create a timeseries for the outflow outflow = cmf.timeseries(solver.t, dt) # Create a list to save the layer wetness wetness = [] # Get the end time until = until if until > solver.t else solver.t + until # The run time loop. Iterates over the outer timestep of the model # Internally, the model may take shorter timesteps try: for t in solver.run(solver.t, until, dt): # store the actual groundwater recharge outflow.add(c.layers[-1].flux_to(groundwater, t)) # store the actual wetness wetness.append(c.layers.wetness) # Print, at which time step you are print("{} - {:6.2f}m3/day, {} rhs-eval".format(t, groundwater(t), solver.get_rhsevals())) except RuntimeError as e: print(e) return outflow, wetness
sunshine=0.9, daylength=14, Rs=26) cell.set_weather(summer) # Initial condition (4) layer.volume = 400.0 # ET-Method (3) et_pot_turc = cmf.TurcET(layer, cell.transpiration) # Stress conditions (5, 6) stress = cmf.VolumeStress(300, 100) cell.set_uptakestress(stress) # A solver solver = cmf.HeunIntegrator(p) solver.t = datetime(2018, 5, 1) et_act = cmf.timeseries(solver.t, cmf.day) volume = cmf.timeseries(solver.t, cmf.day) while solver.t < datetime(2018, 10, 1): et_act.add(cell.transpiration(solver.t)) volume.add(layer.volume) solver(cmf.day) # And a plot plot(et_act, c='g') ylabel(r'$ET_{act} \left[\frac{mm}{day}\right]$') twinx() plot(volume, c='b') ylabel('Volume in mm')
# create the storages/outlet c.surfacewater_as_storage() c.add_layer(5.0) outlet = p.NewOutlet("outlet", 10, 0, 0) # add the connections between the storages cmf.kinematic_wave(c.surfacewater, outlet, 1) cmf.kinematic_wave(c.surfacewater, c.layers[0], 1) cmf.kinematic_wave(c.layers[0], outlet, 3) # create artificial rain data begin = datetime.datetime(1979, 1, 1) end = begin + 15 * datetime.timedelta(days=1) step = datetime.timedelta(days=1) P = cmf.timeseries(begin, step) P.extend(prec for prec in np.random.randint(0, high=30, size=15)) # add a rainstation rainstation = p.rainfall_stations.add("Rain", P, (0, 0, 0)) p.use_nearest_rainfall() # create a solver solver = cmf.CVodeIntegrator(p, 1e-8) # create lists to store the results of the fluxes and storages timeseries_fluxes = [] timeseries_storages = [] # let the solver run for our timeperiod for t in solver.run(begin, end, cmf.day):
import cmf import datetime p = cmf.project() W1=p.NewStorage(name="W1",x=0,y=0,z=0) W2=p.NewStorage(name="W2",x=10,y=0,z=0) q = cmf.kinematic_wave(source=W1,target=W2,residencetime=5.0) W1.volume=1.0 Out = p.NewOutlet(name="Outlet",x=20,y=0,z=0) q2 = cmf.kinematic_wave(source=W1,target=Out,residencetime=1.0) qout = cmf.kinematic_wave(source=W2,target=Out,residencetime=.5) # Create a Neumann Boundary condition connected to W1 In = p.NewNeumannBoundary('In', W1) # Create a timeseries with daily alternating values. In.flux = cmf.timeseries(begin = datetime.datetime(2012,1,1), step = datetime.timedelta(days=1), interpolationmethod = 0) for i in range(1000): # Add 0.0 m3/day for even days, and 1.0 m3/day for odd days In.flux.add(i % 2) # Create the solver solver = cmf.ImplicitEuler(p,1e-9) import datetime # Iterate the solver hourly through the time range and return for each time step the volume in W1 and W2 result = [[W1.volume,W2.volume] for t in solver.run(datetime.datetime(2012,1,1),datetime.datetime(2012,2,1),datetime.timedelta(hours=1))] import pylab as plt plt.plot(result) plt.xlabel('hours') plt.ylabel('Volume in $m^3$') plt.legend(('W1','W2')) plt.show()
def test_timeseries_basic(self): ts = cmf.timeseries(cmf.Time(), cmf.h) self.assertEqual(len(ts), 0) ts.add(1.0) self.assertEqual(len(ts), 1) self.assertEqual(ts.end, cmf.h)
def run(until,dt=cmf.day): outflow = cmf.timeseries(solver.t,dt) for t in solver.run(solver.t,solver.t+until,dt): outflow.add(outlet(t)) print("%20s - %6.1f l/s" % (t,outlet(t)*1e3)) return outflow
def create_result_structure(self): outflow = cmf.timeseries(self.data.begin, cmf.day) outflow.add(self.outlet(self.data.begin)) return outflow
fig,ax = plt.subplots() img = ax.imshow(getdepth(),cmap=plt.cm.Blues,aspect='equal', vmin=0.0,vmax=0.01,origin='bottom',interpolation='nearest', extent=(-length/2,(size[0]-.5)*length,-length/2,length*(size[1]-.5))) fluxdir = cmf.cell_flux_directions(p,solver.t) pos = cmf.cell_positions(p.cells) a=np.array quiver = ax.quiver(pos.X,pos.Y, fluxdir.X,fluxdir.Y, scale=1000,zorder=10, pivot='middle') title = ax.text(length,(size[1]-2)*length,solver.t, size=16) ax.set_xlim(-length,length*size[0]) ax.set_ylim(-length,length*size[1]) dt=cmf.sec*10 #%% qout = cmf.timeseries(solver.t,dt) def run(data): solver(solver.t+dt) t = solver.t if t>cmf.h: setrain(0.0) img.set_array(getdepth()) fluxdir = cmf.cell_flux_directions(p,t) quiver.set_UVC(fluxdir.X,fluxdir.Y) title.set_text('%s/%s %g mm' % (t,solver.dt, np.mean(c.surfacewater.depth)* 1000)) qout.add(outlet(t)) return img,quiver,title #%% ani = animation.FuncAnimation(fig,run,frames=int(2*cmf.h/dt),blit=False,interval=20,repeat=False) plt.show()