コード例 #1
0
    def constrain(self, upper=None, lower=None):
        # Constraint can be set to none if we don't want to change
        constraints = (new if new is not None else old
                       for new, old in zip((upper, lower), self.constraints))
        faces = (self.mesh.facesLeft, self.mesh.facesRight)
        indexes = [0, -1]

        self._exterior_flux = 0

        for val, index, face in zip(constraints, indexes, faces):
            if val is None:
                continue
            try:
                self.var.constrain(val.into("K"),
                                   face)  ## Constrain as temperature
            except DimensionalityError:
                # Fixed flux boundary condition
                # flux density
                v = val.into("W/m^2")

                flux = F.FaceVariable(self.mesh, 'exterior_flux', value=v)

                self._exterior_flux += (self.mesh.exteriorFaces[index] *
                                        flux).divergence

            except AttributeError:
                pass
コード例 #2
0
	def createLinearMesh(self, sections, Acs, As): 
		""" Define mesh """
		# Cross sectional area
		self.AcsMult = Acs
		# Area multiplier for face area
		self.areaMult = Acs
		# Surface area per unit length
		self.As = As
		# Create the meshes and emissivity calculator for each segment
		self.emissivityCalculator = sm.SectionCalculator()
		dx = []		
		i = 0
		for sec in sections:
			numElements = np.ceil(sec['length'] / sec['meshSize'])			
			self.emissivityCalculator.addSection(
					(i, i + numElements - 1), 
					sm.Interpolator1D([sec['temperature1'], sec['temperature2']], [sec['emissivity1'], sec['emissivity2']])
			)
			dx += [sec['length'] / numElements] * numElements
			i += numElements
		self.radiation['emissivity'] = np.zeros((len(dx)))
		self.mesh = fp.Grid1D(dx = dx)
		self.meshType = 'Linear'
		# Define variable
		self.T = fp.CellVariable(name = "temperature",
			mesh = self.mesh, value = 0.)
		self.thermCond = fp.FaceVariable(mesh = self.mesh)
		self.emissivity = fp.CellVariable(mesh = self.mesh)
コード例 #3
0
def forwardEvo(phi, tStart, tEnd, path, saveResults):
    # Initialize step counter and evolution time
    step = 0
    tEvo = tStart
    # Extract cell centers and faces from mesh
    X, P = Mesh.cellCenters()
    xFace, pFace = Mesh.faceCenters()
    # Create plot for starting distribution
    target = 'forwardEvo-Step-' + '%05d' % step + '.png'
    genPlots(phi, tEvo, saveResults, target, path)
    # Continue to evolve distribution until specified end time
    while (tEvo < tEnd):
        # Find current spring constant and location of minimum
        kT = springConstant(tEvo)
        zT = potentialMinimum(tEvo)
        # Calculate time step size
        timeStepDuration = (1. /
                            (SubDiv * Nx)) * (1. /
                                              numpy.sqrt(1. / Tau**2 + kT))
        if (tEvo + timeStepDuration > tEnd):
            timeStepDuration = tEnd - tEvo
        # Create Diffusion Term
        gxx = numpy.zeros(X.shape)
        gxp = numpy.zeros(X.shape)
        gpx = numpy.zeros(X.shape)
        gpp = numpy.ones(X.shape) * (2. / Tau)
        dTerm = fipy.DiffusionTerm(
            fipy.CellVariable(mesh=Mesh, value=[[gxx, gxp], [gpx, gpp]]))
        del gxx, gxp, gpx, gpp
        # Create convection term
        uX = pFace
        uP = -kT * (xFace - zT) - (2. / Tau) * pFace
        cCoeff = fipy.FaceVariable(mesh=Mesh, value=[uX, uP])
        cTerm = fipy.ExponentialConvectionTerm(cCoeff)
        del uX, uP, cCoeff
        # Create evolution equation
        eq = fipy.TransientTerm() + cTerm == dTerm
        # Specify solver
        solver = fipy.solvers.pysparse.LinearLUSolver(tolerance=10**-15, \
                                                iterations=1000, precon=None)
        # Evolve system
        eq.solve(var=phi, dt=timeStepDuration, solver=solver)
        tEvo = tEvo + timeStepDuration
        step = step + 1
        # Check normalization for possible errors
        norm = fipy.numerix.sum(phi.value, axis=0) * Dx * Dp
        if (abs(norm - 1) > 10**(-13)):
            s1 = 'Distribution is no longer normalized.\n'
            s2 = 'Abs(1-Norm) = '
            s3 = repr(norm - 1.)
            raise RuntimeError(s1 + s2 + s3)
        del kT, zT, timeStepDuration, cTerm, eq, norm
        # Create plot of current distribution
        target = 'forwardEvo-Step-' + '%05d' % step + '.png'
        genPlots(phi, tEvo, saveResults, target, path)
    del tEvo, X, P, xFace, pFace
    return phi
コード例 #4
0
ファイル: hydro.py プロジェクト: Txart/blopti_dev
    def T_value(phi, ele, cmask, peat_bottom_arr):
        # Some inputs are in fipy CellVariable type
        gwt = (phi.value * cmask.value - ele).reshape(ny, nx)

        # T(h) - T(bottom)
        T = transmissivity(gwt, t0, t1, t2, t_sapric_coef) - transmissivity(
            peat_bottom_arr, t0, t1, t2, t_sapric_coef)

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        T[T < 0] = 1e-3  # Small non-zero value not to wreck the computation

        Tcell = fp.CellVariable(mesh=mesh, value=T.flatten(
        ))  # diffusion coefficient, transmissivity. As a cell variable.
        Tface = fp.FaceVariable(mesh=mesh,
                                value=Tcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return Tface.value
コード例 #5
0
ファイル: hydro.py プロジェクト: Txart/dosan_daily_map
    def D_value(phi, ele, tra_to_cut, cmask, drmask_not):
        # Some inputs are in fipy CellVariable type
        gwt = phi.value * cmask.value - ele

        d = hydro_utils.peat_map_h_to_tra(
            soil_type_mask=peat_type_mask, gwt=gwt,
            h_to_tra_and_C_dict=httd) - tra_to_cut

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        d[d < 0] = 1e-3  # Small non-zero value not to wreck the computation

        dcell = fp.CellVariable(
            mesh=mesh, value=d
        )  # diffusion coefficient, transmissivity. As a cell variable.
        dface = fp.FaceVariable(mesh=mesh,
                                value=dcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return dface.value
コード例 #6
0
ファイル: fipy_module.py プロジェクト: wd15/sfepy-bm4
def get_vars(params, set_eta, mesh):
    """Get the variables

    Args:
      params: the parameter dict
      set_eta: function to set the initial value of the phase field
      mesh: the FiPy mesh

    Returns:
      a dictionary of the variables (eta, d2f)
    """
    return pipe(
        dict(
            eta=fp.CellVariable(mesh=mesh,
                                hasOld=True,
                                value=params["eta0"],
                                name="eta"),
            d2f=fp.FaceVariable(mesh=mesh, name="d2f"),
        ),
        do(set_eta(params, mesh)),
    )
コード例 #7
0
def test_steady_state():
    """
    Test that we can create a steady-state model using
    FiPy that is similar to that given by our 'naive' solver
    """
    continental_crust.heat_generation = u(1, 'mW/m^3')
    _ = continental_crust.to_layer(u(3000, 'm'))
    section = Section([_])

    heatflow = u(15, 'mW/m^2')
    surface_temperature = u(0, 'degC')

    m = continental_crust
    q = heatflow
    k = m.conductivity
    a = m.heat_generation
    Cp = m.specific_heat
    rho = m.density

    def simple_heat_flow(x):
        # Density and heat capacity matter don't matter in steady-state
        T0 = surface_temperature
        return T0.to('K') + q * x / k + a / (2 * k) * x**2

    p = simple_heat_flow(section.cell_centers)
    dx = section.cell_sizes[0]
    test_profile = p.into('degC')

    grad = (-q / k).into('K/m')
    # Divergence
    div = (-a / k).into('K/m^2')

    a_ = -N.gradient(N.gradient(test_profile, dx), dx)
    assert all(a_ < 0)
    assert N.allclose(a_.min(), div)

    res = steady_state(section, heatflow, surface_temperature)
    profile = res.profile.into('degC')

    assert N.allclose(test_profile, profile)

    solver = FiniteSolver(_)
    solver.constrain(surface_temperature, None)
    solver.constrain(heatflow, None)

    res2 = solver.steady_state()
    # Make sure it's nonlinear and has constant 2nd derivative
    arr = solver.var.faceGrad.divergence.value
    assert N.allclose(sum(arr - arr[0]), 0)
    assert N.allclose(arr.mean(), div)

    # Test simple finite element model
    mesh = F.Grid1D(nx=section.n_cells, dx=section.cell_sizes[0].into('m'))
    T = F.CellVariable(name="Temperature", mesh=mesh)
    T.constrain(surface_temperature.into("K"), mesh.facesLeft)
    A = F.FaceVariable(mesh=mesh, value=m.diffusivity.into("m**2/s"))
    rad_heat = F.CellVariable(mesh=mesh, value=(a / Cp / rho).into("K/s"))

    D = F.DiffusionTerm(coeff=A) + F.ImplicitSourceTerm(coeff=rad_heat)
    sol = D.solve(var=T)
    val = T.faceGrad.divergence.value
    arr = T.value - 273.15
    #assert N.allclose(val.mean(), div)
    assert N.allclose(test_profile, arr)

    P = res2.profile.into('degC')
    assert N.allclose(test_profile, P)
コード例 #8
0
pressureRelaxation = 0.8
velocityRelaxation = 0.5

meshmodule = import_module("mesh{}".format(params["problem"]))

(mesh, inlet, outlet, walls,
 top_right) = meshmodule.mesh_and_boundaries(params)

volumes = fp.CellVariable(mesh=mesh, value=mesh.cellVolumes)

pressure = fp.CellVariable(mesh=mesh, name="$p$")
pressureCorrection = fp.CellVariable(mesh=mesh, name="$p'$")
xVelocity = fp.CellVariable(mesh=mesh, name="$u_x$")
yVelocity = fp.CellVariable(mesh=mesh, name="$u_y$")

velocity = fp.FaceVariable(mesh=mesh, name=r"$\vec{u}$", rank=1)

xVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot(
    [[1.], [0.]]) + density * gravity[0]
yVelocityEq = fp.DiffusionTerm(coeff=viscosity) - pressure.grad.dot(
    [[0.], [1.]]) + density * gravity[1]

ap = fp.CellVariable(mesh=mesh, value=1.)
coeff = 1. / ap.arithmeticFaceValue * mesh._faceAreas * mesh._cellDistances

x, y = mesh.cellCenters
top_right_cell = fp.CellVariable(mesh=mesh,
                                 value=(x > max(x) - params["cellSize"]) &
                                 (y > max(y) - params["cellSize"]))

large_value = 1e10
コード例 #9
0
ファイル: hydro.py プロジェクト: Txart/dosan_daily_map
def hydrology(solve_mode,
              nx,
              ny,
              dx,
              dy,
              days,
              ele,
              phi_initial,
              catchment_mask,
              wt_canal_arr,
              boundary_arr,
              peat_type_mask,
              httd,
              tra_to_cut,
              sto_to_cut,
              diri_bc=0.0,
              neumann_bc=None,
              plotOpt=False,
              remove_ponding_water=True,
              P=0.0,
              ET=0.0,
              dt=1.0):
    """
    INPUT:
        - ele: (nx,ny) sized NumPy array. Elevation in m above c.r.p.
        - Hinitial: (nx,ny) sized NumPy array. Initial water table in m above c.r.p.
        - catchment mask: (nx,ny) sized NumPy array. Boolean array = True where the node is inside the computation area. False if outside.
        - wt_can_arr: (nx,ny) sized NumPy array. Zero everywhere except in nodes that contain canals, where = wl of the canal.
        - value_for_masked: DEPRECATED. IT IS NOW THE SAME AS diri_bc.
        - diri_bc: None or float. If None, Dirichlet BC will not be implemented. If float, this number will be the BC.
        - neumann_bc: None or float. If None, Neumann BC will not be implemented. If float, this is the value of grad phi.
        - P: Float. Constant precipitation. mm/day.
        - ET: Float. Constant evapotranspiration. mm/day.
    """
    #    dneg = []

    track_WT_drained_area = (239, 166)
    track_WT_notdrained_area = (522, 190)

    ele[~catchment_mask] = 0.
    ele = ele.flatten()
    phi_initial = (phi_initial + 0.0 * np.zeros((ny, nx))) * catchment_mask
    #    phi_initial = phi_initial * catchment_mask
    phi_initial = phi_initial.flatten()

    if len(ele) != nx * ny or len(phi_initial) != nx * ny:
        raise ValueError("ele or Hinitial are not of dim nx*ny")

    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    phi = fp.CellVariable(
        name='computed H', mesh=mesh, value=phi_initial,
        hasOld=True)  #response variable H in meters above reference level

    if diri_bc != None and neumann_bc == None:
        phi.constrain(diri_bc, mesh.exteriorFaces)

    elif diri_bc == None and neumann_bc != None:
        phi.faceGrad.constrain(neumann_bc * mesh.faceNormals,
                               where=mesh.exteriorFaces)

    else:
        raise ValueError(
            "Cannot apply Dirichlet and Neumann boundary values at the same time. Contradictory values."
        )

    #*******omit areas outside the catchment. c is input
    cmask = fp.CellVariable(mesh=mesh, value=np.ravel(catchment_mask))
    cmask_not = fp.CellVariable(mesh=mesh,
                                value=np.array(~cmask.value, dtype=int))

    # *** drain mask or canal mask
    dr = np.array(wt_canal_arr, dtype=bool)
    dr[np.array(wt_canal_arr, dtype=bool) * np.array(
        boundary_arr, dtype=bool
    )] = False  # Pixels cannot be canals and boundaries at the same time. Everytime a conflict appears, boundaries win. This overwrites any canal water level info if the canal is in the boundary.
    drmask = fp.CellVariable(mesh=mesh, value=np.ravel(dr))
    drmask_not = fp.CellVariable(
        mesh=mesh, value=np.array(~drmask.value, dtype=int)
    )  # Complementary of the drains mask, but with ints {0,1}

    # mask away unnecesary stuff
    #    phi.setValue(np.ravel(H)*cmask.value)
    #    ele = ele * cmask.value

    source = fp.CellVariable(mesh=mesh,
                             value=0.)  # cell variable for source/sink

    #    CC=fp.CellVariable(mesh=mesh, value=C(phi.value-ele))                   # differential water capacity

    def D_value(phi, ele, tra_to_cut, cmask, drmask_not):
        # Some inputs are in fipy CellVariable type
        gwt = phi.value * cmask.value - ele

        d = hydro_utils.peat_map_h_to_tra(
            soil_type_mask=peat_type_mask, gwt=gwt,
            h_to_tra_and_C_dict=httd) - tra_to_cut

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        d[d < 0] = 1e-3  # Small non-zero value not to wreck the computation

        dcell = fp.CellVariable(
            mesh=mesh, value=d
        )  # diffusion coefficient, transmissivity. As a cell variable.
        dface = fp.FaceVariable(mesh=mesh,
                                value=dcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return dface.value

    def C_value(phi, ele, sto_to_cut, cmask, drmask_not):
        # Some inputs are in fipy CellVariable type
        gwt = phi.value * cmask.value - ele

        c = hydro_utils.peat_map_h_to_sto(
            soil_type_mask=peat_type_mask, gwt=gwt,
            h_to_tra_and_C_dict=httd) - sto_to_cut
        c[c < 0] = 1e-3  # Same reasons as for D

        ccell = fp.CellVariable(
            mesh=mesh, value=c
        )  # diffusion coefficient, transmissivity. As a cell variable.
        return ccell.value

    D = fp.FaceVariable(
        mesh=mesh, value=D_value(phi, ele, tra_to_cut, cmask,
                                 drmask_not))  # THe correct Face variable.
    C = fp.CellVariable(
        mesh=mesh, value=C_value(phi, ele, sto_to_cut, cmask,
                                 drmask_not))  # differential water capacity

    largeValue = 1e20  # value needed in implicit source term to apply internal boundaries

    if plotOpt:
        big_4_raster_plot(
            title='Before the computation',
            raster1=(
                (hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask,
                                               gwt=(phi.value - ele),
                                               h_to_tra_and_C_dict=httd) -
                 tra_to_cut) * cmask.value * drmask_not.value).reshape(ny, nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))
        # for later cross-section plots
        y_value = 270

#        print "first cross-section plot"
#        ele_with_can = copy.copy(ele).reshape(ny,nx)
#        ele_with_can = ele_with_can * catchment_mask
#        ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
#        plot_line_of_peat(ele_with_can, y_value=y_value, title="cross-section", color='green', nx=nx, ny=ny, label="ele")

# ********************************** PDE, STEADY STATE **********************************
    if solve_mode == 'steadystate':
        if diri_bc != None:
            #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc)))

            eq = 0. == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * np.ravel(boundary_arr) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                    - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
            )

        elif neumann_bc != None:
            raise NotImplementedError("Neumann BC not implemented yet!")
            cmask_face = fp.FaceVariable(mesh=mesh,
                                         value=np.array(
                                             cmask.arithmeticFaceValue.value,
                                             dtype=bool))
            D[cmask_face.value] = 0.
            eq = 0. == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * (diri_bc) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                + fp.DiffusionTerm(coeff=largeValue * bmask_face)
                #                - fp.ImplicitSourceTerm((bmask_face * largeValue *neumann_bc * mesh.faceNormals).divergence)
            )

    elif solve_mode == 'transient':
        if diri_bc != None:
            #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc)))

            eq = fp.TransientTerm(coeff=C) == (
                fp.DiffusionTerm(coeff=D) + source * cmask * drmask_not -
                fp.ImplicitSourceTerm(cmask_not * largeValue) +
                cmask_not * largeValue * np.ravel(boundary_arr) -
                fp.ImplicitSourceTerm(drmask * largeValue) +
                drmask * largeValue * (np.ravel(wt_canal_arr))
                #                        - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
            )
        elif neumann_bc != None:
            raise NotImplementedError("Neumann BC not implemented yet!")

    #********************************************************

    max_sweeps = 10  # inner loop.

    avg_wt = []
    wt_track_drained = []
    wt_track_notdrained = []

    cumulative_Vdp = 0.

    #********Finite volume computation******************
    for d in range(days):
        source.setValue(
            (P[d] - ET[d]) * .001 * np.ones(ny * nx)
        )  # source/sink. P and ET are in mm/day. The factor of 10^-3 converst to m/day. It does not matter that there are 100 x 100 m^2 in one pixel
        print("(d, P - ET) = ", (d, (P[d] - ET[d])))
        if plotOpt and d != 0:
            # print "one more cross-section plot"
            plot_line_of_peat(phi.value.reshape(ny, nx),
                              y_value=y_value,
                              title="cross-section",
                              color='cornflowerblue',
                              nx=nx,
                              ny=ny,
                              label=d)

        res = 0.0

        phi.updateOld()

        D.setValue(D_value(phi, ele, tra_to_cut, cmask, drmask_not))
        C.setValue(C_value(phi, ele, tra_to_cut, cmask, drmask_not))

        for r in range(max_sweeps):
            resOld = res

            res = eq.sweep(var=phi, dt=dt)  # solve linearization of PDE

            #print "sum of Ds: ", np.sum(D.value)/1e8
            #print "average wt: ", np.average(phi.value-ele)

            #print 'residue diference:    ', res - resOld

            if abs(res - resOld) < 1e-7:
                break  # it has reached to the solution of the linear system

        if solve_mode == 'transient':  #solving in steadystate will remove water only at the very end
            if remove_ponding_water:
                s = np.where(
                    phi.value > ele, ele, phi.value
                )  # remove the surface water. This also removes phi in those masked values (for the plot only)
                phi.setValue(s)  # set new values for water table

        if (D.value < 0.).any():
            print("Some value in D is negative!")

        # For some plots
        avg_wt.append(np.average(phi.value - ele))
        wt_track_drained.append(
            (phi.value - ele).reshape(ny, nx)[track_WT_drained_area])
        wt_track_notdrained.append(
            (phi.value - ele).reshape(ny, nx)[track_WT_notdrained_area])
        """ Volume of dry peat calc."""
        not_peat = np.ones(shape=peat_type_mask.shape)  # Not all soil is peat!
        not_peat[peat_type_mask == 4] = 0  # NotPeat
        not_peat[peat_type_mask == 5] = 0  # OpenWater
        peat_vol_weights = utilities.PeatV_weight_calc(
            np.array(~dr * catchment_mask * not_peat, dtype=int))
        dry_peat_volume = utilities.PeatVolume(peat_vol_weights,
                                               (ele - phi.value).reshape(
                                                   ny, nx))
        cumulative_Vdp = cumulative_Vdp + dry_peat_volume
        print("avg_wt  = ", np.average(phi.value - ele))
        #        print "wt drained = ", (phi.value - ele).reshape(ny,nx)[track_WT_drained_area]
        #        print "wt not drained = ", (phi.value - ele).reshape(ny,nx)[track_WT_notdrained_area]
        print("Cumulative vdp = ", cumulative_Vdp)

    if solve_mode == 'steadystate':  #solving in steadystate we remove water only at the very end
        if remove_ponding_water:
            s = np.where(
                phi.value > ele, ele, phi.value
            )  # remove the surface water. This also removes phi in those masked values (for the plot only)
            phi.setValue(s)  # set new values for water table

        # Areas with WT <-1.0; areas with WT >0
#        plot_raster_by_value((ele-phi.value).reshape(ny,nx), title="ele-phi in the end, colour keys", bottom_value=0.5, top_value=0.01)

    if plotOpt:
        big_4_raster_plot(
            title='After the computation',
            raster1=(
                (hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask,
                                               gwt=(phi.value - ele),
                                               h_to_tra_and_C_dict=httd) -
                 tra_to_cut) * cmask.value * drmask_not.value).reshape(ny, nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))

        fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12, 9), dpi=80)
        x = np.arange(-21, 1, 0.1)
        axes[0, 0].plot(httd[1]['hToTra'](x), x)
        axes[0, 0].set(title='hToTra', ylabel='depth')
        axes[0, 1].plot(httd[1]['C'](x), x)
        axes[0, 1].set(title='C')
        axes[1, 0].plot()
        axes[1, 0].set(title="Nothing")
        axes[1, 1].plot(avg_wt)
        axes[1, 1].set(title="avg_wt_over_time")

        # plot surface in cross-section
        ele_with_can = copy.copy(ele).reshape(ny, nx)
        ele_with_can = ele_with_can * catchment_mask
        ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
        plot_line_of_peat(ele_with_can,
                          y_value=y_value,
                          title="cross-section",
                          nx=nx,
                          ny=ny,
                          label="surface",
                          color='peru',
                          linewidth=2.0)

        plt.show()

#    change_in_canals = (ele-phi.value).reshape(ny,nx)*(drmask.value.reshape(ny,nx)) - ((ele-H)*drmask.value).reshape(ny,nx)
#    resulting_phi = phi.value.reshape(ny,nx)

    phi.updateOld()

    return (phi.value - ele).reshape(ny, nx)
コード例 #10
0
	def QAx(self):
		return fp.FaceVariable(mesh = self.mesh, value = - self.thermCond * self.areaMult * self.mesh.scaledFaceAreas * self.T.faceGrad)	
コード例 #11
0
def model_heat_transport(Lx, Ly, alpha, beta, Lxmin, cellsize_wedge_top, cellsize_wedge_bottom, cellsize_footwall, 
                         vd, vc, vxa, vya, v_downgoing, 
                         sea_lvl_temp, lapse_rate, lab_temp, K, rho, c, H0, e_folding_depth):
    
    """
    model heat transport using Fipy
    """
        
    # create mesh
    mesh = create_rectangle_mesh_with_fault(Lx, Ly, alpha, beta, Lxmin, cellsize_wedge_top, cellsize_wedge_bottom, cellsize_footwall)

    # get mesh coordinates
    xyc = mesh.cellCenters()
    xyf = mesh.faceCenters()

    # calculate elevation and depth
    surface_elev = xyc[0] * alpha
    surface_elev_f = xyf[0] * alpha

    a = surface_elev < 0
    surface_elev[a] = 0.0

    b = surface_elev_f < 0
    surface_elev_f[b] = 0.0

    depth = surface_elev - xyc[1]
    depthf = surface_elev_f - xyf[1]

    wedge = xyc[1] >= (xyc[0] * beta)
    non_wedge = xyc[1]  < (xyc[0] * beta)
    below_wedge = non_wedge * xyc[0] >= 0
    outside_wedge = xyc[0] < 0

    wedge_f = xyf[1] >= (xyf[0] * beta)
    non_wedge_f = wedge_f == False
    below_wedge_f = non_wedge_f * (xyf[0] >= 0)
    outside_wedge_f = xyf[0] < 0

    # calculate heat production
    hp_exp = 1.0 / e_folding_depth
    HP = H0 * np.exp(-hp_exp * depth)

    # set up variable for advection
    q = fipy.FaceVariable(mesh=mesh, rank=1)

    # calcuate advection rates in wedge
    vxc = horizontal_compression_velocity(xyf[0], vc, Lx)
    vyc = vertical_compression_velocity(xyf[0], xyf[1], vc, alpha, beta, Lx)
    vxt = vd + vxa
    vyt = beta * vd + vya

    vx = vxc + vxt
    vy = vyc + vyt

    q[0] = wedge_f * vx
    q[1] = wedge_f * vy

    # calculate advection rates below wedge
    wedge_angle = np.arctan(beta)

    vx_downgoing = v_downgoing * np.cos(wedge_angle)
    vy_downgoing = v_downgoing * np.sin(wedge_angle)

    # set velocity in front of wedge
    q[0] = q[0] + outside_wedge_f * v_downgoing

    # set velocity below wedge
    q[0] = q[0] + below_wedge_f * vx_downgoing
    q[1] = q[1] + below_wedge_f * vy_downgoing

    # set up temperature variable
    T = fipy.CellVariable(mesh=mesh, name='T')

    # boudnary conditions
    surface_nodes = depthf <= 1.0
    bottom_nodes = ((xyf[0] <= 0) & (np.abs(depthf - Ly) < 1.0)) | ((xyf[0] > 0) & (np.abs(xyf[1] - (beta*xyf[0] - Ly)) < 1.0))

    surface_temp_variable = sea_lvl_temp + xyf[1] * lapse_rate

    #T.constrain(surface_temp_variable, mesh.physicalFaces['surface'])
    T.constrain(surface_temp_variable, surface_nodes)
    #T.constrain(lab_temp, mesh.physicalFaces['bottom'])
    T.constrain(lab_temp, bottom_nodes)

    # constrain flux at lateral boundaries. for some reason zero-flux not automatically enforced by fipy in this case.
    T.faceGrad.constrain([0.0], mesh.facesRight)
    T.faceGrad.constrain([0.0], mesh.facesLeft)

    # coefficients
    k = K / (rho * c)
    HP_adj = HP / (rho * c)

    # set up equation
    diffTerm = fipy.DiffusionTerm(coeff=k) 
    sourceTerm  =  fipy.CellVariable(mesh=mesh,  value=HP_adj)
    #sourceTerm_v2  =  fipy.ImplicitSourceTerm(HP_adj)

    #convTerm = fipy.ExponentialConvectionTerm(coeff=q)
    convTerm = fipy.PowerLawConvectionTerm(coeff=q)
    #convTerm = fipy.UpwindConvectionTerm(coeff=q)

    eq = (diffTerm == convTerm - sourceTerm)

    # solve eequation
    solver = fipy.solvers.LinearGMRESSolver(tolerance=1e-20, iterations=10000)
    eq.solve(var=T, solver=solver)

    # convert result to arrays
    T_array = T(mesh.cellCenters.globalValue)
    x, y = mesh.cellCenters.globalValue
    
    #q_array = q(mesh.cellCenters.globalValue)

    return x, y, T_array, q, mesh
コード例 #12
0
 def QAx(self):
     return fp.FaceVariable(mesh=self.mesh,
                            value=-self.thermalConductivity * self.AcsMult *
                            self.mesh.scaledFaceAreas * self.TCore.faceGrad)
コード例 #13
0
ファイル: HeatExchangerSolver.py プロジェクト: birdol/SmoWeb
    def solve(self, heatExch):
        # Create variables for temperature and thermal conductivity
        self.T = FP.CellVariable(name='T', mesh=self.mesh)
        self.thermCond = FP.FaceVariable(name='lambda', mesh=self.mesh)
        # Create the coefficient for the source terms emulating boundary conditions
        self.cPrimCoeff = (self.primChannels *
                           self.mesh.faceNormals).divergence
        self.cSecCoeff = (self.secChannels * self.mesh.faceNormals).divergence
        self.cExtCoeff = (self.extChannel * self.mesh.faceNormals).divergence

        # Initial guess
        self.T.setValue(heatExch.externalFlowIn.T)
        self.primChannelCalc.sections[0].fState.update_Tp(
            heatExch.primaryFlowIn.T, heatExch.primaryFlowIn.p)
        self.secChannelCalc.sections[0].fState.update_Tp(
            heatExch.secondaryFlowIn.T, heatExch.secondaryFlowIn.p)
        self.extChannelCalc.sections[0].fState.update_Tp(
            heatExch.externalFlowIn.T, heatExch.externalFlowIn.p)
        # Solve for a single cross section
        for i in range(self.numSectionSteps):
            heatExch.updateProgress((i + 1.0) / self.numSectionSteps, 1.)
            primSection = self.primChannelCalc.sections[i]
            secSection = self.secChannelCalc.sections[i]
            extSection = self.extChannelCalc.sections[i]
            # Compute convection coefficients
            primSection.computeConvectionCoefficient()
            secSection.computeConvectionCoefficient()
            extSection.computeConvectionCoefficient()
            # Run FV solver
            TPrim = primSection.fState.T
            TSec = secSection.fState.T
            TExt = extSection.fState.T
            self.solveSectionThermal(TPrim=TPrim,
                                     hConvPrim=primSection.hConv,
                                     TSec=TSec,
                                     hConvSec=secSection.hConv,
                                     TExt=TExt,
                                     hConvExt=extSection.hConv)
            # 			self.checkResults(
            # 				TPrim = TPrim, hConvPrim = primSection.hConv,
            # 				TSec = TSec, hConvSec = secSection.hConv,
            # 				TExt = TExt, hConvExt = extSection.hConv)
            # Compute average channel wall temperatures
            TFaces = self.T.arithmeticFaceValue()
            TPrimWall = self.getFaceAverage(TFaces, self.primChannels)
            TSecWall = self.getFaceAverage(TFaces, self.secChannels)
            TExtWall = self.getFaceAverage(TFaces, self.extChannel)
            primSection.TWall = TPrimWall
            secSection.TWall = TSecWall
            extSection.TWall = TExtWall
            # Compute heat fluxes and new temperatures
            if (i < self.numSectionSteps - 1):
                primSection.computeExitState(
                    self.primChannelCalc.sections[i + 1].fState)
                secSection.computeExitState(
                    self.secChannelCalc.sections[i + 1].fState)
                extSection.computeExitState(
                    self.extChannelCalc.sections[i + 1].fState)
            else:
                primSection.computeExitState(self.primChannelStateOut)
                secSection.computeExitState(self.secChannelStateOut)
                extSection.computeExitState(self.extChannelStateOut)
            # Make a section result plot
            if (i == 0 or (i - self.lastPlotPos) >=
                    float(self.numSectionSteps) / self.numPlots
                    or i == self.numSectionSteps - 1):
                if (self.currPlot <= self.numPlots):
                    ax = heatExch.__getattr__('sectionPlot%d' % self.currPlot)
                    ax.set_aspect('equal')
                    ax.set_title('Section at x=%g' % primSection.xStart)
                    if (heatExch.sectionResultsSettings.setTRange):
                        self.plotSolution(
                            heatExch,
                            ax,
                            self.T,
                            zmin=heatExch.sectionResultsSettings.Tmin,
                            zmax=heatExch.sectionResultsSettings.Tmax)
                    else:
                        self.plotSolution(heatExch, ax, self.T)
                    self.currPlot += 1
                    self.lastPlotPos = i
コード例 #14
0
ファイル: hydro.py プロジェクト: Txart/blopti_dev
def hydrology(mode,
              sensor_positions,
              nx,
              ny,
              dx,
              dy,
              days,
              ele,
              phi_initial,
              catchment_mask,
              wt_canal_arr,
              boundary_arr,
              peat_type_mask,
              peat_bottom_arr,
              transmissivity,
              t0,
              t1,
              t2,
              t_sapric_coef,
              storage,
              s0,
              s1,
              s2,
              s_sapric_coef,
              diri_bc=0.0,
              plotOpt=False,
              remove_ponding_water=True,
              P=0.0,
              ET=0.0,
              dt=1.0):
    """
    INPUT:
        - ele: (nx,ny) sized NumPy array. Elevation in m above c.r.p.
        - Hinitial: (nx,ny) sized NumPy array. Initial water table in m above c.r.p.
        - catchment mask: (nx,ny) sized NumPy array. Boolean array = True where the node is inside the computation area. False if outside.
        - wt_can_arr: (nx,ny) sized NumPy array. Zero everywhere except in nodes that contain canals, where = wl of the canal.
        - value_for_masked: DEPRECATED. IT IS NOW THE SAME AS diri_bc.
        - diri_bc: None or float. If None, Dirichlet BC will not be implemented. If float, this number will be the BC.
        - neumann_bc: None or float. If None, Neumann BC will not be implemented. If float, this is the value of grad phi.
        - P: Float. Constant precipitation. mm/day.
        - ET: Float. Constant evapotranspiration. mm/day.
    """
    #    dneg = []

    # track_WT_drained_area = (239,166)
    # track_WT_notdrained_area = (522,190)

    ele[~catchment_mask] = 0.
    ele = ele.flatten()
    phi_initial = (phi_initial + 0.0 * np.zeros((ny, nx))) * catchment_mask
    #    phi_initial = phi_initial * catchment_mask
    phi_initial = phi_initial.flatten()

    if len(ele) != nx * ny or len(phi_initial) != nx * ny:
        raise ValueError("ele or Hinitial are not of dim nx*ny")

    mesh = fp.Grid2D(dx=dx, dy=dy, nx=nx, ny=ny)
    phi = fp.CellVariable(
        name='computed H', mesh=mesh, value=phi_initial,
        hasOld=True)  #response variable H in meters above reference level

    if diri_bc != None:
        phi.constrain(diri_bc, mesh.exteriorFaces)

    else:
        raise ValueError("Dirichlet boundary conditions must have a value")

    #*******omit areas outside the catchment. c is input
    cmask = fp.CellVariable(mesh=mesh, value=np.ravel(catchment_mask))
    cmask_not = fp.CellVariable(mesh=mesh,
                                value=np.array(~cmask.value, dtype=int))

    # *** drain mask or canal mask
    dr = np.array(wt_canal_arr, dtype=bool)
    dr[np.array(wt_canal_arr, dtype=bool) * np.array(
        boundary_arr, dtype=bool
    )] = False  # Pixels cannot be canals and boundaries at the same time. Everytime a conflict appears, boundaries win. This overwrites any canal water level info if the canal is in the boundary.
    drmask = fp.CellVariable(mesh=mesh, value=np.ravel(dr))
    drmask_not = fp.CellVariable(
        mesh=mesh, value=np.array(~drmask.value, dtype=int)
    )  # Complementary of the drains mask, but with ints {0,1}

    # mask away unnecesary stuff
    #    phi.setValue(np.ravel(H)*cmask.value)
    #    ele = ele * cmask.value

    source = fp.CellVariable(mesh=mesh,
                             value=0.)  # cell variable for source/sink

    #    CC=fp.CellVariable(mesh=mesh, value=C(phi.value-ele))                   # differential water capacity

    def T_value(phi, ele, cmask, peat_bottom_arr):
        # Some inputs are in fipy CellVariable type
        gwt = (phi.value * cmask.value - ele).reshape(ny, nx)

        # T(h) - T(bottom)
        T = transmissivity(gwt, t0, t1, t2, t_sapric_coef) - transmissivity(
            peat_bottom_arr, t0, t1, t2, t_sapric_coef)

        # d <0 means tra_to_cut is greater than the other transmissivity, which in turn means that
        # phi is below the impermeable bottom. We allow phi to have those values, but
        # the transmissivity is in those points is equal to zero (as if phi was exactly at the impermeable bottom).
        T[T < 0] = 1e-3  # Small non-zero value not to wreck the computation

        Tcell = fp.CellVariable(mesh=mesh, value=T.flatten(
        ))  # diffusion coefficient, transmissivity. As a cell variable.
        Tface = fp.FaceVariable(mesh=mesh,
                                value=Tcell.arithmeticFaceValue.value
                                )  # THe correct Face variable.

        return Tface.value

    def S_value(phi, ele, cmask, peat_bottom_arr):
        # Some inputs are in fipy CellVariable type
        gwt = (phi.value * cmask.value - ele).reshape(ny, nx)

        S = storage(gwt, s0, s1, s2, s_sapric_coef) - storage(
            peat_bottom_arr, s0, s1, s2, s_sapric_coef)
        S[S < 0] = 1e-3  # Same reasons as for D

        Scell = fp.CellVariable(mesh=mesh, value=S.flatten(
        ))  # diffusion coefficient, transmissivity. As a cell variable.
        return Scell.value

    T = fp.FaceVariable(mesh=mesh,
                        value=T_value(
                            phi, ele, cmask,
                            peat_bottom_arr))  # THe correct Face variable.
    S = fp.CellVariable(mesh=mesh,
                        value=S_value(
                            phi, ele, cmask,
                            peat_bottom_arr))  # differential water capacity

    largeValue = 1e20  # value needed in implicit source term to apply internal boundaries

    if plotOpt:
        big_4_raster_plot(
            title='Before the computation',
            # raster1=((hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask, gwt=(phi.value - ele), h_to_tra_and_C_dict=httd) - tra_to_cut)*cmask.value *drmask_not.value ).reshape(ny,nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))
        # for later cross-section plots
        y_value = 270
    """
    ###### PDE ######
    """

    if mode == 'steadystate':
        temp = 0.
    elif mode == 'transient':
        temp = fp.TransientTerm(coeff=S)

    if diri_bc != None:
        #        diri_boundary = fp.CellVariable(mesh=mesh, value= np.ravel(diri_boundary_value(boundary_mask, ele2d, diri_bc))
        eq = temp == (
            fp.DiffusionTerm(coeff=T) + source * cmask * drmask_not -
            fp.ImplicitSourceTerm(cmask_not * largeValue) +
            cmask_not * largeValue * np.ravel(boundary_arr) -
            fp.ImplicitSourceTerm(drmask * largeValue) + drmask * largeValue *
            (np.ravel(wt_canal_arr))
            #                        - fp.ImplicitSourceTerm(bmask_not*largeValue) + bmask_not*largeValue*(boundary_arr)
        )

    #********************************************************

    max_sweeps = 10  # inner loop.

    avg_wt = []
    # wt_track_drained = []
    # wt_track_notdrained = []

    cumulative_Vdp = 0.

    #********Finite volume computation******************
    for d in range(days):

        if type(P) == type(ele):  # assume it is a numpy array
            source.setValue(
                (P[d] - ET[d]) * .001 * np.ones(ny * nx)
            )  # source/sink, in mm/day. The factor of 10^-3 takes into account that there are 100 x 100 m^2 in one pixel
            # print("(d,P) = ", (d, (P[d]-ET[d])* 10.))
        else:
            source.setValue((P - ET) * 10. * np.ones(ny * nx))
            # print("(d,P) = ", (d, (P-ET)* 10.))

        if plotOpt and d != 0:
            # print "one more cross-section plot"
            plot_line_of_peat(phi.value.reshape(ny, nx),
                              y_value=y_value,
                              title="cross-section",
                              color='cornflowerblue',
                              nx=nx,
                              ny=ny,
                              label=d)

        res = 0.0

        phi.updateOld()

        T.setValue(T_value(phi, ele, cmask, peat_bottom_arr))
        S.setValue(S_value(phi, ele, cmask, peat_bottom_arr))

        for r in range(max_sweeps):
            resOld = res

            res = eq.sweep(var=phi, dt=dt)  # solve linearization of PDE

            #print "sum of Ds: ", np.sum(D.value)/1e8
            #print "average wt: ", np.average(phi.value-ele)

            #print 'residue diference:    ', res - resOld

            if abs(res - resOld) < 1e-7:
                break  # it has reached to the solution of the linear system

        if remove_ponding_water:
            s = np.where(
                phi.value > ele, ele, phi.value
            )  # remove the surface water. This also removes phi in those masked values (for the plot only)
            phi.setValue(s)  # set new values for water table

        if (T.value < 0.).any():
            print("Some value in D is negative!")

        # For some plots
        avg_wt.append(np.average(phi.value - ele))
        # wt_track_drained.append((phi.value - ele).reshape(ny,nx)[track_WT_drained_area])
        # wt_track_notdrained.append((phi.value - ele).reshape(ny,nx)[track_WT_notdrained_area])
        """ Volume of dry peat calc."""
        not_peat = np.ones(shape=peat_type_mask.shape)  # Not all soil is peat!
        not_peat[peat_type_mask == 4] = 0  # NotPeat
        not_peat[peat_type_mask == 5] = 0  # OpenWater
        peat_vol_weights = utilities.PeatV_weight_calc(
            np.array(~dr * catchment_mask * not_peat, dtype=int))
        dry_peat_volume = utilities.PeatVolume(peat_vol_weights,
                                               (ele - phi.value).reshape(
                                                   ny, nx))
        cumulative_Vdp = cumulative_Vdp + dry_peat_volume

    if plotOpt:
        big_4_raster_plot(
            title='After the computation',
            # raster1=((hydro_utils.peat_map_h_to_tra(soil_type_mask=peat_type_mask, gwt=(phi.value - ele), h_to_tra_and_C_dict=httd) - tra_to_cut)*cmask.value *drmask_not.value ).reshape(ny,nx),
            raster2=(ele.reshape(ny, nx) - wt_canal_arr) * dr * catchment_mask,
            raster3=ele.reshape(ny, nx),
            raster4=(ele - phi.value).reshape(ny, nx))

        # fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12,9), dpi=80)
        # x = np.arange(-21,1,0.1)
        # axes[0,0].plot(httd[1]['hToTra'](x),x)
        # axes[0,0].set(title='hToTra', ylabel='depth')
        # axes[0,1].plot(httd[1]['C'](x),x)
        # axes[0,1].set(title='C')
        # axes[1,0].plot()
        # axes[1,0].set(title="Nothing")
        # axes[1,1].plot(avg_wt)
        # axes[1,1].set(title="avg_wt_over_time")

        # # plot surface in cross-section
        # ele_with_can = copy.copy(ele).reshape(ny,nx)
        # ele_with_can = ele_with_can * catchment_mask
        # ele_with_can[wt_canal_arr > 0] = wt_canal_arr[wt_canal_arr > 0]
        # plot_line_of_peat(ele_with_can, y_value=y_value, title="cross-section", nx=nx, ny=ny, label="surface", color='peru', linewidth=2.0)

        # plt.show()

#    change_in_canals = (ele-phi.value).reshape(ny,nx)*(drmask.value.reshape(ny,nx)) - ((ele-H)*drmask.value).reshape(ny,nx)
#    resulting_phi = phi.value.reshape(ny,nx)

    wtd = (phi.value - ele).reshape(ny, nx)
    wtd_sensors = [wtd[i] for i in sensor_positions]

    return np.array(wtd_sensors)
コード例 #15
0
 def create_coefficient(self):
     """A spatially varying diffusion coefficient"""
     arr = self.section.material_property("diffusivity").into("m**2/s")
     arr = N.append(arr, arr[-1])
     assert len(arr) == len(self.mesh.faceCenters[0])
     self.diffusion_coefficient = F.FaceVariable(mesh=self.mesh, value=arr)
コード例 #16
0
ファイル: RadialHeatTransfer.py プロジェクト: birdol/SmoWeb
 def QAx(self):
     return fp.FaceVariable(mesh=self.mesh,
                            value=-self.thermalConductivity *
                            self.areaFaces * self.T.faceGrad)