#back up of working python code
parent
342f4f3bc0
commit
ddf60b7cb0
@ -0,0 +1,688 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
import re
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import collections
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
from tqdm import tqdm
|
||||||
|
from datetime import datetime
|
||||||
|
import pyrma.pyrma
|
||||||
|
|
||||||
|
path = "C:/Users/z5025317/OneDrive - UNSW/Hunter_CC_Modeling/07_Modelling/01_Input/BCGeneration/"
|
||||||
|
|
||||||
|
###Input parameters for Climate change runs
|
||||||
|
pres_start_date = datetime(int(1995), int('1'), int('1'))
|
||||||
|
pres_end_date = datetime(int(2005), int('12'), int('31'))
|
||||||
|
River_temp_increase = 0.5
|
||||||
|
|
||||||
|
# Load project settings
|
||||||
|
# Establish the settings and run parameters (see the description of
|
||||||
|
# settings that are in header of this code)
|
||||||
|
if __name__ == '__main__':
|
||||||
|
setup_files = [f for f in os.listdir(path) if f.lower().endswith('.s')]
|
||||||
|
if len(setup_files) == 1:
|
||||||
|
settingsfile = setup_files[0]
|
||||||
|
else:
|
||||||
|
print('Enter the name of the settings file: ')
|
||||||
|
settingsfile = input()
|
||||||
|
|
||||||
|
S = collections.OrderedDict()
|
||||||
|
|
||||||
|
print('Reading settings file: {}'.format(settingsfile))
|
||||||
|
with open(settingsfile, 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
# Ignore commented and empty lines
|
||||||
|
if line[0] is not '#' and line[0] is not '\n':
|
||||||
|
# Take key name before colon
|
||||||
|
ln = line.strip().split(':', 1)
|
||||||
|
key = ln[0]
|
||||||
|
|
||||||
|
# Separate multiple values
|
||||||
|
val = [x.strip() for x in ln[1].strip().split(',')]
|
||||||
|
|
||||||
|
if len(val) == 1:
|
||||||
|
val = val[0]
|
||||||
|
S[key] = val
|
||||||
|
|
||||||
|
val = ln[1].strip().split(',')
|
||||||
|
if len(val) == 1:
|
||||||
|
val = val[0]
|
||||||
|
S[key] = val
|
||||||
|
|
||||||
|
#create output directory
|
||||||
|
if not os.path.exists(S['output_dir']):
|
||||||
|
os.makedirs(S['output_dir'])
|
||||||
|
print('-------------------------------------------')
|
||||||
|
print("output directory folder didn't exist and was generated")
|
||||||
|
print('-------------------------------------------')
|
||||||
|
if not os.path.exists(S['output_dir'] + 'RMA2'):
|
||||||
|
os.makedirs(S['output_dir'] + 'RMA2')
|
||||||
|
print('-------------------------------------------')
|
||||||
|
print("output directory folder didn't exist and was generated")
|
||||||
|
print('-------------------------------------------')
|
||||||
|
if not os.path.exists(S['output_dir'] + 'RMA11'):
|
||||||
|
os.makedirs(S['output_dir'] + 'RMA11')
|
||||||
|
print('-------------------------------------------')
|
||||||
|
print("output directory folder didn't exist and was generated")
|
||||||
|
print('-------------------------------------------')
|
||||||
|
|
||||||
|
|
||||||
|
# Collect run parameters
|
||||||
|
env_str = ''
|
||||||
|
env_str += "{0:20} : {1}\n".format("Time Run",
|
||||||
|
time.strftime('%Y-%m-%d %H:%M:%S'))
|
||||||
|
env_str += "{0:20} : {1}\n".format("Settings File", settingsfile)
|
||||||
|
for envvar in S.keys():
|
||||||
|
env_str += "{0:20} : {1}\n".format(envvar, S[envvar])
|
||||||
|
|
||||||
|
# Load RMA mesh
|
||||||
|
print('Reading RMA mesh file')
|
||||||
|
nodes, elements = pyrma.loadMesh(S['mesh_file'])
|
||||||
|
mesh = pd.DataFrame(elements, index=[0]).transpose()
|
||||||
|
mesh.columns = ['name']
|
||||||
|
mesh['centroid'] = [e.centroid for e in elements.values()]
|
||||||
|
|
||||||
|
# Add empty lists to dataframe
|
||||||
|
mesh['inflows'] = np.empty((len(mesh), 0)).tolist()
|
||||||
|
mesh['inflows'] = mesh['inflows'].astype(object)
|
||||||
|
|
||||||
|
# Generate empty dataframe for inflows
|
||||||
|
start_date = datetime(int(S['start_year']), int(S['start_month']), int(S['start_day']))
|
||||||
|
end_date = datetime(int(S['end_year']), int(S['end_month']), int(S['end_day']))
|
||||||
|
inflow_timeseries = pd.DataFrame(index=pd.date_range(start_date, end_date))
|
||||||
|
|
||||||
|
# Generate empty dictionary (to be filled with dataframes) for water quality
|
||||||
|
wq_timeseries = {}
|
||||||
|
|
||||||
|
# Read upstream boundary inflows
|
||||||
|
if S['include_boundary_flows'].lower() == 'yes':
|
||||||
|
|
||||||
|
# Read boundary condition data from setup file
|
||||||
|
bc_data = {}
|
||||||
|
for key, val in S.items():
|
||||||
|
if re.match('bc_\d', key):
|
||||||
|
bc_data[val[0]] = dict(east=int(val[1]), north=int(val[2]))
|
||||||
|
|
||||||
|
dir_name = S['bc_directory']
|
||||||
|
for key, val in bc_data.items():
|
||||||
|
file_name = [x for x in os.listdir(dir_name) if x.startswith(key)][0]
|
||||||
|
bc_data[key]['path'] = os.path.join(dir_name, file_name)
|
||||||
|
|
||||||
|
# Assign upstream boundary inflows to RMA mesh
|
||||||
|
for key, val in bc_data.items():
|
||||||
|
|
||||||
|
# Find nearest element in RMA mesh
|
||||||
|
x = val['east']
|
||||||
|
y = val['north']
|
||||||
|
mesh['calc'] = [pyrma.point(x, y).dist(c) for c in mesh['centroid']]
|
||||||
|
idx = mesh['calc'].idxmin()
|
||||||
|
|
||||||
|
# Add nearest mesh element location to dataframe
|
||||||
|
mesh.at[idx, 'inflows'] = np.append(mesh.loc[idx, 'inflows'], key)
|
||||||
|
|
||||||
|
for key, val in bc_data.items():
|
||||||
|
|
||||||
|
# Read upstream boundary condition file
|
||||||
|
print('Reading upstream boundary inflow: {}'.format(key))
|
||||||
|
df = pd.read_csv(
|
||||||
|
val['path'], index_col=0, parse_dates=['datetime'], dayfirst=True)
|
||||||
|
|
||||||
|
#TH # Shift the upstream boundary flows into the future if date is in the future.
|
||||||
|
df.index = df.index + (start_date - pres_start_date)
|
||||||
|
|
||||||
|
# Trim dates to valid range
|
||||||
|
df = df[start_date:end_date]
|
||||||
|
|
||||||
|
# Scale flow units to m3/s
|
||||||
|
df[key] = df['Q[ML/d]'] * 1000 / 24 / 3600
|
||||||
|
|
||||||
|
# Merge all dataframes together
|
||||||
|
#inflow_timeseries2 = pd.merge(
|
||||||
|
#inflow_timeseries, df[[key]], right_index=True, left_index=True)
|
||||||
|
#TH #Tino added:
|
||||||
|
inflow_timeseries = pd.concat([inflow_timeseries, df[[key]]], axis=1)
|
||||||
|
|
||||||
|
# Add to water quality timeseries
|
||||||
|
wq_timeseries[key] = df.drop(['Q[ML/d]', key], axis = 1)
|
||||||
|
|
||||||
|
# Read WWTP data from setup file
|
||||||
|
wwtp_data = {}
|
||||||
|
for key, val in S.items():
|
||||||
|
if re.match('wwtp_\d', key):
|
||||||
|
wwtp_data[val[0]] = dict(east=int(val[1]), north=int(val[2]))
|
||||||
|
|
||||||
|
dir_name = S['wwtp_directory']
|
||||||
|
for key, val in wwtp_data.items():
|
||||||
|
file_name = [x for x in os.listdir(dir_name) if x.startswith(key)][0]
|
||||||
|
wwtp_data[key]['path'] = os.path.join(dir_name, file_name)
|
||||||
|
|
||||||
|
# Read WWTP inflows
|
||||||
|
if S['include_wwtp_flows'].lower() == 'yes':
|
||||||
|
print('Reading WWTP inflows (variable)')
|
||||||
|
for key in wwtp_data.keys():
|
||||||
|
df = pd.read_csv(
|
||||||
|
wwtp_data[key]['path'],
|
||||||
|
index_col=0,
|
||||||
|
parse_dates=[0],
|
||||||
|
dayfirst=True)
|
||||||
|
|
||||||
|
# Find nearest element in RMA mesh
|
||||||
|
x = wwtp_data[key]['east']
|
||||||
|
y = wwtp_data[key]['north']
|
||||||
|
mesh['calc'] = [pyrma.point(x, y).dist(c) for c in mesh['centroid']]
|
||||||
|
idx = mesh['calc'].idxmin()
|
||||||
|
|
||||||
|
# Add nearest mesh element location to dataframe
|
||||||
|
mesh.at[idx, 'inflows'] = np.append(mesh.loc[idx, 'inflows'], key)
|
||||||
|
|
||||||
|
# Convert from ML/day to m3/s
|
||||||
|
df[key] = df[['Q[ML/d]']] * 1000 / 24 / 3600
|
||||||
|
|
||||||
|
# Add to inflow time series dataframes
|
||||||
|
inflow_timeseries = inflow_timeseries.join(df[[key]])
|
||||||
|
|
||||||
|
# Add to water quality timeseries
|
||||||
|
wq_timeseries[key] = df.drop(['Q[ML/d]', key], axis = 1)
|
||||||
|
|
||||||
|
# Load reference rainfall and evapotranspiration
|
||||||
|
eto_master = pd.read_csv(
|
||||||
|
S['evap_file'], parse_dates=['datetime'], index_col=['datetime'])
|
||||||
|
rain_master = pd.read_csv(
|
||||||
|
S['rain_file'], parse_dates=['datetime'], index_col=['datetime'])
|
||||||
|
|
||||||
|
# Trim climate data to current date range
|
||||||
|
eto_master = eto_master[start_date:end_date]
|
||||||
|
rain_master = rain_master[start_date:end_date]
|
||||||
|
#inflow_timeseries.index.difference(rain_master.index)
|
||||||
|
|
||||||
|
|
||||||
|
# Calculate catchment inflows with AWBM
|
||||||
|
if S['include_hydro_model'].lower() == 'yes':
|
||||||
|
|
||||||
|
# Load water quality data for catchment inflows
|
||||||
|
for key in ['awbm_wq_natural', 'awbm_wq_urban']:
|
||||||
|
df = pd.read_csv(S[key], index_col=0, parse_dates=[0], dayfirst=True)
|
||||||
|
#TH # Shift the upstream boundary flows into the future if date is in the future.
|
||||||
|
df.index = df.index + (start_date - pres_start_date)
|
||||||
|
wq_timeseries[key] = df
|
||||||
|
|
||||||
|
print('Calculating AWBM inflows')
|
||||||
|
|
||||||
|
# Read catchment data
|
||||||
|
catchments = pd.read_csv(S['catchment_file'], index_col=[0])
|
||||||
|
catchments = catchments.set_index(catchments['Cat_Name'])
|
||||||
|
|
||||||
|
for index, row in catchments.iterrows():
|
||||||
|
|
||||||
|
# Find nearest element in RMA mesh
|
||||||
|
x = row.Easting
|
||||||
|
y = row.Northing
|
||||||
|
mesh['calc'] = [pyrma.point(x, y).dist(c) for c in mesh['centroid']]
|
||||||
|
idx = mesh['calc'].idxmin()
|
||||||
|
|
||||||
|
# Add nearest mesh element location to dataframe
|
||||||
|
mesh.at[idx, 'inflows'] = np.append(mesh.loc[idx, 'inflows'],
|
||||||
|
row.Cat_Name)
|
||||||
|
|
||||||
|
# Get weather station data
|
||||||
|
station_names = list(eto_master.columns)
|
||||||
|
|
||||||
|
# Load weights from Thiessen polygons
|
||||||
|
thiessen_weights = pd.read_csv(S['catchment_thiessen_weights'])
|
||||||
|
|
||||||
|
# Add catchment inflows
|
||||||
|
for index, c in catchments.iterrows():
|
||||||
|
|
||||||
|
# Time step (units: days)
|
||||||
|
timeStep = 1.0
|
||||||
|
|
||||||
|
# Area (units: m2)
|
||||||
|
totalArea = c['Area (km2)'] * 1000 * 1000
|
||||||
|
|
||||||
|
# S
|
||||||
|
consS = [c['C1'], c['C2'], c['C3']]
|
||||||
|
|
||||||
|
# A (must sum to 1)
|
||||||
|
consA = [c['A1'], c['A2'], c['A3']]
|
||||||
|
|
||||||
|
consKB = c['Kbase']
|
||||||
|
consKS = c['Ksurf']
|
||||||
|
BFI = c['BFI']
|
||||||
|
|
||||||
|
bucketValue = [0, 0, 0]
|
||||||
|
bfValue = 0
|
||||||
|
sfValue = 0
|
||||||
|
|
||||||
|
def flowInit(length):
|
||||||
|
vec = [0] * length
|
||||||
|
return vec
|
||||||
|
|
||||||
|
def updatebucket(Elevation, surfaceCon, previousValue, flow):
|
||||||
|
if Elevation > surfaceCon:
|
||||||
|
flow = Elevation - surfaceCon
|
||||||
|
previousValue = surfaceCon
|
||||||
|
else:
|
||||||
|
flow = 0
|
||||||
|
previousValue = max(Elevation, 0)
|
||||||
|
return previousValue, flow
|
||||||
|
|
||||||
|
# Calculate Thiessen weightings
|
||||||
|
weights = thiessen_weights[thiessen_weights['Name'] == c['Cat_Name']][
|
||||||
|
station_names]
|
||||||
|
|
||||||
|
rain_local = (rain_master[station_names] *
|
||||||
|
weights.values.flatten()).sum(axis=1).values
|
||||||
|
|
||||||
|
eto_local = (eto_master[station_names] *
|
||||||
|
weights.values.flatten()).sum(axis=1).values
|
||||||
|
|
||||||
|
# Count number of timesteps
|
||||||
|
n = len(rain_master.index)
|
||||||
|
|
||||||
|
Excess = [flowInit(n) for i in range(3)]
|
||||||
|
ExcessTotal = flowInit(n)
|
||||||
|
ExcessBF = flowInit(n)
|
||||||
|
ExcessSF = flowInit(n)
|
||||||
|
ExcessRunoff = flowInit(n)
|
||||||
|
Qflow = flowInit(n)
|
||||||
|
|
||||||
|
[aa, bb] = updatebucket(1, 2, 3, 4)
|
||||||
|
for i in range(1, len(rain_local)):
|
||||||
|
ElevTemp = [[bucketValue[j] + rain_local[i] - eto_local[i]]
|
||||||
|
for j in range(3)]
|
||||||
|
for k in range(3):
|
||||||
|
[bucketValue[k], Excess[k][i]] = updatebucket(
|
||||||
|
ElevTemp[k][0], consS[k], bucketValue[k], Excess[k][i - 1])
|
||||||
|
ExcessTotal[i] = (Excess[0][i] * consA[0] + Excess[1][i] * consA[1]
|
||||||
|
+ Excess[2][i] * consA[2])
|
||||||
|
ExcessBF[i] = bfValue + ExcessTotal[i] * BFI
|
||||||
|
bfValue = max(consKB * ExcessBF[i], 0)
|
||||||
|
ExcessSF[i] = sfValue + (1 - BFI) * ExcessTotal[i]
|
||||||
|
sfValue = max(consKS * ExcessSF[i], 0)
|
||||||
|
ExcessRunoff[i] = ((1 - consKB) * ExcessBF[i] +
|
||||||
|
(1 - consKS) * ExcessSF[i])
|
||||||
|
|
||||||
|
Qflow = [
|
||||||
|
a * (1e-3) * totalArea / (timeStep * 86400) for a in ExcessRunoff
|
||||||
|
] # flow in m3/s
|
||||||
|
|
||||||
|
Qflow_df = pd.DataFrame(Qflow, index=rain_master.index)
|
||||||
|
Qflow_df.columns = [c['Cat_Name']]
|
||||||
|
#inflow_timeseries[c['Cat_Name']] = Qflow
|
||||||
|
inflow_timeseries = pd.concat([inflow_timeseries, Qflow_df], axis=1)
|
||||||
|
#interpolate the NA value of the leap year 29th of March
|
||||||
|
inflow_timeseries[c['Cat_Name']]= inflow_timeseries[c['Cat_Name']].interpolate(method='linear', axis=0)
|
||||||
|
|
||||||
|
# Calculate irrigation demand
|
||||||
|
if S['include_crop_model'].lower() == 'yes':
|
||||||
|
|
||||||
|
print('Calculating irrigation demand')
|
||||||
|
|
||||||
|
# Create QA summary
|
||||||
|
qa_fraction_used = pd.DataFrame(
|
||||||
|
index=pd.date_range(start=start_date, end=end_date, freq='AS'))
|
||||||
|
|
||||||
|
# Load water licence holders
|
||||||
|
licences = pd.read_csv(S['licences_file'])
|
||||||
|
licences['point'] = [
|
||||||
|
pyrma.point(x, y)
|
||||||
|
for x, y in zip(licences['Easting'], licences['Northing'])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Assign water licences to RMA mesh
|
||||||
|
for index, row in licences.iterrows():
|
||||||
|
|
||||||
|
# Find nearest element in RMA mesh
|
||||||
|
x = row.Easting
|
||||||
|
y = row.Northing
|
||||||
|
mesh['calc'] = [pyrma.point(x, y).dist(c) for c in mesh['centroid']]
|
||||||
|
idx = mesh['calc'].idxmin()
|
||||||
|
|
||||||
|
# Add nearest mesh element location to dataframe
|
||||||
|
mesh.at[idx, 'inflows'] = np.append(mesh.loc[idx, 'inflows'],
|
||||||
|
row.CWLICENSE)
|
||||||
|
|
||||||
|
weather_stations = pd.read_excel(S['weather_station_file'])
|
||||||
|
weather_stations['point'] = [
|
||||||
|
pyrma.point(x, y) for x, y in zip(weather_stations['E_MGA56'],
|
||||||
|
weather_stations['N_MGA56'])
|
||||||
|
]
|
||||||
|
|
||||||
|
# Find nearest weather station
|
||||||
|
licences['station_name'] = ''
|
||||||
|
for index, row in licences.iterrows():
|
||||||
|
idx = np.argmin(
|
||||||
|
[row['point'].dist(p) for p in weather_stations['point']])
|
||||||
|
licences.at[index, 'station_name'] = weather_stations['Name'][idx]
|
||||||
|
|
||||||
|
# http://www.fao.org/docrep/x0490e/x0490e0e.htm
|
||||||
|
crop_types = {
|
||||||
|
'type': [
|
||||||
|
'pasture', 'turf', 'lucerne', 'vegetables', 'orchard',
|
||||||
|
'non_irrigation'
|
||||||
|
],
|
||||||
|
'crop_coefficient': [1, 1, 1, 1, 1, np.nan],
|
||||||
|
'root_zone_depth': [1000, 750, 1500, 500, 1500, np.nan],
|
||||||
|
'allowable_depletion': [0.6, 0.5, 0.6, 0.5, 0.5, np.nan],
|
||||||
|
}
|
||||||
|
|
||||||
|
crop_types = pd.DataFrame(crop_types)
|
||||||
|
|
||||||
|
# Check number of days to spread irrigation over
|
||||||
|
irrigation_days = int(S['irrigation_days'])
|
||||||
|
|
||||||
|
# Check if moisture in soil should be kept full (saturated) or empty
|
||||||
|
if S['irrigate_to_saturation'].lower() == 'yes':
|
||||||
|
saturation_mode = True
|
||||||
|
else:
|
||||||
|
saturation_mode = False
|
||||||
|
|
||||||
|
irrigation_time_factor = 1 / irrigation_days
|
||||||
|
|
||||||
|
# Iterate through licences
|
||||||
|
for index, lic in tqdm(licences.iterrows(), total=licences.shape[0]):
|
||||||
|
|
||||||
|
# Initialise variables for new licence
|
||||||
|
currently_irrigating = False
|
||||||
|
licence_exhausted = False
|
||||||
|
|
||||||
|
# Annual extraction volume
|
||||||
|
annual_volume_capped = lic['SHARECOMPO'] * 1000
|
||||||
|
annual_volume_uncapped = np.inf
|
||||||
|
|
||||||
|
# Set a maximum daily extraction limit
|
||||||
|
daily_maximum_volume = annual_volume_capped * float(
|
||||||
|
S['daily_limit_fraction'])
|
||||||
|
|
||||||
|
if S['capped_to_licence'].lower() == 'yes':
|
||||||
|
# Limited to share component
|
||||||
|
annual_volume = annual_volume_capped
|
||||||
|
else:
|
||||||
|
# Unlimited
|
||||||
|
annual_volume = annual_volume_uncapped
|
||||||
|
|
||||||
|
# Check if licence is for non-irrigation purposes
|
||||||
|
if lic['PRIMARY_USE'].lower() == 'non_irrigation':
|
||||||
|
# Distribute licenced amount evenly over year (m3/year to m3/s)
|
||||||
|
irrigation_q = annual_volume / 365.25 / 24 / 3600
|
||||||
|
inflow_timeseries[lic['CWLICENSE']] = -irrigation_q
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Irrigation area (m2)
|
||||||
|
area = lic['Area']
|
||||||
|
|
||||||
|
# Available water holding capacity (mm per m)
|
||||||
|
water_holding_capacity = 110 / 1000
|
||||||
|
|
||||||
|
# Get parameters for specific crop type
|
||||||
|
crop = crop_types[crop_types['type'] == lic['PRIMARY_USE'].lower()]
|
||||||
|
|
||||||
|
# Crop coefficient (from FAO56)
|
||||||
|
crop_coefficient = float(crop['crop_coefficient'])
|
||||||
|
|
||||||
|
# Root zone depth (mm)
|
||||||
|
root_zone_depth = float(crop['root_zone_depth'])
|
||||||
|
|
||||||
|
# Allowable water level depletion, before irrigation is required (%)
|
||||||
|
allowable_depletion = float(crop['allowable_depletion'])
|
||||||
|
|
||||||
|
# Irrigation efficiency (percent)
|
||||||
|
efficiency = float(S['irrigation_efficiency'])
|
||||||
|
|
||||||
|
# Plant available water (mm)
|
||||||
|
plant_available_water = root_zone_depth * water_holding_capacity
|
||||||
|
|
||||||
|
# Irrigation trigger depth (mm)
|
||||||
|
threshold_depth = plant_available_water * allowable_depletion
|
||||||
|
|
||||||
|
# Calculate soil moisture over time
|
||||||
|
rain_local = rain_master[lic['station_name']]
|
||||||
|
eto_local = eto_master[lic['station_name']]
|
||||||
|
date = rain_master.index
|
||||||
|
depletion_depth = np.zeros(len(date))
|
||||||
|
irrigation_volume = np.zeros(len(date))
|
||||||
|
annual_irrigation_volume = np.zeros(len(date))
|
||||||
|
|
||||||
|
etc = eto_local * crop_coefficient
|
||||||
|
|
||||||
|
for i in range(1, len(date)):
|
||||||
|
|
||||||
|
if not saturation_mode:
|
||||||
|
currently_irrigating = False
|
||||||
|
|
||||||
|
# Calculate remaining licence allocation
|
||||||
|
remaining_allocation = annual_volume - annual_irrigation_volume[i -
|
||||||
|
1]
|
||||||
|
|
||||||
|
# Check if licence is exhausted
|
||||||
|
if remaining_allocation <= 0:
|
||||||
|
licence_exhausted = True
|
||||||
|
|
||||||
|
# Apply evapotranspiration and rain
|
||||||
|
current_depth = depletion_depth[i - 1] + etc[i] - rain_local[i - 1]
|
||||||
|
|
||||||
|
# Check if soil was irrigated the previous day
|
||||||
|
if irrigation_volume[i - 1] > 0:
|
||||||
|
current_depth = (
|
||||||
|
current_depth -
|
||||||
|
irrigation_volume[i - 1] / area * 1000 * efficiency)
|
||||||
|
|
||||||
|
# If soil is saturated from rain or irrigation, do not store excess
|
||||||
|
if current_depth < 0:
|
||||||
|
current_depth = 0
|
||||||
|
currently_irrigating = False
|
||||||
|
|
||||||
|
# Check if soil moisture is too low
|
||||||
|
if (((current_depth > threshold_depth) and
|
||||||
|
(rain_local[i] < 0.2 * current_depth)) or currently_irrigating):
|
||||||
|
|
||||||
|
if currently_irrigating:
|
||||||
|
idx_last_irrigation = np.where(
|
||||||
|
irrigation_volume[i::-1])[0][0]
|
||||||
|
irrigation_volume[i] = np.min([
|
||||||
|
irrigation_volume[i - idx_last_irrigation],
|
||||||
|
remaining_allocation, daily_maximum_volume
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
currently_irrigating = True
|
||||||
|
irrigation_volume[i] = np.min([
|
||||||
|
current_depth / 1000 * area / efficiency *
|
||||||
|
irrigation_time_factor, remaining_allocation,
|
||||||
|
daily_maximum_volume
|
||||||
|
])
|
||||||
|
|
||||||
|
if licence_exhausted:
|
||||||
|
irrigation_volume[i] = 0
|
||||||
|
current_depth = threshold_depth
|
||||||
|
currently_irrigating = False
|
||||||
|
|
||||||
|
# Check if new year has started
|
||||||
|
if date[i].dayofyear == 1:
|
||||||
|
annual_irrigation_volume[i] = 0 + irrigation_volume[i]
|
||||||
|
licence_exhausted = False
|
||||||
|
else:
|
||||||
|
annual_irrigation_volume[
|
||||||
|
i] = annual_irrigation_volume[i - 1] + irrigation_volume[i]
|
||||||
|
|
||||||
|
# Update depletion depth
|
||||||
|
depletion_depth[i] = current_depth
|
||||||
|
|
||||||
|
# Update QA table at end of year
|
||||||
|
if (date[i].month == 12) & (date[i].day == 31):
|
||||||
|
q_fraction_of_licence = annual_irrigation_volume[
|
||||||
|
i] / annual_volume_capped
|
||||||
|
qa_fraction_used.loc[datetime(date[i].year, 1, 1), lic[
|
||||||
|
'CWLICENSE']] = q_fraction_of_licence
|
||||||
|
|
||||||
|
# Update inflows with irrigation demand (sign is negative for outflow)
|
||||||
|
irrigation_q = irrigation_volume / 24 / 3600
|
||||||
|
irrigation_q_df = pd.DataFrame(irrigation_q, index=rain_master.index)
|
||||||
|
irrigation_q_df.columns = [lic['CWLICENSE']]
|
||||||
|
inflow_timeseries = pd.concat([inflow_timeseries, irrigation_q_df], axis=1)
|
||||||
|
#interpolate the NA value of the leap year 29th of March
|
||||||
|
inflow_timeseries[lic['CWLICENSE']]= inflow_timeseries[lic['CWLICENSE']].interpolate(method='linear', axis=0)
|
||||||
|
#inflow_timeseries[lic['CWLICENSE']] = -irrigation_q
|
||||||
|
|
||||||
|
|
||||||
|
# Consolidate wq data into single dataframe
|
||||||
|
if S['include_WQ'].lower() == 'yes':
|
||||||
|
wq_df = pd.DataFrame()
|
||||||
|
wq_cols = wq_timeseries.keys()
|
||||||
|
|
||||||
|
####Written by tino##############################################
|
||||||
|
# # Generate empty dataframe for inflows
|
||||||
|
# Full_present_period_df = pd.DataFrame(index=pd.date_range(pres_start_date, pres_end_date))
|
||||||
|
# # Generate empty dataframe for inflows
|
||||||
|
# start_date = datetime(
|
||||||
|
# int(S['start_year']), int(S['start_month']), int(S['start_day']))
|
||||||
|
# end_date = datetime(int(S['end_year']), int(S['end_month']), int(S['end_day']))
|
||||||
|
# for n in wq_cols:
|
||||||
|
# Full_present_period_df = pd.concat([Full_present_period_df, pd.DataFrame(wq_timeseries[n]['Salinity'])], axis=1)
|
||||||
|
# Full_present_period_df = pd.DataFrame(Full_present_period_df.loc[(Full_present_period_df .index >= pres_start_date) & (Full_present_period_df .index <= pres_end_date)])
|
||||||
|
# wq = Full_present_period_df.replace(np.nan, 0)
|
||||||
|
# wq.columns = wq_cols
|
||||||
|
# #shift the WQ time series into the future if a future model run is executed
|
||||||
|
# wq.index = wq.index + (start_date - pres_start_date)
|
||||||
|
# #wq.index.name = 'constituent'
|
||||||
|
# #wq = wq.reset_index()
|
||||||
|
# #wq.index = np.tile(1, wq.shape[0])
|
||||||
|
# wq_df = wq
|
||||||
|
# #wq_df = wq_df.append(wq)
|
||||||
|
####Written by tino##############################################
|
||||||
|
|
||||||
|
#there is a problem here if the model run goes earlier than 1994, it
|
||||||
|
#then can't find the 1990 index from teh inflow_timeseries
|
||||||
|
#wq_timeseries[n].index
|
||||||
|
for i in inflow_timeseries.index:
|
||||||
|
wq = pd.DataFrame([wq_timeseries[n].loc[i, :] for n in wq_cols]).T
|
||||||
|
wq.columns = wq_cols
|
||||||
|
wq.index.name = 'constituent'
|
||||||
|
wq = wq.reset_index()
|
||||||
|
wq.index = np.tile(i, wq.shape[0])
|
||||||
|
wq_df = wq_df.append(wq)
|
||||||
|
|
||||||
|
#Shift the water quality time series data frame by
|
||||||
|
wq_df.index = wq_df.index + (start_date - pres_start_date)
|
||||||
|
|
||||||
|
|
||||||
|
# Write element inflows for RMA
|
||||||
|
# Consolidate inflow elements in RMA mesh (only include those with inflows)
|
||||||
|
inflow_elements = mesh.loc[[len(n) > 0
|
||||||
|
for n in mesh['inflows']], ['name', 'inflows']]
|
||||||
|
|
||||||
|
# Iterate through years
|
||||||
|
for current_year in range(start_date.year, end_date.year + 1):
|
||||||
|
|
||||||
|
# RMA2: create input file
|
||||||
|
fq = open(
|
||||||
|
os.path.join(S['output_dir'], 'RMA2', '{}.elt'.format(current_year)),
|
||||||
|
'w')
|
||||||
|
fq.write('TE Generated Runoff (see end of file for run parameters)\n')
|
||||||
|
|
||||||
|
# RMA11: create input file
|
||||||
|
if S['include_WQ'].lower() == 'yes':
|
||||||
|
fwq = open(
|
||||||
|
os.path.join(S['output_dir'], 'RMA11',
|
||||||
|
'{}.wqg'.format(current_year)), 'w')
|
||||||
|
|
||||||
|
# Create progress bar
|
||||||
|
pbar = tqdm(
|
||||||
|
inflow_elements['inflows'].iteritems(), total=inflow_elements.shape[0])
|
||||||
|
|
||||||
|
# Iterate through mesh elements
|
||||||
|
for ID, q_names in pbar:
|
||||||
|
|
||||||
|
# Update progess bar
|
||||||
|
pbar.set_description('Writing input for year {}'.format(current_year))
|
||||||
|
|
||||||
|
# For each new element
|
||||||
|
fq.write('{:<8}{:>8}{:>8}{:>8}'.format('QEI', ID, 1, current_year))
|
||||||
|
fq.write(' ### {}\n'.format(list(q_names)))
|
||||||
|
|
||||||
|
if S['include_WQ'].lower() == 'yes':
|
||||||
|
fwq.write('TI {}\n'.format(list(q_names)))
|
||||||
|
fwq.write('{:<8}{:>8}{:>8}{:>8}\n'.format('QT', ID, 3,
|
||||||
|
current_year))
|
||||||
|
|
||||||
|
# Iterate through time steps
|
||||||
|
for index, row in inflow_timeseries[inflow_timeseries.index.year ==
|
||||||
|
current_year].iterrows():
|
||||||
|
# Calculate flow rate for each timestep
|
||||||
|
q = sum(row[q_names].values)
|
||||||
|
fq.write('{:<5}{:>3}{:>8}{:>+8.1E}\n'.format(
|
||||||
|
'QE', index.dayofyear, index.hour, q))
|
||||||
|
|
||||||
|
if S['include_WQ'].lower() == 'yes':
|
||||||
|
# Get water quality values for current day
|
||||||
|
#wq = wq_df.loc[index, :].set_index('constituent')
|
||||||
|
index + 100
|
||||||
|
wq = wq_df[wq_df.index == index].set_index('constituent') #TH I changed this since the constituent part did not work here.
|
||||||
|
# Get names of WWTP, catchment, and boundaries at current element
|
||||||
|
try:
|
||||||
|
w_names = [x for x in q_names if x in wwtp_data.keys()]
|
||||||
|
except NameError:
|
||||||
|
w_names = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
c_names = [x for x in q_names if x in catchments.index]
|
||||||
|
except NameError:
|
||||||
|
c_names = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
b_names = [x for x in q_names if x in bc_data.keys()]
|
||||||
|
except NameError:
|
||||||
|
b_names = []
|
||||||
|
|
||||||
|
# Initialise water quality values
|
||||||
|
wq_mass = np.zeros(len(wq.index))
|
||||||
|
|
||||||
|
# Calculate water quality in catchment runoff
|
||||||
|
if c_names:
|
||||||
|
c_natural_frac = catchments.loc[c_names, 'Natural'].values
|
||||||
|
c_natural_conc = wq['awbm_wq_natural'].values[:,
|
||||||
|
np.newaxis]
|
||||||
|
c_urban_frac = catchments.loc[c_names, 'Urban'].values
|
||||||
|
c_urban_conc = wq['awbm_wq_urban'].values[:, np.newaxis]
|
||||||
|
c_flow = row[c_names].values
|
||||||
|
|
||||||
|
wq_mass += np.sum(
|
||||||
|
c_flow * (c_natural_frac * c_natural_conc +
|
||||||
|
c_urban_frac * c_urban_conc),
|
||||||
|
axis=1)
|
||||||
|
|
||||||
|
# Calculate water quality from WWTP inflows
|
||||||
|
if w_names:
|
||||||
|
w_conc = wq[w_names].values
|
||||||
|
w_flow = row[w_names].values
|
||||||
|
wq_mass += np.sum(w_flow * w_conc, axis=1)
|
||||||
|
|
||||||
|
# Calculate water quality from upstream boundaries
|
||||||
|
if b_names:
|
||||||
|
b_conc = wq[b_names].values
|
||||||
|
b_flow = row[b_names].values
|
||||||
|
wq_mass += np.sum(b_flow * b_conc, axis=1)
|
||||||
|
|
||||||
|
# Calculate water quality concentrations
|
||||||
|
if q <= 0:
|
||||||
|
wq_conc = [0] * len(wq_mass)
|
||||||
|
else:
|
||||||
|
wq_conc = wq_mass / q
|
||||||
|
|
||||||
|
# Write water quality concentrations
|
||||||
|
fwq.write('{:<5}{:>3}{:>8}{:>+8.1E}'.format(
|
||||||
|
'QD', index.dayofyear, index.hour, q) + ''.join(
|
||||||
|
'{:>8.2E}'.format(x) for x in wq_conc))
|
||||||
|
fwq.write('\n')
|
||||||
|
|
||||||
|
fq.write('ENDDATA\n\n')
|
||||||
|
fq.write(env_str)
|
||||||
|
fq.close()
|
||||||
|
|
||||||
|
if S['include_WQ'].lower() == 'yes':
|
||||||
|
fwq.write('ENDDATA\n\n')
|
||||||
|
fwq.write(env_str)
|
||||||
|
fwq.close()
|
||||||
|
|
||||||
|
print(env_str.split('\n')[0])
|
||||||
|
print('Done\n')
|
Loading…
Reference in New Issue