swextraction = [water_limit['sw_unregulated']/365.0 for i in range(365)], gwextraction = [water_limit['gw']/365.0 for i in range(365)]) hydro_sim, hydro_tdat, hydro_mod = run_hydrology(*state) # get state so model can be stopped and started state = get_state(hydro_sim, hydro_tdat, hydro_mod, 365) # extract data from hydrological model output dates, flow, gwlevel, gwstorage, gwfitparams = get_outputs(hydro_sim, hydro_tdat, hydro_mod) # run LP farmer decision model # ------------------------------------------- total_water_licence = water_licence['sw_unregulated']+water_licence['gw'] farm_profit = maximum_profit(all_crops, farm_area, total_water_licence) all_years_gwstorage[y*365:(y+1)*365] = gwstorage all_years_gwlevel[y*365:(y+1)*365] = gwlevel all_years_flow[y*365:(y+1)*365] = flow all_years_profit[y*365:(y+1)*365] = farm_profit # subtract water used by farmer from flows # TODO # no longer necessary - extractions included in set_climate_data above # gwstorage = gwstorage - water_limit['gw']/365.0 # interpolated_gwlevel = map(lambda x: x*gwfitparams[0] + gwfitparams[1], gwstorage) # flow = flow - water_limit['sw_unregulated']/365.0 # run ecological model # water_index = calculate_water_index(interpolated_gwlevel, flow, dates)
def model(dates, rainfall, temperature, crops, WUE, farm_area, AWD): # write rainfall and temperature to csv files # ------------------------------------------- # write to rainfall, temparture, extractions for given time range max_i = 3000 extractions = [0 for i in dates] set_climate_data(dates=dates[:max_i], rainfall=rainfall[:max_i], temperature=temperature[:max_i], swextraction=extractions[:max_i], gwextraction=extractions[:max_i]) # run hydrological model # ------------------------------------------- # hydro_sim, hydro_tdat, hydro_mod = run_hydrology() # RunIhacresGw.R takes about 17 seconds hydro_sim, hydro_tdat, hydro_mod = run_hydrology( 0, 422.7155 / 2, # d/2 [0, 0], # must be of length NC 0, 0) gw_i = 3 gwlevel = -np.array( hydro_sim.rx2('Glevel').rx2('gw_shallow'))[:, gw_i] # 3rd col varies most flow = np.array(hydro_sim.rx2('Q')).squeeze() gwstorage = np.array(hydro_sim.rx2('G')).squeeze()[:, 0] dates = list(hydro_tdat.rx2('dates')) gwfitparams = -np.array( hydro_mod.rx2('param').rx2('gwFitParam').rx2('gw_shallow'))[gw_i, :] # interpolated_gwlevel = map(lambda x: x*gwfitparams[0] + gwfitparams[1], gwstorage) # assert np.alltrue(interpolated_gwlevel == gwlevel) print 'gwstorage', gwstorage print 'gwlevel', gwlevel print 'flow', flow # print 'dates',dates # TODO # use gwlevel and flow from above to adjust AWD then update extractions, rerun # run a year at a time!! # apply AWD to get water_licence # ------------------------------------------- # Extraction limit 2,200 ML/yr \cite{Upper_and_Lower_Namoi_Groundwater_Sources} # Maules Creek Entitlement (ML/year) 1,413 \cite{Namoi_Unregulated_and_Alluvial} water_limit = {"sw_unregulated": 1413, "gw": 2200} water_licence = {} for licence_type in water_limit: water_licence[ licence_type] = water_limit[licence_type] * AWD[licence_type] # run LP farmer decision model # ------------------------------------------- total_water_licence = water_licence['sw_unregulated'] + water_licence['gw'] farm_profit = maximum_profit(crops, farm_area, total_water_licence) # subtract water used by farmer from flows # ------------------------------------------- # TODO # run a year at a time gwstorage = gwstorage - water_limit['gw'] / 365.0 interpolated_gwlevel = map(lambda x: x * gwfitparams[0] + gwfitparams[1], gwstorage) flow = flow - water_limit['sw_unregulated'] / 365.0 import matplotlib.pyplot as plt plt.plot(gwlevel) plt.plot(interpolated_gwlevel) plt.show() # run ecological model # ------------------------------------------- water_index = calculate_water_index(interpolated_gwlevel, flow, dates) return farm_profit, water_index
def test_annual(): all_crops = load_crops() # Water allocations for the Namoi Valley # Available Water Determination Order for Various NSW Groundwater Sources (No. 1) 2014 # http://www.water.nsw.gov.au/Water-management/Water-availability/Water-allocations/Available-water-determinations # TODO # this should ideally be a function of gwlevel and flow? AWD = {"sw unregulated": 1, "gw": 1} # apply AWD to get water_licence # ------------------------------------------- # Extraction limit 2,200 ML/yr \cite{Upper_and_Lower_Namoi_Groundwater_Sources} # Maules Creek Entitlement (ML/year) 1,413 \cite{Namoi_Unregulated_and_Alluvial} water_limit = {"sw unregulated": 1413, "gw": 2200} # TODO water_licence = {} for licence_type in water_limit: water_licence[ licence_type] = water_limit[licence_type] * AWD[licence_type] # Comparative Irrigation Costs 2012 - NSW DPI (Peter Smith) # TODO # does nothing WUE = { "flood irrigation": 0.65, "spray irrigation": 0.8, "drip irrigation": 0.85 } # \cite{powell2011representative} farm_area = { "flood irrigation": 782, "spray irrigation": 0, "drip irrigation": 0, "dryland": 180 } climate_dates, rainfall, PET = read_climate_projections( 'climate/419051.csv', scenario=1) # TODO # get climate projections temp not PET temperature = PET * 5 # burn in hydrological model # ------------------------------------------- burn_in = 365 * 2 # write rainfall and temperature, extractions to csv files extractions = [0 for i in climate_dates] set_climate_data(dates=climate_dates[:365 * 5], rainfall=rainfall[:365 * 5], PET=temperature[:365 * 5], swextraction=extractions[:365 * 5], gwextraction=extractions[:365 * 5]) hydro_sim, hydro_tdat, hydro_mod = run_hydrology( 0, 422.7155 / 2, # d/2 [0, 0], # must be of length NC 0, 0, "PET") state = get_state(hydro_sim, hydro_tdat, hydro_mod, burn_in) burn_flow = np.array(hydro_sim.rx2('Q')).squeeze() burn_gwstorage = np.array(hydro_sim.rx2('G')).squeeze()[:, 0] # run for each year # ------------------------------------------- years = 3 assert len(climate_dates) > burn_in + 365 * years all_years_flow = np.empty((365 * years)) all_years_gwstorage = np.empty((365 * years)) for y in range(years): extractions = [0 for i in climate_dates] # write rainfall and temperature, extractions to csv files start_date = burn_in + y * 365 end_date = burn_in + (y + 1) * 365 set_climate_data(dates=climate_dates[start_date:end_date], rainfall=rainfall[start_date:end_date], PET=temperature[start_date:end_date], swextraction=extractions[start_date:end_date], gwextraction=extractions[start_date:end_date]) hydro_sim, hydro_tdat, hydro_mod = run_hydrology( state[0], state[1], state[2], state[3], state[4], "PET") # hydro_sim, hydro_tdat, hydro_mod = run_hydrology(*state) state = get_state(hydro_sim, hydro_tdat, hydro_mod, 365) # extract data from hydrological model output gw_i = 3 gwlevel = -np.array(hydro_sim.rx2('Glevel').rx2( 'gw_shallow'))[:, gw_i] # 3rd col varies most flow = np.array(hydro_sim.rx2('Q')).squeeze() gwstorage = np.array(hydro_sim.rx2('G')).squeeze()[:, 0] dates = list(hydro_tdat.rx2('dates')) gwfitparams = -np.array( hydro_mod.rx2('param').rx2('gwFitParam').rx2('gw_shallow'))[ gw_i, :] interpolated_gwlevel = map( lambda x: x * gwfitparams[0] + gwfitparams[1], gwstorage) assert np.alltrue(interpolated_gwlevel == gwlevel) all_years_gwstorage[y * 365:(y + 1) * 365] = gwstorage all_years_flow[y * 365:(y + 1) * 365] = flow assert np.alltrue(dates == climate_dates[start_date:end_date]) # run LP farmer decision model # ------------------------------------------- total_water_licence = water_licence['sw unregulated'] + water_licence[ 'gw'] farm_profit = maximum_profit(all_crops, farm_area, total_water_licence) # subtract water used by farmer from flows # ------------------------------------------- # TODO # run a year at a time gwstorage = gwstorage - water_limit['gw'] / 365.0 interpolated_gwlevel = map( lambda x: x * gwfitparams[0] + gwfitparams[1], gwstorage) flow = flow - water_limit['sw unregulated'] / 365.0 # run ecological model # ------------------------------------------- water_index = calculate_water_index(interpolated_gwlevel, flow, dates) # print "PROFIT", farm_profit # print "WATER", np.min(water_index), np.mean(water_index), np.max(water_index) assert np.allclose(burn_flow[burn_in:], all_years_flow) import matplotlib.pyplot as plt # plt.plot(all_years_flow, label='all years flow', ls='--') # plt.plot(burn_flow[burn_in:], label='burn flow') plt.plot(burn_flow[burn_in:] - all_years_flow) plt.legend() plt.show() # plt.plot(all_years_gwstorage, label='all years gwstorage', ls='--') # plt.plot(burn_gwstorage[burn_in:], label='burn gwstorage') plt.plot(burn_gwstorage[burn_in:] - all_years_gwstorage) plt.legend() plt.show()
def run_integrated(years, WUE, water_limit, AWD, adoption, crop_price_choice, climate_dates, rainfall, PET, climate_type, eco_min_separation, eco_min_duration, eco_ctf, eco_weights, plot, timing_col, duration_col, dry_col, gwlevel_col, sw_uncertainty, gw_uncertainty, crop_trend, cj_options): # TODO add prices as parameter once we have min, max # crop prices, yields, costs all determined here crops = load_chosen_crops( WUE, crop_price_choice ) #load chosen crops.csv data, then manipulate water use (ML/ha) based on WUE scenarios (e.g. min flood wue is 50%) #adoption['flood'] = % area under flood irrigation (0~100). Used in optimisation, farm_area = max farm area (km^2) under flood and spray irrigation. farm_area = { "flood": 782. * 7. * adoption["flood"] / 100., # hectares #/100 to convert adoption rate from 0~100 to 0~1. "spray": 782. * 7. * adoption["spray"] / 100., "drip": 782. * 7. * adoption["drip"] / 100., "dryland": 180. * 7. / 100., } #calculate daily extractions, same every day, same for all climates, depends on annual limits only. #years for the selected climate period, and the daily indices. year_indices, year_list = get_year_indices(climate_dates) #model can't run if the years parameter is longer than the # of years for selected climate period. assert years <= len(year_indices) #create number of very small values. n = in the climate period, find the # of dates in the first 12 (=years parameter) years. eg if the first year starts 31 dec, then it's practically 11 years+1 day data all_years_flow = np.empty((year_indices[years - 1]["end"])) all_years_gwstorage = np.empty((year_indices[years - 1]["end"])) all_years_gwlevel = np.empty((year_indices[years - 1]["end"])) all_years_profit = np.empty((year_indices[years - 1]["end"])) # hydrological timeseries model initial state state = ( 0, #initial gw storage 422.7155 / 2, # d/2 #initial C [0, 0], # must be of length NC # initial Nash 0, #initial Qq 0) #initial Qs # run LP farmer decision model previous_rainfall = mean_annual_rainfall annual_profit = [] gw_alloc_avg_years = 5 max_gw_over_alloc = AWD['gw'] * 0.3 good_sw_condition = AWD['sw unregulated'] * 0.9 past_gw_allocs = [] for year in range(years): # adjust crop prices so they stay the same, trend up, or trend down for i in range(len(crops)): if crop_trend == "flat": crops[i]['price ($/unit)'] = crops[i]['price med ($/unit)'] elif crop_trend == "down": crops[i]['price ($/unit)'] = crops[i][ 'price med ($/unit)'] - 0.2 * crops[i][ 'price med ($/unit)'] * (year + 1.0) / years elif crop_trend == "up": crops[i]['price ($/unit)'] = crops[i][ 'price med ($/unit)'] + 0.2 * crops[i][ 'price med ($/unit)'] * (year + 1.0) / years AWD_surface = AWD_policy(previous_rainfall, AWD['sw unregulated']) sw_deficit = max(0., AWD['sw unregulated'] - AWD_surface) * water_limit['sw unregulated'] if cj_options == "byrain": # Option 0: groundwater allocation linearly related to rainfall AWD_gw = AWD_policy(previous_rainfall, AWD['gw']) elif cj_options == "constant1": # Option 1: current option where gw_AWD is constantly = 100% AWD_gw = AWD['gw'] elif cj_options == "forcefix": # ---- Option forcefix ---- #: Allow over extraction of gw over x years by letting GW make up the difference # Fixed forcing at year n #If less than gw_alloc_avg_years, allow overextraction of gw and add to record if len(past_gw_allocs) < (gw_alloc_avg_years - 1): AWD_gw = AWD['gw'] + min(max_gw_over_alloc, sw_deficit / water_limit['gw']) past_gw_allocs.append(AWD_gw) else: #at year n, force fix AWD_gw = max(0, (len(past_gw_allocs) + 1) * AWD['gw'] - sum(past_gw_allocs)) past_gw_allocs = [] #End if elif cj_options == "oppfix": #---- Option oppfix ---- #Opportunistic forcing based on surface allocation if AWD_surface >= good_sw_condition: AWD_gw = max(0, (len(past_gw_allocs) + 1) * AWD['gw'] - sum(past_gw_allocs)) past_gw_allocs = [] else: #Otherwise, allow overextraction of gw and add to record AWD_gw = AWD['gw'] + min(max_gw_over_alloc, sw_deficit / water_limit['gw']) past_gw_allocs.append(AWD_gw) #End if elif cj_options == "oppandforcefix": # ---- Option oppandforcefix ---- # Fixed forcing when surface allocation allows it, otherwise opportunistic forcing if len(past_gw_allocs) < (gw_alloc_avg_years - 1): #Fix gw if surface water conditions is good if AWD_surface >= good_sw_condition: AWD_gw = max(0, (len(past_gw_allocs) + 1) * AWD['gw'] - sum(past_gw_allocs) ) #Correct gw allocation to maintain average past_gw_allocs.append(AWD_gw) # print "Good SW conditions" # print past_gw_allocs past_gw_allocs = [] else: #Overallocate AWD_gw = AWD['gw'] + min(max_gw_over_alloc, sw_deficit / water_limit['gw']) past_gw_allocs.append(AWD_gw) # print "Poor or normal SW conditions" # print past_gw_allocs else: # print "Forced Fix" #It is year n, force fix gw AWD_gw = max(0, gw_alloc_avg_years - sum(past_gw_allocs)) past_gw_allocs.append(AWD_gw) # print past_gw_allocs past_gw_allocs = [] #End if # print "Year: ", year # print "Surface Alloc: ", AWD_surface # print "GW Alloc: ", AWD_gw, cj_options # print '-----' sw_extractions, gw_extractions = generate_extractions( climate_dates, AWD_surface * water_limit['sw unregulated'] / 365, AWD_gw * water_limit['gw'] / 365) farm_profit = maximum_profit( crops, farm_area, { 'surface': AWD_surface * water_limit['sw unregulated'], 'ground': AWD_gw * water_limit['gw'] }) state, flow, gwlevel, gwstorage = run_hydrology_by_year( year, state, climate_dates, rainfall, PET, sw_extractions, gw_extractions, climate_type) indices = year_indices[year] all_years_gwstorage[ indices["start"]:indices["end"]] = gwstorage #no use all_years_gwlevel[ indices["start"]:indices["end"]] = gwlevel * gw_uncertainty all_years_flow[indices["start"]:indices["end"]] = flow * sw_uncertainty all_years_profit[indices["start"]:indices[ "end"]] = farm_profit #annual value repeated for each day # previous_rainfall = np.sum(rainfall[indices["start"]:indices["end"]]) previous_rainfall = all_annual_rainfall[all_years.index( year_list[year])] np.sum(rainfall[indices["start"]:indices["end"]]) annual_profit.append(farm_profit) # dispose of burn in dates # start with the third year. ie burn in period different for the climate periods, which start at different date of a year. the_dates = climate_dates[year_indices[2]["start"]:year_indices[years - 1]["end"]] all_years_flow = all_years_flow[year_indices[2]["start"]:] all_years_gwlevel = all_years_gwlevel[year_indices[2]["start"]:] all_years_profit = all_years_profit[year_indices[2]["start"]:] rainfall = rainfall[year_indices[2]["start"]:year_indices[years - 1]["end"]] # run ecological model surface_index, gwlevel_index = calculate_water_index( gw_level=all_years_gwlevel, flow=all_years_flow, dates=the_dates, threshold=eco_ctf, min_separation=eco_min_separation, min_duration=eco_min_duration, duration_weight=eco_weights["Duration"], timing_weight=eco_weights["Timing"], dry_weight=eco_weights["Dry"], surface_weight=0.5, gwlevel_weight=0.5, timing_col=timing_col, duration_col=duration_col, dry_col=dry_col, gwlevel_col=gwlevel_col) # sw_dates, sw, gw_dates, gw = read_NSW_data() # np.savetxt("gw_obs.csv", gw, delimiter=",") # with open("gw_obs.csv", "wb") as csvfile: # writer = csv.writer(csvfile) # for i in range(len(gw_dates)): # writer.writerow([gw_dates[i], gw[i]]) # with open("modelled_flow.csv", "wb") as csvfile: # writer = csv.writer(csvfile) # for i in range(len(climate_dates)): # print climate_dates[i], all_years_flow[i], all_years_gwlevel[i] # writer.writerow([climate_dates[i], all_years_flow[i], all_years_gwlevel[i]]) if plot: plot_results(the_dates, rainfall, all_years_flow, all_years_gwlevel, surface_index, gwlevel_index, all_years_profit) surface_index_sum, years = f_by_year(the_dates, surface_index, np.sum) gw_index_sum, years = f_by_year(the_dates, gwlevel_index, np.sum) gw_level_min, years = f_by_year(the_dates, all_years_gwlevel, np.std) # print surface_index_sum #return: annual farm profit, annual average return annual_profit, np.mean(surface_index_sum), np.mean( gw_index_sum), np.mean(all_years_gwlevel), np.mean(gw_level_min)