def setup_and_run_fdm(gridpar, k, rch, axis=1): Lx, wx, Ly, wy, D, d = gridpar x = np.linspace(-Lx, Lx, int(2 * Lx / wx) + 1) y = np.linspace(-Ly, Ly, int(2 * Ly / wy) + 1) z = np.linspace(-D, D, int(2 * D / d) + 1) gr = mfgrid.Grid(x, y, z) K = gr.const(k) FH = gr.const(0.) FQ = gr.Volume * rch IBOUND = gr.const(1) if axis == 0: IBOUND[[0, -1], :, :] = -1 elif axis == 1: IBOUND[:, [0, -1], :] = -1 elif axis == 2: IBOUND[:, :, [0, -1]] = -1 else: print("axis must be 0, 1, or 2, not {}".format(axis)) # Solve for the heads: Out = fdm.fdm3(gr, (K, K, K), FQ, FH, IBOUND) return Out, gr, IBOUND
def setup_and_run_fdm(gridpar, k, Q): Lx, wx, Ly, wy, D, d = gridpar x = np.linspace(-Lx, Lx, int(2 * Lx / wx) + 1) y = np.linspace(-Ly, Ly, int(2 * Ly / wy) + 1) z = np.linspace(-D, D, int(2 * D / d) + 1) gr = mfgrid.Grid(x, y, z) K = gr.const(k) # * np.random.rand(gr.Nod).reshape(gr.shape) FH = gr.const(0.) FQ = gr.const(0.) IBOUND = gr.const(1) IBOUND[[0, -1], :, :] = -1 IBOUND[:, [0, -1], :] = -1 IBOUND[:, :, [0, -1]] = -1 icx, icy, icz = gr.ixyz(0., 0., 0.) FQ[icy, icx, icz] = Q # Solve for the heads: Out = fdm.fdm3(gr, (K, K, K), FQ, FH, IBOUND) return Out, gr, IBOUND
def set_up_and_run_fdm(gridpar, k, hbound, axis=None): Lx, wx, Ly, wy, D, d = gridpar x = np.linspace(-Lx, Lx, int(2 * Lx / wx) + 1) y = np.linspace(-Ly, Ly, int(2 * Ly / wy) + 1) z = np.linspace(-D , D, int(2 * D / d) + 1) gr = mfgrid.Grid(x, y, z) K = gr.const(k) # * np.random.rand(gr.Nod).reshape(gr.shape) FH = gr.const(0.) FQ = gr.const(0.) IBOUND = gr.const(1) if axis == 0: IBOUND[[0, -1], :, :] = -1 FH[0, :, :] = hbound[0] FH[-1, :,:] = hbound[1] elif axis == 1: IBOUND[:,[0, -1], :] = -1 FH[:, 0, :] = hbound[0] FH[:, -1, :] = hbound[1] elif axis == 2: IBOUND[:, :, [0, -1]] = -1 FH[:, :, 0] = hbound[0] FH[:, :, -1] = hbound[1] else: print("axis must be 0, 1, or to, not {}".format(axis)) raise ValueError() # Solve for the heads: Out = fdm.fdm3(gr, (K, K, K), FQ, FH, IBOUND) return Out, gr, IBOUND
def example_de_glee(): """Axial symmetric example, well in semi-confined aquifer (De Glee case) De Glee was a Dutch engineer/groundwater hydrologist and later the first director of the water company of the province of Groningen. His PhD (1930) solved the axial symmetric steady state flow to a well in a semi confined aquifer using the Besselfunctions of the second kind, known as K0 and K1. The example computes the heads in the regional aquifer below a semi confining layer with a fixed head above. It uses two model layers a confining one in which the heads are fixed and a semi-confined aquifer with a prescribed extraction at r=r0. If r0>>0, both K0 and K1 Bessel functions are needed. The grid is signaled to use inteprete the grid as axially symmetric. """ Q = -1200.0 # m3/d, well extraction r0 = 100. # m, well radius R = 2500. # m, outer radius of model d = 10. # m, thickness of confining top layer D = 50. # m, thickness of regional aquifer c = 250 # d, vertical resistance of confining top layer k1 = d / c # m/d conductivity of confining top layer k2 = 10. # m/d conductivity of regional aquifer kD = k2 * D # m2/d, transmissivity of regional aquifer r = np.hstack((r0 + 0.001, np.logspace(np.log10(r0), np.log10(R), 41))) # distance to well center y = None # dummy, ignored because problem is axially symmetric z = np.array([0, -d, -d - D]) # m, elevation of tops and bottoms of model layers gr = mfgrid.Grid(r, y, z, axial=True) # generate grid FQ = gr.const(0.) FQ[0, 0, -1] = Q # m3/d fixed flows IH = gr.const(0.) # m, initial heads IBOUND = gr.const(1) IBOUND[:, :, 0] = -1 # modflow like boundary array K = gr.const([k1 / 2., k2]) # full 3D array of conductivities out = fdm.fdm3(gr, K, FQ, IH, IBOUND) # run model numerical = out.Phi[0, :, -1] analytic = de_glee(Q, kD, c, r0, gr.xm) #============================================================================== # plt.figure() # plt.setp(plt.gca(), 'xlabel', 'r [m]', 'ylabel', 'head [m]',\ # 'title', 'De Glee, well extraction, axially symmetric', 'xscale', 'log', 'xlim', [1.0, R]) # plt.plot(gr.xm, numerical, 'ro-', label='fdm3') # plt.plot(gr.xm, analytic , 'bx-',label='analytic') # plt.legend() # #============================================================================== return numerical, analytic, out
def set_up_and_run_fdm(gridpar, k, Q, well_axis): Lx, wx, Ly, wy, D, d = gridpar x = np.linspace(-Lx, Lx, int(2 * Lx / wx) + 1) y = np.linspace(-Ly, Ly, int(2 * Ly / wy) + 1) z = np.linspace(-D , D, int(2 * D / d) + 1) gr = mfgrid.Grid(x, y, z) K = gr.const(k) # * np.random.rand(gr.Nod).reshape(gr.shape) FH = gr.const(0.) FQ = gr.const(0.) # Cell indices of center of model: hard wired here x0, y0, z0 = 0., 0., 0. icx, icy, icz = gr.ixyz(x0, y0, z0) # Covner to int to prevent shape errors with FQ below icx = int(icx); icy=int(icy); icz=int(icz) if well_axis == 2: # i.e. z # screen in z direction, flow in xy plane IBOUND = gr.const(1) IBOUND[[0,-1], :, :] = -1 IBOUND[:, [0,-1], :] = -1 FQ[icy, icx, :] = Q * gr.dz / np.sum(gr.dz) elif well_axis == 0: # i.e. y # screen in x direction, flow in zx plane IBOUND = gr.const(1) IBOUND[:, [0,-1], :] = -1 IBOUND[:, :, [0,-1]] = -1 FQ[:, icx, icz] = Q * gr.dy / np.sum(gr.dy) elif well_axis == 1: # i.e. x # screen in y direction, flow in yz plane IBOUND = gr.const(1) IBOUND[[0,-1], :, :] = -1 IBOUND[:, :, [0,-1]] = -1 FQ[icy, :, icz] = Q * gr.dx / np.sum(gr.dx) else: print("well_axis must be 0, 1, or 2, not {}".format(well_axis)) # Solve for the heads: Out = fdm.fdm3(gr, (K, K, K), FQ, FH, IBOUND) return Out, gr, IBOUND
def example_mazure(): """1D flow in semi-confined aquifer example Mazure was Dutch professor in the 1930s, concerned with leakage from polders that were pumped dry. His situation is a cross section perpendicular to the dike of a regional aquifer covered by a semi-confining layer with a maintained head in it. The head in the regional aquifer at the dike was given as well. The head obeys the following analytical expression phi(x) - hp = (phi(0)-hp) * exp(-x/lam), lam = sqrt(kDc) To compute we use 2 model layers and define the values such that we obtain the Mazure result. """ x = np.hstack((0.001, np.linspace(0., 2000., 101))) # column coordinates y = np.array([-0.5, 0.5]) # m, model is 1 m thick d = 10. # m, thickness of confining top layer D = 50. # m, thickness of regional aquifer z = np.array([0, -d, -d - D]) # tops and bottoms of layers gr = mfgrid.Grid(x, y, z, axial=False) c = 250 # d, vertical resistance of semi-confining layer k1 = d / c # m/d conductivity of the top layer k2 = 10. # m/d conductivity of the regional aquifer kD = k2 * D # m2/d, transmissivity of regional aquifer K = gr.const([k1 / 2., k2]) # k1 = 0.5 d/c because conductance from layer center FQ = gr.const(0) # prescribed flows s0 = 2.0 # head in aquifer at x=0 IH = gr.const(0) IH[:, 0, -1] = s0 # prescribed heads IBOUND = gr.const(1) IBOUND[:, :, 0] = -1 IBOUND[:, 0, -1] = -1 out = fdm.fdm3(gr, K, FQ, IH, IBOUND) # compute heads, run model numerical = out.Phi[0, :, -1] analytic = vanMarzure(s0, kD, c, gr.xm) #============================================================================== # plt.figure() # plt.setp(plt.gca(), 'xlabel','x [m]', 'ylabel', 'head [m]', 'title', 'Mazure 1D flow') # plt.plot(gr.xm, numerical, 'ro-', label='fdm3') # numeric solution # plt.plot(gr.xm, analytic ,'bx-', label='analytic') # analytic solution # plt.legend() # #============================================================================== return numerical, analytic, out
def setupAndRunFDM_model(gridpar, k, hbound): Lx, wx, Ly, wy, D, d = gridpar hW, hE, hN, hS, hT, hB = hbound x = np.linspace(-Lx, Lx, int(2 * Lx / wx) + 1) y = np.linspace(-Ly, Ly, int(2 * Ly / wy) + 1) z = np.linspace(0, -D, int(D / d) + 1) gr = mfgrid.Grid(x, y, z) K = gr.const(k) # * np.random.rand(gr.Nod).reshape(gr.shape) FH = gr.const(0.) FQ = gr.const(0.) IBOUND = gr.const(1) if not (hW is None): IBOUND[:, 0, :] = -1 FH[:, 0, :] = hW if not hE is None: IBOUND[:, -1, :] = -1 FH[:, -1, :] = hE if not hN is None: IBOUND[0, :, :] = -1 FH[0, :, :] = hN if not hS is None: IBOUND[-1, :, :] = -1 FH[-1, :, :] = hS if not hT is None: IBOUND[:, :, 0] = -1 FH[:, :, 0] = hT if not hB is None: IBOUND[:, :, -1] = -1 FH[:, :, -1] = hB # Solve for the heads: Out = fdm.fdm3(gr, (K, K, K), FQ, FH, IBOUND) return Out, gr, IBOUND
xGr = np.logspace(-1, 4, 51) xGr = np.linspace(0, 2000, 101) yGr = np.array([-0.5, 0.5]) zGr = np.array([0., -5, -50, -60, -100]) gr = mfgrid.Grid(xGr, yGr, zGr, axial) IBOUND = gr.const(1) IBOUND[:, :, 0] = -1 # head in top confining unit fixed k = gr.const(np.array([0.01, 10., 0.01, 20.])) FH = gr.const(0.) FQ = gr.const(0.) FQ[0, 0, 1] = Q # insecond layer # run flow model Out = fdm.fdm3(gr, (k, k, k), FQ, FH, IBOUND) Psi = fdm.psi(Out.Qx) #pdb.set_trace() # visualize title = 'Cross section Axial={0}, Q={1} {2}'.format( axial, Q, 'm3/d' if axial else 'm2/d') ax = plt.figure().add_subplot(111) xlim = gr.x[[0, -1]] ax.set(xlabel='x [m]', ylabel=['z [m]'], title=title, xlim=xlim) ax.contour(gr.xm, gr.zm, Out.Phi[0].T, 30) ax.contour(gr.xp, gr.zp, Psi, 30) #plt.show()