Demonstration of WellResponse Class

Notebook to demonstrate using the Well Class to estimate drawdown or stream depletion using the solutions available in the python module.

[1]:
import sys
sys.path.insert(1, '../../')
import pycap
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

Example Depletion

The Well class will estimate depletions for streams. The stream distances and streambed conductances, if needed, are passed through dictionaries keyed by a stream name or ID. In this notebook a table of values will be made manually from Table 2 from Reeves, H.W., Hamilton, D.A., Seelbach, P.W., and Asher, A.J., 2009, Ground-water-withdrawal component of the Michigan water-withdrawal screening tool: U.S. Geological Survey Scientific Investigations Report 2009–5003, 36 p. [https://pubs.usgs.gov/sir/2009/5003/]

[2]:
stream_table = pd.DataFrame(({'id': 8, 'distance': 14802},
                            {'id': 9, 'distance': 12609.2},
                            {'id': 11, 'distance': 15750.5},
                            {'id': 27, 'distance': 22567.6},
                            {'id': 9741, 'distance': 27565.2},
                            {'id': 10532, 'distance': 33059.5},
                            {'id': 11967, 'distance': 14846.3},
                            {'id': 12515, 'distance': 17042.55},
                            {'id': 12573, 'distance': 11959.5},
                            {'id': 12941, 'distance': 19070.8},
                            {'id': 13925, 'distance': 10028.9}))


[3]:
stream_table.head()
[3]:
id distance
0 8 14802.0
1 9 12609.2
2 11 15750.5
3 27 22567.6
4 9741 27565.2

Compute apportionment

The Michigan screening tool uses inverse distance weighting apportionment. Other apportionment approaches that may be used as a simple way to extend the analytical solution are discussed by Zipper and others (2019). [https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2018WR024403]

[4]:
invers =np.array([1/x for x in stream_table['distance']])
stream_table['apportionment'] = (1./stream_table['distance'])/np.sum(invers)
[5]:
stream_table
[5]:
id distance apportionment
0 8 14802.00 0.098916
1 9 12609.20 0.116118
2 11 15750.50 0.092959
3 27 22567.60 0.064878
4 9741 27565.20 0.053116
5 10532 33059.50 0.044288
6 11967 14846.30 0.098621
7 12515 17042.55 0.085911
8 12573 11959.50 0.122426
9 12941 19070.80 0.076774
10 13925 10028.90 0.145993
[6]:
np.sum(stream_table['apportionment'])
[6]:
1.0000000000000002

make dictionaries from the distances and apportionment values

[7]:
distances = dict(zip(stream_table.id.values, stream_table.distance.values))
[8]:
apportion = dict(zip(stream_table.id.values, stream_table.apportionment.values))

set aquifer properties and streambed conductances

[9]:
stream_table = pd.DataFrame(({'id': 8, 'distance': 14802},
                            {'id': 9, 'distance': 12609.2},
                            {'id': 11, 'distance': 15750.5},
                            {'id': 27, 'distance': 22567.6},
                            {'id': 9741, 'distance': 27565.2},
                            {'id': 10532, 'distance': 33059.5},
                            {'id': 11967, 'distance': 14846.3},
                            {'id': 12515, 'distance': 17042.5},
                            {'id': 12573, 'distance': 11959.5},
                            {'id': 12941, 'distance': 19070.8},
                            {'id': 13925, 'distance': 10028.9}))
[10]:
T= 7211.  # ft^2/day
S= 0.01
Q = 70  # 70 gpm in cubic feet per day
well_name = 'demo'
pumpdays = int(5. * 365)

call a utility to convert Q to a series with appropriate formatting

also convert to CFD from GPM

[11]:
Q = pycap.Q2ts(pumpdays, 5, Q) * pycap.GPM2CFD
[12]:
Q
[12]:
1       13475.935829
2       13475.935829
3       13475.935829
4       13475.935829
5       13475.935829
            ...
1821    13475.935829
1822    13475.935829
1823    13475.935829
1824    13475.935829
1825    13475.935829
Length: 1825, dtype: float64
[13]:
stream_table['conductance'] = 7.11855  # example uses constant streambed_conductance
[14]:
stream_table.head()
[14]:
id distance conductance
0 8 14802.0 7.11855
1 9 12609.2 7.11855
2 11 15750.5 7.11855
3 27 22567.6 7.11855
4 9741 27565.2 7.11855
[15]:
cond = dict(zip(stream_table.id.values, stream_table.conductance.values))
[16]:
test_well = pycap.Well(T=T,
                 S=S,
                 Q=Q,
                 depletion_years=5,
                 depl_method='hunt99',
                 drawdown_dist={'test0':50.},
                 streambed_conductance=cond,
                 stream_dist=distances,
                 stream_apportionment=apportion)
[17]:
test_well.drawdown
/home/runner/work/pycap-dss/pycap-dss/source/examples/../../pycap/solutions.py:66: RuntimeWarning: divide by zero encountered in divide
  u = dist**2.0 * S / (4.0 * T * time)
[17]:
{'test0': array([0.        , 0.96284254, 1.06585921, ..., 2.07921679, 2.07929839,
        2.07937994])}
[18]:
deltaQ = pycap._calc_deltaQ(Q)
deltaQ
[18]:
1    13475.935829
dtype: float64
[19]:
test_well.depletion
/home/runner/work/pycap-dss/pycap-dss/source/examples/../../pycap/solutions.py:561: RuntimeWarning: divide by zero encountered in divide
  a = np.sqrt(S * dist**2 / (4.0 * T * time))
[19]:
{8: array([0.00000000e+00, 3.98636452e-33, 3.31204669e-16, ...,
        9.90280807e+02, 9.90371342e+02, 9.90461805e+02]),
 9: array([0.00000000e+00, 7.13367383e-24, 1.74727419e-11, ...,
        1.21340842e+03, 1.21350207e+03, 1.21359564e+03]),
 11: array([0.00000000e+00, 1.44038609e-37, 1.82588316e-18, ...,
        9.13187370e+02, 9.13276691e+02, 9.13365942e+02]),
 27: array([0.00000000e+00, 2.33569680e-77, 1.39682712e-38, ...,
        5.52264289e+02, 5.52345936e+02, 5.52427521e+02]),
 9741: array([0.00000000e+000, 2.44245084e-115, 1.07059588e-057, ...,
        4.03755855e+002, 4.03832253e+002, 4.03908595e+002]),
 10532: array([0.00000000e+000, 1.00292409e-165, 5.26758880e-083, ...,
        2.94853678e+002, 2.94924279e+002, 2.94994832e+002]),
 11967: array([0.00000000e+00, 2.50629102e-33, 2.61529655e-16, ...,
        9.86458285e+02, 9.86548762e+02, 9.86639167e+02]),
 12515: array([0.00000000e+00, 4.77131258e-44, 9.40917849e-22, ...,
        8.22143476e+02, 8.22231229e+02, 8.22318914e+02]),
 12573: array([0.00000000e+00, 2.10485259e-21, 3.22528609e-10, ...,
        1.29536178e+03, 1.29545646e+03, 1.29555107e+03]),
 12941: array([0.00000000e+00, 3.21102915e-55, 2.08239385e-27, ...,
        7.04476694e+02, 7.04562126e+02, 7.04647491e+02]),
 13925: array([0.00000000e+00, 8.60822413e-15, 8.25718576e-07, ...,
        1.60192335e+03, 1.60202161e+03, 1.60211978e+03])}
[20]:
stream_depl = pd.DataFrame(test_well.depletion)

need to convert to GPM to compare results to Table 2

[21]:
stream_depl = stream_depl/pycap.GPM2CFD
stream_depl
[21]:
8 9 11 27 9741 10532 11967 12515 12573 12941 13925
0 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00 0.000000e+00
1 2.070695e-35 3.705547e-26 7.482006e-40 1.213265e-79 1.268718e-117 5.209633e-168 1.301879e-35 2.478432e-46 1.093354e-23 1.667951e-57 4.471494e-17
2 1.720424e-18 9.076119e-14 9.484449e-21 7.255741e-41 5.561151e-60 2.736220e-85 1.358501e-18 4.887545e-24 1.675357e-12 1.081688e-29 4.289149e-09
3 9.397226e-13 1.521286e-09 2.774686e-14 7.755022e-28 1.159869e-40 1.310323e-57 8.006897e-13 1.661375e-16 1.112081e-08 2.547071e-20 2.414180e-06
4 7.690155e-10 2.171820e-07 5.262710e-11 2.831779e-21 5.934766e-31 1.018311e-43 6.806930e-10 1.076022e-12 9.976385e-07 1.376230e-15 6.273796e-05
... ... ... ... ... ... ... ... ... ... ... ...
1820 5.143017e+00 6.302009e+00 4.742572e+00 2.867857e+00 2.096493e+00 1.530867e+00 5.123162e+00 4.269666e+00 6.727700e+00 3.658476e+00 8.320080e+00
1821 5.143488e+00 6.302496e+00 4.743037e+00 2.868282e+00 2.096890e+00 1.531234e+00 5.123632e+00 4.270122e+00 6.728193e+00 3.658921e+00 8.320591e+00
1822 5.143959e+00 6.302983e+00 4.743501e+00 2.868706e+00 2.097287e+00 1.531601e+00 5.124103e+00 4.270579e+00 6.728685e+00 3.659365e+00 8.321102e+00
1823 5.144429e+00 6.303469e+00 4.743965e+00 2.869130e+00 2.097684e+00 1.531968e+00 5.124573e+00 4.271034e+00 6.729177e+00 3.659809e+00 8.321612e+00
1824 5.144899e+00 6.303955e+00 4.744429e+00 2.869554e+00 2.098081e+00 1.532334e+00 5.125042e+00 4.271490e+00 6.729668e+00 3.660252e+00 8.322122e+00

1825 rows × 11 columns

[22]:
five_year= pd.DataFrame(stream_depl.loc[1824].T)
[23]:
five_year.rename(columns={1824: 'Depletion'}, inplace=True)
[24]:
pd.options.display.float_format = '{:,.2f}'.format
five_year
[24]:
Depletion
8 5.14
9 6.30
11 4.74
27 2.87
9741 2.10
10532 1.53
11967 5.13
12515 4.27
12573 6.73
12941 3.66
13925 8.32

Matches Table 2

[ ]:

[ ]: