def test_lookup_bmp_infiltration(self): """ Do some spot-checks on the data from Table B. """ self.assertEqual(lookup_bmp_infiltration('d', 'green_roof'), 1.6) self.assertEqual(lookup_bmp_infiltration('c', 'porous_paving'), 1.73) self.assertEqual(lookup_bmp_infiltration('b', 'rain_garden'), 0.6) self.assertEqual(lookup_bmp_infiltration('a', 'infiltration_trench'), 2.4) # noqa
def simulate_cell_day(precip, evaptrans, cell, cell_count): """ Simulate a bunch of cells of the same type during a one-day event. `precip` is the amount of precipitation in inches. `evaptrans` is evapotranspiration. `cell` is a string which contains a soil type and land use separated by a colon. `cell_count` is the number of cells to simulate. The return value is a dictionary of runoff, evapotranspiration, and infiltration as volumes of water. """ soil_type, land_use, bmp = cell.lower().split(':') # If there is no precipitation, then there is no runoff or # infiltration. There is evapotranspiration, however (is # understood that over a period of time, this can lead to the sum # of the three values exceeding the total precipitation). if precip == 0.0: return { 'runoff-vol': 0.0, 'et-vol': cell_count * evaptrans, 'inf-vol': 0.0 } # Deal with the Best Management Practices (BMPs). For most BMPs, # the infiltration is read from the table and the runoff is what # is left over after infiltration and evapotranspiration. Rain # gardens are treated differently. if bmp and is_bmp(bmp) and bmp != 'rain_garden': inf = lookup_bmp_infiltration(soil_type, bmp) # infiltration runoff = precip - (evaptrans + inf) # runoff return { 'runoff-vol': cell_count * runoff, 'et-vol': cell_count * evaptrans, 'inf-vol': cell_count * inf } elif bmp and bmp == 'rain_garden': # Here, return a mixture of 20% ideal rain garden and 80% high # intensity residential. inf = lookup_bmp_infiltration(soil_type, bmp) runoff = precip - (evaptrans + inf) hi_res_cell = soil_type + ':hi_residential:' hi_res = simulate_cell_day(precip, evaptrans, hi_res_cell, 1) hir_run = hi_res['runoff-vol'] hir_et = hi_res['et-vol'] hir_inf = hi_res['inf-vol'] return { 'runoff-vol': cell_count * (0.2 * runoff + 0.8 * hir_run), 'et-vol': cell_count * (0.2 * evaptrans + 0.8 * hir_et), 'inf-vol': cell_count * (0.2 * inf + 0.8 * hir_inf) } # At this point, if the `bmp` string has non-zero length, it is # equal to either 'no_till' or 'cluster_housing'. land_use = bmp or land_use # When the land use is a built-type and the level of precipitation # is two inches or less, use the Pitt Small Storm Hydrology Model. # When the land use is a built-type but the level of precipitation # is higher, the runoff is the larger of that predicted by the # Pitt model and NRCS model. Otherwise, return the NRCS amount. if is_built_type(land_use) and precip <= 2.0: runoff = runoff_pitt(precip, land_use) elif is_built_type(land_use): pitt_runoff = runoff_pitt(2.0, land_use) nrcs_runoff = runoff_nrcs(precip, evaptrans, soil_type, land_use) runoff = max(pitt_runoff, nrcs_runoff) else: runoff = runoff_nrcs(precip, evaptrans, soil_type, land_use) inf = precip - (evaptrans + runoff) return { 'runoff-vol': cell_count * runoff, 'et-vol': cell_count * evaptrans, 'inf-vol': cell_count * max(inf, 0.0), }