def run(self): """Perform a full simulation including infiltration, surface flow etc., recording of data and mass_balance calculation """ # dict of next time-step (datetime object) self.next_ts = { 'end': self.end_time, 'rec': self.start_time + self.record_step } for k in ['hyd', 'surf', 'drain']: self.next_ts[k] = self.start_time # First time-step is forced self.nextstep = self.sim_time + self.dt self.surf_sim.dt = self.dt self.rast_domain.update_input_arrays(self.sim_time) self.surf_sim.solve_q() # case if no drainage simulation if not self.drainage: self.next_ts['drain'] = self.end_time self.rast_domain.isnew['n_drain'] = False else: self.drainage.set_linkable() self.rast_domain.isnew['n_drain'] = True self.drainage.solve_dt() # record initial state self.report.step(self.sim_time) self.rast_domain.reset_stats(self.sim_time) sim_start_time = datetime.now() msgr.verbose(u"Starting time-stepping...") while self.sim_time < self.end_time: # display advance of simulation msgr.percent(self.start_time, self.end_time, self.sim_time, sim_start_time) # recalculate the flow direction if DEM changed if self.rast_domain.isnew['z']: self.surf_sim.update_flow_dir() # step models self.step() # update simulation time self.sim_time += self.dt # update input arrays self.rast_domain.update_input_arrays(self.sim_time) # write final report self.report.end(self.sim_time) return self
def run(self): """Perform a full simulation including infiltration, surface flow etc., recording of data and mass_balance calculation """ sim_start_time = datetime.now() msgr.verbose(u"Starting time-stepping...") while self.sim_time < self.end_time: # display advance of simulation msgr.percent(self.start_time, self.end_time, self.sim_time, sim_start_time) # step models self.step() return self
def update_input_arrays(self, sim_time): """Get new array using TimedArray First update the DEM and mask if needed Replace the NULL values (mask) """ # make sure DEM is treated first if not self.tarr['z'].is_valid(sim_time): self.arr['z'][:] = self.tarr['z'].get(sim_time) self.isnew['z'] = True # note: must run update_flow_dir() in SuperficialSimulation self.update_mask(self.arr['z']) self.mask_array(self.arr['z'], np.finfo(self.dtype).max) else: self.isnew['z'] = False # loop through the arrays for k, ta in self.tarr.iteritems(): if not ta.is_valid(sim_time): # z is done before if k == 'z': continue # calculate statistics before updating array if k in ['in_q', 'rain']: self.populate_stat_array(k, sim_time) # update array msgr.verbose(u"{}: update input array <{}>".format( sim_time, k)) self.arr[k][:] = ta.get(sim_time) self.isnew[k] = True if k == 'n': fill_value = 1 else: fill_value = 0 # mask arrays self.mask_array(self.arr[k], fill_value) else: self.isnew[k] = False # calculate water volume at the beginning of the simulation if self.isnew['h']: self.start_volume = self.asum('h') return self
def initialize(self): """Set-up the simulation. """ # instantiate simulation objects gis_kwargs = dict(start_time=self.start_time, end_time=self.end_time, dtype=self.dtype, mkeys=self.in_map_names.keys(), region_id=self.region_id, raster_mask_id=self.raster_mask_id) self.igis = gis.Igis(**gis_kwargs) msgr.verbose(u"Setting up models...") self.__set_models(self.igis) msgr.verbose(u"Models set up") msgr.verbose(u"Reading maps information from GIS...") self.igis.read(self.in_map_names) # dict of next time-step (datetime object) self.next_ts = { 'end': self.end_time, 'rec': self.start_time + self.record_step } for k in ['hyd', 'surf', 'drain']: self.next_ts[k] = self.start_time # case if no drainage simulation if not self.drainage: self.next_ts['drain'] = self.end_time # First time-step is forced self.nextstep = self.sim_time + self.dt # record initial state self.rast_domain.update_input_arrays(self.sim_time) self.report.step(self.sim_time) self.rast_domain.reset_stats(self.sim_time) return self
def __init__(self, sim_times, input_maps, output_maps, sim_param, drainage_params, dtype=np.float32, dtmin=timedelta(seconds=0.01), stats_file=None): # read time parameters self.start_time = sim_times.start self.end_time = sim_times.end self.duration = sim_times.duration self.record_step = sim_times.record_step self.temporal_type = sim_times.temporal_type # set simulation time to start_time self.sim_time = self.start_time # First time-step is forced self.dt = dtmin # Global time-step self.dtinf = sim_param['dtinf'] # dictionaries of map names self.in_map_names = input_maps self.out_map_names = output_maps # data type of arrays self.dtype = dtype # simulation parameters self.sim_param = sim_param self.inf_model = self.sim_param['inf_model'] # drainage parameters self.drainage_params = drainage_params # statistic file name self.stats_file = stats_file # instantiate a Igis object self.gis = gis.Igis(start_time=self.start_time, end_time=self.end_time, dtype=self.dtype, mkeys=self.in_map_names.keys()) msgr.verbose(u"Reading maps information from GIS...") self.gis.read(self.in_map_names) # instantiate simulation objects msgr.verbose(u"Setting up models...") self.__set_models() msgr.verbose(u"Models set up")
def step(self): """Step each of the models if needed """ # HYDROLOGY MODEL - compute rainfall rates, losses rates, infiltration rates# #------------------------------------------------------------------------------ if self.sim_time == self.next_ts['hyd']: self.hydrology.solve_dt() # calculate when will happen the next time-step self.next_ts['hyd'] += self.hydrology.dt self.hydrology.step() # update stat array self.rast_domain.populate_stat_array('inf', self.sim_time) self.rast_domain.populate_stat_array('capped_losses', self.sim_time) #SWMM MODEL - Apply linkage flow to SWMM Model and STEP SWMM Model #------------------------------------------------------------------------------ if self.sim_time == self.next_ts['drain'] and self.drainage: self.drainage.apply_drainage_flow() self.drainage.step() self.drainage.solve_dt() self.next_ts['drain'] += self.drainage.dt #compute next 1D time # SURFACE FLOW SIM #------------------------------------------------------------------------------ #calculate fluxes at cell interfaces self.surf_sim.solve_q() # calculate drainage flows and apply it to 2D Model at each 2D timestep if self.drainage: self.drainage.drainage_flow( self.dt.total_seconds()) #compute drainage flow self.rast_domain.update_ext_array() self.rast_domain.populate_stat_array('n_drain', self.sim_time) else: self.rast_domain.update_ext_array() self.surf_sim.apply_boundary_conditions() try: self.surf_sim.update_h() # in case of NaN/NULL cells, raisea NullError self.surf_sim.arr_err = np.isnan(self.rast_domain.get('h')) if np.any(self.surf_sim.arr_err): raise NullError except NullError: self.report.write_error_to_gis(self.surf_sim.arr_err) msgr.fatal(u"{}: Null value detected in simulation, " u"terminating".format(self.sim_time)) self.surf_sim.swap_flow_arrays() # calculate when should happen the next surface time-step self.surf_sim.solve_dt() # increment time when should happen next timestep if self.drainage: self.next_ts['surf'] += min( self.surf_sim.dt, self.drainage.dt2d ) #self.drainage.dt2d is the courant condition based on maximum node head. else: self.next_ts['surf'] += self.surf_sim.dt #REPORTING #------------------------------------------------------------------------------ # send current time-step duration to mass balance object if self.massbal: self.massbal.add_value('tstep', self.dt.total_seconds()) # Reporting # if self.sim_time == self.next_ts['rec']: msgr.verbose(u"{}: Writing output maps...".format(self.sim_time)) self.report.step(self.sim_time) self.next_ts['rec'] += self.record_step # reset statistic maps self.rast_domain.reset_stats(self.sim_time) #GLOBAL STEP CALCULATION #------------------------------------------------------------------------------ # find next step self.nextstep = min(self.next_ts.values()) # force the surface time-step to the lowest time-step self.next_ts['surf'] = self.nextstep self.dt = self.nextstep - self.sim_time # force time-step to be the general time-step self.surf_sim.dt = self.dt return self
def step(self): """Step each of the models if needed """ # hydrology # if self.sim_time == self.next_ts['hyd']: self.hydrology.solve_dt() # calculate when will happen the next time-step self.next_ts['hyd'] += self.hydrology.dt self.hydrology.step() # update stat array self.rast_domain.populate_stat_array('inf', self.sim_time) self.rast_domain.populate_stat_array('capped_losses', self.sim_time) # drainage # if self.sim_time == self.next_ts['drain'] and self.drainage: self.drainage.solve_dt() # calculate when will happen the next time-step self.next_ts['drain'] += self.drainage.dt self.drainage.step() self.drainage.apply_linkage(self.dt.total_seconds()) self.rast_domain.isnew['n_drain'] = True # update stat array self.rast_domain.populate_stat_array('n_drain', self.sim_time) else: self.rast_domain.isnew['n_drain'] = False # surface flow # # update arrays of infiltration, rainfall etc. self.rast_domain.update_ext_array() # force time-step to be the general time-step self.surf_sim.dt = self.dt # surf_sim.step() raise NullError in case of NaN/NULL cell # if this happen, stop simulation and # output a map showing the errors try: self.surf_sim.step() except NullError: self.report.write_error_to_gis(self.surf_sim.arr_err) msgr.fatal(u"{}: Null value detected in simulation, " u"terminating".format(self.sim_time)) # calculate when should happen the next surface time-step self.surf_sim.solve_dt() self.next_ts['surf'] += self.surf_sim.dt # send current time-step duration to mass balance object if self.massbal: self.massbal.add_value('tstep', self.dt.total_seconds()) # Reporting # if self.sim_time >= self.next_ts['rec']: msgr.verbose(u"{}: Writing output maps...".format(self.sim_time)) self.report.step(self.sim_time) self.next_ts['rec'] += self.record_step # reset statistic maps self.rast_domain.reset_stats(self.sim_time) # find next step self.nextstep = min(self.next_ts.values()) # force the surface time-step to the lowest time-step self.next_ts['surf'] = self.nextstep self.dt = self.nextstep - self.sim_time return self
def display_sim_param(self): """Display simulation parameters if verbose """ inter_txt = u"#" * 50 txt_template = u"{:<24s} {}" msgr.verbose(u"{}".format(inter_txt)) msgr.verbose(u"Input maps:") for k, v in self.input_map_names.items(): msgr.verbose(txt_template.format(k, v)) msgr.verbose(u"{}".format(inter_txt)) msgr.verbose(u"Output maps:") for k, v in self.output_map_names.items(): msgr.verbose(txt_template.format(k, v)) msgr.verbose(u"{}".format(inter_txt)) msgr.verbose(u"Simulation parameters:") for k, v in self.sim_param.items(): msgr.verbose(txt_template.format(k, v)) # simulation times msgr.verbose(u"{}".format(inter_txt)) msgr.verbose(u"Simulation times:") txt_start_time = self.sim_times.start.isoformat(" ").split(".")[0] txt_end_time = self.sim_times.end.isoformat(" ").split(".")[0] msgr.verbose(txt_template.format('start', txt_start_time)) msgr.verbose(txt_template.format('end', txt_end_time)) msgr.verbose(txt_template.format('duration', self.sim_times.duration)) msgr.verbose( txt_template.format('record_step', self.sim_times.record_step)) msgr.verbose(u"{}".format(inter_txt))