Esempio n. 1
0
    def project(self, t=None):
        """Project solution onto CG subspace.

        soln.project(t)

        project projects the solution at time t onto a CG
        FunctionSpace. The projected function is left in
        self.CGfunction. If argument t is not supplied, the currently
        loaded solution will be used. (In this case, you must have
        called load(t) before calling project().

        project returns self.CGfunction as its value.
        """
        solver_type = 'petsc'
        if t is not None:
            self.load(t)
        if not hasattr(self, 'CS'):
            #
            # create CG FunctionSpace
            #
            self.CE = CGelement(self.fs)
            self.CS = FunctionSpace(self.fs.mesh(), self.CE)
        self.CGfunction = fe.project(self.function,
                                     self.CS,
                                     solver_type=solver_type)
        return self.CGfunction
Esempio n. 2
0
def project_gradient_neumann(
        f0,
        degree=None,
        mesh=None,
        solver_type='gmres',
        preconditioner_type='default'
    ):
    """Find an approximation to f0 that has the same gradient

    The resulting function also satisfies homogeneous Neumann boundary
    conditions.

    Parameters:    
    f0: the function to approximate
    mesh=None: the mesh on which to approximate it If not provided, the
        mesh is extracted from f0.
    degree=None: degree of the polynomial approximation. extracted
        from f0 if not provided. 
    solver_type='gmres': The linear solver type to use.
    preconditioner_type='default': Preconditioner type to use
    """
    if not mesh: mesh = f0.function_space().mesh()
    element = f0.ufl_element()
    if not degree:
        degree = element.degree()
    CE = FiniteElement('CG', mesh.ufl_cell(), degree)
    CS = FunctionSpace(mesh, CE)
    DE = FiniteElement('DG', mesh.ufl_cell(), degree)
    DS = FunctionSpace(mesh, DE)
    CVE = VectorElement('CG', mesh.ufl_cell(), degree - 1)
    CV = FunctionSpace(mesh, CVE)
    RE = FiniteElement('R', mesh.ufl_cell(), 0)
    R = FunctionSpace(mesh, RE)
    CRE = MixedElement([CE, RE])
    CR = FunctionSpace(mesh, CRE)
    f = fe.project(f0, CS,
                   solver_type=solver_type,
                   preconditioner_type=preconditioner_type)
    g = fe.project(fe.grad(f), CV,
                   solver_type=solver_type,
                   preconditioner_type=preconditioner_type)
    lf = fe.project(fe.nabla_div(g), CS,
                    solver_type=solver_type,
                    preconditioner_type=preconditioner_type)
    tf, tc = TrialFunction(CR)
    wf, wc = TestFunctions(CR)
    dx = Measure('dx', domain=mesh,
                 metadata={'quadrature_degree': min(degree, 10)})
    a = (fe.dot(fe.grad(tf), fe.grad(wf)) + tc * wf + tf * wc) * dx
    L = (f * wc - lf * wf) * dx
    igc = Function(CR)
    fe.solve(a == L, igc,
             solver_parameters={'linear_solver': solver_type,
                                 'preconditioner': preconditioner_type}
    )
    ig, c = igc.sub(0), igc.sub(1)
    igd = fe.project(ig, DS,
                     solver_type=solver_type,
                     preconditioner_type=preconditioner_type)
    return igd
Esempio n. 3
0
    def test_multiplication(self):
        print(
            '\n== testing multiplication of system matrix for problem of weighted projection ===='
        )
        for dim, pol_order in itertools.product([2, 3], [1, 2]):
            N = 2  # no. of elements

            print('dim={0}, pol_order={1}, N={2}'.format(dim, pol_order, N))

            # creating MESH and defining MATERIAL
            if dim == 2:
                mesh = UnitSquareMesh(N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])",
                               degree=2)  # material coefficients
            elif dim == 3:
                mesh = UnitCubeMesh(N, N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*(1-x[1])*x[2]",
                               degree=2)  # material coefficients

            mesh.coordinates()[:] += 0.1 * np.random.random(
                mesh.coordinates().shape)  # mesh perturbation

            V = FunctionSpace(mesh, "CG", pol_order)  # original FEM space
            W = FunctionSpace(mesh, "CG", 2 * pol_order)  # double-grid space

            print('assembling local matrices for DoGIP...')
            Bhat = get_Bhat(
                dim, pol_order,
                problem=0)  # projection between V on W on a reference element
            AT_dogip = get_A_T(m, V, W, problem=0)

            dofmapV = V.dofmap()

            def system_multiplication_DoGIP(AT_dogip, Bhat, u_vec):
                # mutliplication with DoGIP decomposition
                Au = np.zeros_like(u_vec)
                for ii, cell in enumerate(cells(mesh)):
                    ind = dofmapV.cell_dofs(ii)  # local to global map
                    Au[ind] += Bhat.T.dot(AT_dogip[ii] * Bhat.dot(u_vec[ind]))
                return Au

            print('assembling FEM sparse matrix')
            u, v = TrialFunction(V), TestFunction(V)
            Asp = assemble(m * u * v * dx, tensor=EigenMatrix())  #
            Asp = Asp.sparray()

            print('multiplication...')
            ur = Function(V)  # creating random vector
            ur_vec = 5 * np.random.random(V.dim())
            ur.vector().set_local(ur_vec)

            Au_DoGIP = system_multiplication_DoGIP(
                AT_dogip, Bhat, ur_vec)  # DoGIP multiplication
            Auex = Asp.dot(ur_vec)  # FEM multiplication with sparse matrix

            # testing the difference between DoGIP and FEniCS
            self.assertAlmostEqual(0, np.linalg.norm(Auex - Au_DoGIP))
            print('...ok')
Esempio n. 4
0
 def make_function_space(self, mesh=None, dim=None, degree=None):
     if not mesh: mesh = self.mesh
     if not dim: dim = self.dim
     if not degree: degree = self.degree
     SE = FiniteElement('DG', cellShapes[dim - 1], degree)
     SS = FunctionSpace(mesh, SE)  # scalar space
     VE = MixedElement(SE, SE)
     VS = FunctionSpace(mesh, VE)  # vector space
     return dict(SE=SE, SS=SS, VE=VE, VS=VS)
Esempio n. 5
0
 def make_function_space(self, mesh=None, dim=None, degree=None):
     if not mesh: mesh = self.mesh
     if not dim: dim = self.dim
     if not degree: degree = self.degree
     SE = FiniteElement('DG', cellShapes[dim - 1], degree)
     SS = FunctionSpace(mesh, SE)  # scalar space
     elements = [SE] * ((self.nligands + 1) * 2**self.dim)
     VE = MixedElement(elements)
     VS = FunctionSpace(mesh, VE)  # vector space
     logPERIODIC('VS', VS)
     return dict(SE=SE, SS=SS, VE=VE, VS=VS)
Esempio n. 6
0
def evenodd_functions_old(
    omesh,
    degree,
    func,
    width=None,
    evenodd=None
):
    """Break a function into even and odd components

    Required parameters:
    omesh: the mesh on which the function is defined
    degree: the degree of the FunctionSpace 
    func: the Function. This has to be something that fe.interpolate
        can interpolate onto a FunctionSpace or that fe.project can
        project onto a FunctionSpace.
    width: the width of the domain on which func is defined. (If not
        provided, this will be determined from omesh.
    evenodd: the symmetries of the functions to be constructed
        evenodd_symmetries(dim) is used if this is not provided
    """
    SS = FunctionSpace(omesh, 'CG', degree)
    dim = omesh.geometry().dim()
    if width is None:
        stats = mesh_stats(omesh)
        width = stats['xmax']
    if evenodd is None:
        evenodd = evenodd_symmetries(dim)
    try:
        f0 = fe.interpolate(func, SS)
    except TypeError:
        f0 = fe.project(func, SS)
    ffuncs = []
    flips = evenodd_symmetries(dim)
    for flip in (flips):
        fmesh = Mesh(omesh)
        SSf = FunctionSpace(fmesh, 'CG', degree)
        ffunc = fe.interpolate(f0, SSf)
        fmesh.coordinates()[:, :] = (width*flip
                                     + (1 - 2*flip)*fmesh.coordinates())
        fmesh.bounding_box_tree().build(fmesh)
        ffuncs.append(ffunc)
    E = evenodd_matrix(evenodd)
    components = matmul(2**(-dim)*E, ffuncs)
    cs = []
    for c in components:
        try:
            cs.append(fe.interpolate(c, SS))
        except TypeError:
            cs.append(fe.project(c, SS, solver_type='lu'))
    return(cs)
Esempio n. 7
0
def read_dem(bounds, res):
    """
    Function to read in a DEM from SRTM amd interplolate it onto a dolphyn mesh. This function uses the python package
    'elevation' (http://elevation.bopen.eu/en/stable/) and the gdal libraries.

    I will assume you want the 30m resolution SRTM model.

    :param bounds: west, south, east, north coordinates
    :return u_n, lx, ly: the elevation interpolated onto the dolphyn mesh and the lengths of the domain
    """
    west, south, east, north = bounds

    # Create a temporary file to store the DEM and go get it using elevation
    dem_path = 'tmp.tif'
    output = os.getcwd() + '/' + dem_path
    elv.clip(bounds=bounds, output=output, product='SRTM1')

    # read in the DEM into a numpy array
    gdal_data = gdal.Open(output)
    data_array = gdal_data.ReadAsArray().astype(np.float)

    # The DEM is 30m per pixel, so lets make a array for x and y at 30 m
    ny, nx = np.shape(data_array)
    lx = nx * 30
    ly = ny * 30

    x, y = np.meshgrid(np.linspace(0, lx / ly, nx), np.linspace(0, 1, ny))

    # Create mesh and define function space
    domain = Rectangle(Point(0, 0), Point(lx / ly, 1))
    mesh = generate_mesh(domain, res)
    V = FunctionSpace(mesh, 'P', 1)
    u_n = Function(V)

    # Get the global coordinates
    gdim = mesh.geometry().dim()
    gc = V.tabulate_dof_coordinates().reshape((-1, gdim))

    # Interpolate elevation into the initial condition
    elevation = interpolate.griddata((x.flatten(), y.flatten()),
                                     data_array.flatten(),
                                     (gc[:, 0], gc[:, 1]),
                                     method='nearest')
    u_n.vector()[:] = elevation

    # remove tmp DEM
    os.remove(output)

    return u_n, lx, ly, mesh, V
Esempio n. 8
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        epsilon = Constant(arguments[Components().Diffusion])
        f = Expression("(1 - epsilon*4*pow(pi,2))*cos(2*pi*x[0])",\
                       epsilon=epsilon, degree=1)

        a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx
        L = f * w * dx

        # solving the variational problem.
        v = Function(H)
        solve(a == L, v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Esempio n. 9
0
    def __init__(self, function):
        """Expand a Function defined on a corner mesh to a full mesh.

        Required parameter:
        funcion: the Function to be expanded.
        """
        self.VS = function.function_space()
        self.submesh = self.VS.mesh()
        self.dim = self.submesh.geometric_dimension()
        self.nss = self.VS.num_sub_spaces()
        self.nfields = self.nss // (2**self.dim)
        self.subcoords = self.submesh.coordinates()
        self.vtrans = integerify_transform(self.subcoords)
        self.icols = ['i' + str(i) for i in range(self.dim)]
        self.emesh, self.maps, self.cellmaps, self.vertexmaps = (expand_mesh(
            self.submesh, self.vtrans))
        self.dcoords = np.reshape(self.VS.tabulate_dof_coordinates(),
                                  (-1, self.dim))
        self.dtrans = integerify_transform(self.dcoords)
        self.eSE = scalar_element(self.VS)
        self.degree = self.eSE.degree()
        self.eVE = MixedElement([self.eSE] * self.nfields)
        self.eVS = FunctionSpace(self.emesh, self.eVE)
        self.sub_dof_list = dof_list(self.VS, self.dtrans)
        subs = self.sub_dof_list['sub'].values
        self.sub_dof_list['submesh'] = subs % (2**self.dim)
        self.sub_dof_list['field'] = subs // (2**self.dim)
        sc = self.sub_dof_list[['submesh', 'cell']].values
        self.sub_dof_list['ecell'] = self.cellmaps[(sc[:, 0], sc[:, 1])]
        self.e_dof_list = dof_list(self.eVS, self.dtrans)
        self.remap = self.sub2e_map()
        self.symmetries = evenodd_symmetries(self.dim)
        self.eomat = evenodd_matrix(self.symmetries)
        self.sub_function = Function(self.VS)
        self.expanded_function = Function(self.eVS)
Esempio n. 10
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        epsilon = Constant(arguments[Components().Diffusion])
        f = Constant(0)

        a = (epsilon * inner(grad(v), grad(w)) + inner(v, w)) * dx
        #Still have to figure it how to use a Neumann Condition here
        L = f * w * dx

        # solving the variational problem.
        v = Function(H)
        solve(a == L, v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
def compute_mesh_error(do_local_refine, mesh_resolution, num_refinements):
    mesh = generate_rectangle_mesh(mesh_resolution)

    # Define heat kernel
    t0 = 0.01
    u = Expression("exp(-(x[0]*x[0]+x[1]*x[1])/(4*t))/(4*pi*t)",
                   t=t0,
                   domain=mesh,
                   degree=3)

    # Define finite element function space
    degree = 1
    V = FunctionSpace(mesh, "CG", degree)

    # Refine mesh
    r = 0.4
    xc, yc = 0.0, 0.0
    for i in range(0, num_refinements):
        if do_local_refine:
            mesh = local_refine(mesh, [xc, yc], r)
        else:
            mesh = refine(mesh)

    # Interpolate the heat kernel into the function space
    Iu = interpolate(u, V)

    # Compute L1 error between u and its interpolant
    error = compute_error(u, Iu)
    return error
Esempio n. 12
0
def initialise(dem, bounds, res):
    """
    Function to initialise the model space

    :param dem: 0 = no input DEM; 1 = input DEM
    :param bounds: west, south, east, north - if no DEM [0, 0, lx, ly]; if DEM [west, south, east, north]
    :param res: model resolution along the y-axis.
    :return model_space, u_n, mesh, V, bc:
    """

    if dem == 0:
        lx = bounds[1]
        ly = bounds[3]

        # Create mesh and define function space
        domain = Rectangle(Point(0, 0), Point(lx / ly, ly / ly))
        mesh = generate_mesh(domain, res)

        V = FunctionSpace(mesh, 'P', 1)

        # Define initial value
        u_D = Constant(0)
        eps = 10 / ly
        u_n = interpolate(u_D, V)
        u_n.vector().set_local(u_n.vector().get_local() +
                               eps * np.random.random(u_n.vector().size()))

    if dem == 1:
        u_n, lx, ly, mesh, V = read_dem(bounds, res)

    # boundary conditions

    class East(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], lx / ly)

    class West(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0)

    class North(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], ly / ly)

    class South(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0)

    # Should make this into an option!

    bc = [DirichletBC(V, u_n, West()), DirichletBC(V, u_n, East())]

    # def boundary(x, on_boundary):
    #   return on_boundary
    # bc = DirichletBC(V, u_n, boundary)

    model_space = [lx, ly, res]

    return model_space, u_n, mesh, V, bc
def run_fokker_planck(nx, num_steps, t_0 = 0, t_final=10):

    # define mesh
    mesh = IntervalMesh(nx, -200, 200)
    # define function space. 
    V = FunctionSpace(mesh, "Lagrange", 1)

    # Homogenous Neumann BCs don't have to be defined as they are the default in dolfin
    # define parameters.
    dt = (t_final-t_0) / num_steps

    # set mu and sigma 
    mu = Constant(-1)
    D = Constant(1)

    # define initial conditions u_0
    u_0 = Expression('x[0]', degree=1)

    # set U_n to be the interpolant of u_0 over the function space V. Note that 
    # u_n is the value of u at the previous timestep, while u is the current value. 
    u_n = interpolate(u_0, V)

    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    F = u*v*dx + dt*inner(D*grad(u), grad(v))*dx + dt*mu*grad(u)[0]*v*dx - inner(u_n, v)*dx

    # isolate the bilinear and linear forms. 
    a, L = lhs(F), rhs(F)

    # initialize function to capture solution. 
    t = 0 
    u_h = Function(V)

    plt.figure(figsize=(15, 15))

    # time-stepping section
    for n in range(num_steps):
        t += dt 

        # compute solution 
        solve(a == L, u_h)
        u_n.assign(u_h)

        # Plot solutions intermittently
        if n % (num_steps // 10) == 0 and num_steps > 0:

            plot(u_h, label='t = %s' % t)
    
    plt.legend() 
    plt.grid()
    plt.title("Finite Element Solutions to Fokker-Planck Equation with $\mu(x, t) = -(x+1)$ , $D(x, t) = e^t x^2$, $t_n$ = %s" % t_final)
    plt.ylabel("$u(x, t)$")
    plt.xlabel("x")
    plt.savefig("fpe/fokker-planck-solutions-mu.png")
    plt.clf() 

    # return the approximate solution evaluated on the coordinates, and the actual coordinates. 
    return u_n.compute_vertex_values(), mesh.coordinates() 
def test_video_loading():
    m = UnitSquareMesh(30, 30)
    V = FunctionSpace(m, "CG", 4)

    video = VideoData(element=V.ufl_element())
    video.load_video("video_data/ach12.mp4")

    print(video)

    plot(video, mesh=m)
    plt.show()

    video.set_time(10000.)
    plot(video, mesh=m)
    plt.show()

    assert True
Esempio n. 15
0
def dual_error_estimates(resolution):
    mesh = UnitSquareMesh(resolution, resolution)

    def all_boundary(_, on_boundary):
        return on_boundary

    zero = Constant(0.0)

    def a(u, v):
        return inner(grad(u), grad(v)) * dx

    def L(f, v):
        return f * v * dx

    # Primal problem
    f = Expression("32.*x[0]*(1. - x[0])+32.*x[1]*(1. - x[1])",
                   domain=mesh,
                   degree=5)
    ue = Expression("16.*x[0]*(1. - x[0])*x[1]*(1. - x[1])",
                    domain=mesh,
                    degree=5)

    Qp = FunctionSpace(mesh, 'CG', 1)
    bcp = DirichletBC(Qp, zero, all_boundary)

    u = TrialFunction(Qp)
    v = TestFunction(Qp)

    U = Function(Qp)
    solve(a(u, v) == L(f, v), U, bcp)

    # Dual problem
    Qd = FunctionSpace(mesh, 'CG', 2)
    psi = Constant(1.0)
    bcd = DirichletBC(Qd, zero, all_boundary)

    w = TestFunction(Qd)
    phi = TrialFunction(Qd)
    Phi = Function(Qd)
    solve(a(w, phi) == L(psi, w), Phi, bcd)

    # Compute errors
    e1 = compute_error(ue, U)
    e2 = assemble((inner(grad(U), grad(Phi)) - f * Phi) * dx)
    print("e1 = {}".format(e1))
    print("e2 = {}".format(e2))
Esempio n. 16
0
def main():
    np.random.seed(793817931)
    degree = 3
    mesh = UnitSquareMesh(2, 2)
    gdim = mesh.geometry().dim()
    fs = FunctionSpace(mesh, 'CG', degree)
    f = Function(fs)
    random_function(f)
    print(f.vector()[:])
Esempio n. 17
0
def evenodd_functions(
    omesh,
    degree,
    func,
    width=None,
    evenodd=None
):
    """Break a function into even and odd components

    Required parameters:
    omesh: the mesh on which the function is defined
    degree: the degree of the FunctionSpace 
    func: the Function. This has to be something that fe.interpolate
        can interpolate onto a FunctionSpace or that fe.project can
        project onto a FunctionSpace.
    width: the width of the domain on which func is defined. (If not
        provided, this will be determined from omesh.
    evenodd: the symmetries of the functions to be constructed
        evenodd_symmetries(dim) is used if this is not provided
    """
    SS = FunctionSpace(omesh, 'CG', degree)
    dim = omesh.geometry().dim()
    comm = omesh.mpi_comm()
    rank = comm.rank
    if width is None:
        stats = mesh_stats(omesh)
        width = stats['xmax']
    if evenodd is None:
        evenodd = evenodd_symmetries(dim)
    try:
        f0 = fe.interpolate(func, SS)
    except TypeError:
        f0 = fe.project(func, SS)
    vec0 = f0.vector().gather_on_zero()
    dofcoords = gather_dof_coords(SS)
    ndofs = len(dofcoords)
    fvecs = np.empty((2**dim, len(vec0)), float)
    flips = evenodd_symmetries(dim)
    for row,flip in enumerate(flips):
        newcoords = (width*flip
                     + (1 - 2*flip)*dofcoords)
        remap = coord_remap(SS, newcoords)
        E = evenodd_matrix(evenodd)
        if rank == 0:
            fvecs[row, :] = vec0[remap]
            components = np.matmul(2**(-dim)*E, fvecs)
        else:
            components = np.zeros((2**dim, ndofs), float)
    logPERIODIC('components.shape', components.shape)
    fs = []
    logPERIODIC('broadcasting function DOFs')
    for c in components:
        f = Function(SS)
        f = bcast_function(SS, c, f)
        # f.set_allow_extrapolation(True)
        fs.append(f)
    return(fs)
Esempio n. 18
0
 def restart(self):
     logVARIABLE('restart')
     self.set_time(self.t0)
     CE = FiniteElement('CG', cellShapes[self.dim - 1], self.degree)
     CS = FunctionSpace(self.mesh, CE)  # scalar space
     coords = gather_dof_coords(CS)
     fe.assign(self.sol.sub(0),
               function_interpolate(self.rho0, self.SS, coords=coords))
     for i, U0i in enumerate(self.U0s):
         fe.assign(self.sol.sub(i + 1),
                   function_interpolate(U0i, self.SS, coords=coords))
Esempio n. 19
0
    def solve(self, **arguments):

        t_start = time.clock()

        # definig Function space on this mesh using Lagrange
        #polynoimals of degree 1.
        H = FunctionSpace(self.mesh, "CG", 1)

        # Setting up the variational problem
        v = TrialFunction(H)
        w = TestFunction(H)

        coeff_dx2 = Constant(1)
        coeff_v = Constant(1)

        f = Expression("(4*pow(pi,2))*exp(-(1/coeff_v)*t)*sin(2*pi*x[0])",
                       {'coeff_v': coeff_v},
                       degree=2)

        v0 = Expression("sin(2*pi*x[0])", degree=2)

        f.t = 0

        def boundary(x, on_boundary):
            return on_boundary

        bc = DirichletBC(H, v0, boundary)

        v1 = interpolate(v0, H)
        dt = self.steps.time

        a = (dt * inner(grad(v), grad(w)) + dt * coeff_v * inner(v, w)) * dx
        L = (f * dt - coeff_v * v1) * w * dx

        A = assemble(a)
        v = Function(H)

        T = self.domain.time[-1]
        t = dt

        # solving the variational problem.
        while t <= T:
            b = assemble(L, tensor=b)
            vo.t = t
            bc.apply(A, b)

            solve(A, v.vector(), b)
            t += dt

            v1.assign(v)

        self.solution.extend(v.vector().array())

        return [self.solution, time.clock() - t_start]
Esempio n. 20
0
 def restart(self):
     logSOLVER('restart')
     self.t = self.t0
     CE = FiniteElement('CG', cellShapes[self.dim - 1], self.degree)
     CS = FunctionSpace(self.mesh, CE)  # scalar space
     coords = gather_dof_coords(CS)
     logSOLVER('function_interpolate(self.U0, self.SS, coords=coords)',
               function_interpolate(self.U0, self.SS, coords=coords))
     fe.assign(self.sol.sub(1),
               function_interpolate(self.U0, self.SS, coords=coords))
     logSOLVER('U0 assign returned')
     fe.assign(self.sol.sub(0),
               function_interpolate(self.rho0, self.SS, coords=coords))
Esempio n. 21
0
    def __init__(self, mesh, N=0):

        # Define mesh parameters
        self.mesh = mesh
        self.cell_size = CellDiameter(mesh)
        self.normal_vector = FacetNormal(mesh)

        # Define measures
        inner_boundary = Inner_boundary()
        sub_domains = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
        sub_domains.set_all(0)
        inner_boundary.mark(sub_domains, 1)
        self.dx = Measure("dx", domain=mesh)
        self.ds = Measure("ds", domain=mesh, subdomain_data=sub_domains)

        # Define function spaces
        finite_element = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
        self.function_space = FunctionSpace(mesh,
                                            finite_element * finite_element)
        self.function_space_split = [
            self.function_space.sub(0).collapse(),
            self.function_space.sub(1).collapse(),
        ]
Esempio n. 22
0
 def __init__(self, *, V: Optional[FunctionSpace], mesh: Mesh,
              dt: float) -> None:
     V = V or FunctionSpace(mesh, "Lagrange", 1)
     self.V = V
     self.T = TrialFunction(V)
     self.v = TestFunction(V)
     self.T_prev = Function(V)
     self.P_s = Constant(1.0)
     self.c_s = Constant(1.0)
     self.k_e = Constant(1.0)
     self.Q_pc = Constant(1.0)
     self.Q_sw = Constant(1.0)
     self.Q_mm = Constant(1.0)
     self.dt = Constant(dt)
Esempio n. 23
0
    def test_DoGIP_vs_FEniCS(self):
        print(
            '\n== testing DoGIP vs. FEniCS for problem of weighted projection ===='
        )

        for dim, pol_order in itertools.product([2, 3], [1, 2]):
            print('dim={}; pol_order={}'.format(dim, pol_order))
            N = 2
            # creating MESH, defining MATERIAL and SOURCE
            if dim == 2:
                mesh = UnitSquareMesh(N, N)
                m = Expression("1+10*16*x[0]*(1-x[0])*x[1]*(1-x[1])",
                               degree=3)  # material coefficients
                f = Expression("x[0]*x[0]*x[1]", degree=2)
            elif dim == 3:
                mesh = UnitCubeMesh(N, N, N)
                m = Expression("1+100*x[0]*(1-x[0])*x[1]*x[2]",
                               degree=2)  # material coefficients
                f = Expression("(1-x[0])*x[1]*x[2]", degree=2)

            mesh.coordinates()[:] += 0.1 * np.random.random(
                mesh.coordinates().shape)  # mesh perturbation

            ## standard approach with FEniCS #############################################
            V = FunctionSpace(mesh, "CG", pol_order)  # original FEM space
            u, v = TrialFunction(V), TestFunction(V)
            u_fenics = Function(V)
            solve(m * u * v * dx == m * f * v * dx, u_fenics)

            ## DoGIP - double-grid integration with interpolation-projection #############
            W = FunctionSpace(mesh, "CG", 2 * pol_order)  # double-grid space
            w = TestFunction(W)
            A_dogip = assemble(
                m * w *
                dx).get_local()  # diagonal matrix of material coefficients
            b = assemble(m * f * v * dx)  # vector of right-hand side

            # assembling interpolation-projection matrix B
            B = get_B(V, W, problem=0)

            # # linear solver on double grid, standard
            Afun = lambda x: B.T.dot(A_dogip * B.dot(x))

            Alinoper = linalg.LinearOperator((V.dim(), V.dim()),
                                             matvec=Afun,
                                             dtype=np.float)
            x, info = linalg.cg(Alinoper,
                                b.get_local(),
                                x0=np.zeros(V.dim()),
                                tol=1e-10,
                                maxiter=1e3,
                                callback=None)

            # testing the difference between DoGIP and FEniCS
            self.assertAlmostEqual(
                0, np.linalg.norm(u_fenics.vector().get_local() - x))
            print('...ok')
Esempio n. 24
0
    def __init__(self,
                 grid_shape,
                 f,
                 init_z,
                 dirichlet,
                 degree=1,
                 polynomial_type='P',
                 reparam=True):
        """Parameters
        ----------
        grid_shape : numpy.array or list
            Defines the grid dimensions of the mesh used to solve the problem.
        f : str
            Source term of the Poisson equation in a form accepted by FEniCS (C++ style string)
        init_z : numpy.ndarray
            Placeholder value(s) for parameters of the model.
        dirichlet : str
            Dirichlet boundary conditions in string form accepted by FEniCS.
        degree : int, default 1
            Polynomial degree for the functional space.
        polynomial_type : str, default 'P'
            String encoding the type of polynomials in the functional space, according to FEniCS conventions
            (defaults to Lagrange polynomials).
        reparam: bool, default True
            Boolean indicating whether input parameters are to be reparametrized according to
            an inverse-logit transform.
        """
        def boundary(x, on_boundary):
            return on_boundary

        self.grid_shape = grid_shape
        self.mesh = UnitSquareMesh(*grid_shape)

        self.V = FunctionSpace(self.mesh, polynomial_type, degree)
        self.dirichlet = DirichletBC(self.V,
                                     Expression(dirichlet, degree=degree + 3),
                                     boundary)
        self._paramnames = ['param{}'.format(i) for i in range(len(init_z))]
        self.f = Expression(f,
                            degree=degree,
                            **dict(zip(self._paramnames, init_z)))
        u = TrialFunction(self.V)
        v = TestFunction(self.V)

        self.a = dot(grad(u), grad(v)) * dx
        self.L = self.f * v * dx
        self.u = Function(self.V)
        self.reparam = reparam
        self.solver = CountIt(solve)
Esempio n. 25
0
def compute_error(u1, u2):
    """
    L1 error between two functions u1 and u2

    :param u1: FEniCS function
    :param u2: FEniCS function
    :return: Approximate L1 error between u1 and u2
    """
    mesh_resolution_ref = 400
    mesh_ref = UnitSquareMesh(mesh_resolution_ref, mesh_resolution_ref)
    V_ref = FunctionSpace(mesh_ref, "CG", degree=1)
    Iu1 = interpolate(u1, V_ref)
    Iu2 = interpolate(u2, V_ref)
    error = assemble(abs(Iu1 - Iu2) * dx)
    return error
    def compute_steady_state(self):

        names = {'Cl', 'Na', 'K'}

        P1 = FiniteElement('P', fe.triangle, 1)
        element = MixedElement([P1, P1, P1])
        V = FunctionSpace(self.mesh, element)
        self.V_conc = V

        (u_cl, u_na, u_k) = TrialFunction(V)
        (v_cl, v_na, v_k) = TestFunction(V)

        assert (self.flow is not None)

        n = fe.FacetNormal(self.mesh)

        # F = ( self.F_diff_conv(u_cl, v_cl, n, grad(self.phi), 1. ,1., 0.)
        #    + self.F_diff_conv(u_na, v_na, n, grad(self.phi), 1. ,1., 0.)
        #    + self.F_diff_conv(u_k , v_k , n, grad(self.phi), 1. ,1., 0.) )

        dx, ds = self.dx, self.ds
        flow = self.flow
        F = inner(grad(u_cl), grad(v_cl)) * dx \
            + inner(flow, grad(u_cl)) * v_cl * dx \
            + inner(grad(u_na), grad(v_na)) * dx \
            + inner(flow, grad(u_na)) * v_na * dx \
            + inner(grad(u_k), grad(v_k)) * dx \
            + inner(flow, grad(u_k)) * v_k * dx

        a, L = fe.lhs(F), fe.rhs(F)
        a_mat = fe.assemble(a)
        L_vec = fe.assemble(L)
        # solve
        u = Function(V)
        fe.solve(a_mat, u.vector(), L_vec)

        u_cl, u_na, u_k = u.split()

        output1 = fe.File('/tmp/steady_state_cl.pvd')
        output1 << u_cl
        output2 = fe.File('/tmp/steady_state_na.pvd')
        output2 << u_na
        output3 = fe.File('/tmp/steady_state_k.pvd')
        output3 << u_k

        self.u_cl = u_cl
        self.u_na = u_na
        self.u_k = u_k
Esempio n. 27
0
def solve():
    mesh = UnitIntervalMesh(10)
    V = FunctionSpace(mesh, "Lagrange", 1)
    dt = 0.01
    bt_params = bulk_temperature.BulkTemperatureParameters(V=V,
                                                           mesh=mesh,
                                                           dt=dt)
    bt = bulk_temperature.BulkTemperature(params=bt_params)
    a_T, L_T = bt.construct_variation_problem()
    T = Function(V)
    bt_params.T_prev.vector().set_local(
        np.random.uniform(0, -10,
                          bt_params.T_prev.vector().size()))
    map_params = mass_air_phase.MassAirPhaseParameters(V=V, mesh=mesh, dt=dt)
    map_params.T_s = T
    ma_ph = mass_air_phase.MassAirPhase(params=map_params)
    a_P, L_P = ma_ph.construct_variation_problem()
    P = Function(V)
    num_steps = 10
    t = 0
    T_sols = [bt_params.T_prev.vector().array()]
    P_sols = []
    for n in range(num_steps):
        bc = bt.make_bcs(V, 0, -10)
        _, bt_params.T_prev, T = bulk_temperature.step(time=t,
                                                       dt=dt,
                                                       t_prev=bt_params.T_prev,
                                                       t=T,
                                                       a=a_T,
                                                       l=L_T,
                                                       bc=bc)
        _, map_params.P_prev, P = mass_air_phase.step(time=t,
                                                      dt=dt,
                                                      p_prev=map_params.P_prev,
                                                      p=P,
                                                      a=a_P,
                                                      l=L_P)
        t += dt
        T_sols.append(T.vector().array())
        P_sols.append(P.vector().array())
    for T_s in T_sols:
        plt.plot(T_s)
    plt.figure()
    for P_s in P_sols:
        plt.plot(P_s)

    plt.show()
Esempio n. 28
0
 def __init__(self, *, V: Optional[FunctionSpace], mesh: Mesh, dt: float):
     V = V or FunctionSpace(mesh, "Lagrange", 1)
     self.V = V
     self.u = TrialFunction(V)
     self.v = TestFunction(V)
     self.P_prev = Function(V)
     self.theta_a = Constant(1.0)
     self.D_e = Constant(1.0)
     self.P_d = Constant(1.0)
     self.my_v = Constant(1.0)
     self.my_d = Constant(1.0)
     self.alpha_th = Constant(1.0)
     self.M_mm = Constant(1.0)
     self.q_h = Constant(1.0)
     self.T_s = project(Constant(-5.0), V)
     self.dt = Constant(dt)
     self.mesh = mesh
def solve_wave_equation(u0, u1, u_boundary, f, domain, mesh, degree):
    """Solving the wave equation using CG-CG method.

    Args:
        u0: Initial data.
        u1: Initial velocity.
        u_boundary: Dirichlet boundary condition.
        f: Right-hand side.
        domain: Space-time domain.
        mesh: Computational mesh.
        degree: CG(degree) will be used as the finite element.
    Outputs:
        uh: Numerical solution.
    """
    # Element
    V = FunctionSpace(mesh, "CG", degree)
    # Measures on the initial and terminal slice
    mask = MeshFunction("size_t", mesh, mesh.topology().dim() - 1, 0)
    domain.get_initial_slice().mark(mask, 1)
    ends = ds(subdomain_data=mask)
    # Form
    g = Constant(((-1.0, 0.0), (0.0, 1.0)))
    u = TrialFunction(V)
    v = TestFunction(V)
    a = dot(grad(v), dot(g, grad(u))) * dx
    L = f * v * dx + u1 * v * ends(1)
    # Assembled matrices
    A = assemble(a, keep_diagonal=True)
    b = assemble(L, keep_diagonal=True)
    # Spatial boundary condition
    bc = DirichletBC(V, u_boundary, domain.get_spatial_boundary())
    bc.apply(A, b)
    # Temporal boundary conditions (by hand)
    (A, b) = apply_time_boundary_conditions(domain, V, u0, A, b)
    # Solve
    solver = LUSolver()
    solver.set_operator(A)
    uh = Function(V)
    solver.solve(uh.vector(), b)
    return uh
Esempio n. 30
0
alpha = 3  # parameter alpha
beta = 1.3  # parameter beta
gamma = args.gamma  # parameter gamma, dependence of heat flux on time
y_bottom, y_top = 0, 1
x_left, x_right = 0, 2
x_coupling = 1.5  # x coordinate of coupling interface

if domain_part is DomainPart.LEFT:
    p0 = Point(x_left, y_bottom)
    p1 = Point(x_coupling, y_top)
elif domain_part is DomainPart.RIGHT:
    p0 = Point(x_coupling, y_bottom)
    p1 = Point(x_right, y_top)

mesh = RectangleMesh(p0, p1, nx, ny)
V = FunctionSpace(mesh, 'P', 2)

# Define boundary condition
u_D = Expression(
    '1 + gamma*t*x[0]*x[0] + (1-gamma)*x[0]*x[0] + alpha*x[1]*x[1] + beta*t',
    degree=2,
    alpha=alpha,
    beta=beta,
    gamma=gamma,
    t=0)
u_D_function = interpolate(u_D, V)
# Define flux in x direction on coupling interface (grad(u_D) in normal direction)
f_N = Expression('2 * gamma*t*x[0] + 2 * (1-gamma)*x[0] ',
                 degree=1,
                 gamma=gamma,
                 t=0)
Esempio n. 31
0
class DataInput(object):
  """ 
  This object brokers the relation between the driver file and a number of
  data sets. It's function is to:

    1) Read the data. Presently it is assumed that all input is Matlab V5.
    2) Filter or process the data. Presently the only filter is to remove
       rows or columns in key data sets that are entirely not a number.
    3) Project the data onto a finite element mesh that is generated based
       on the extents of the input data set.
  """
  def __init__(self, direc, files, flip=False, mesh=None, gen_space=True, 
               zero_edge=False, bool_data=False, req_dg=False):
    """
    The following data are used to initialize the class :
    
      direc     : Set the directory containing the input files. 
      files     : Tuple of file names.  All files are scanned for rows or 
                  columns of nans. Assume all files have the same extents.
      flip      : flip the data over the x-axis?
      mesh      : FEniCS mesh if there is one already created.
      zero_edge : Make edges of domain -0.002?
      bool_data : Convert data to boolean?
      req_dg    : Some field may require DG space?
    
    Based on thickness extents, create a rectangular mesh object.
    Also define the function space as continious galerkin, order 1.
    """
    self.directory  = direc
    self.data       = {}        # dictionary of converted matlab data
    self.rem_nans   = False
    self.chg_proj   = False     # change to other projection flag
    
    first = True  # initialize domain by first file's extents

    if direc == None and type(files) == dict:
      self.name = files.pop('dataset')
    elif direc != None:
      self.name = direc
    
    print "::: creating %s DataInput object :::" % self.name
    
    # process the data files :
    for fn in files:
     
      if direc == None and type(files) == dict:
        d_dict = files[fn]
    
      
      elif direc != None:
        d_dict = loadmat(direc + fn)
        d_dict['projection']     = d_dict['projection'][0]
        d_dict['standard lat']   = d_dict['standard lat'][0]
        d_dict['standard lon']   = d_dict['standard lon'][0]
        d_dict['lat true scale'] = d_dict['lat true scale'][0]
      
      d = d_dict["map_data"]
     
      # initialize extents :
      if first: 
        self.ny,self.nx = shape(d_dict['map_data'])
        self.x_min      = float(d_dict['map_western_edge'])
        self.x_max      = float(d_dict['map_eastern_edge'])
        self.y_min      = float(d_dict['map_southern_edge'])
        self.y_max      = float(d_dict['map_northern_edge'])
        self.proj       = str(d_dict['projection'])
        self.lat_0      = str(d_dict['standard lat'])
        self.lon_0      = str(d_dict['standard lon'])
        self.lat_ts     = str(d_dict['lat true scale'])
        self.x          = linspace(self.x_min, self.x_max, self.nx)
        self.y          = linspace(self.y_min, self.y_max, self.ny)
        self.good_x     = array(ones(len(self.x)), dtype=bool)      # no NaNs
        self.good_y     = array(ones(len(self.y)), dtype=bool)      # no NaNs
        first           = False
  
      # identify, but not remove the NaNs : 
      self.identify_nans(d, fn)
     
      # make edges all zero for interpolation of interior regions :
      if zero_edge:
        d[:,0] = d[:,-1] = d[0,:] = d[-1,:] = -0.002
        d[:,1] = d[:,-2] = d[1,:] = d[-2,:] = -0.002

      # convert to boolean : 
      if bool_data: d[d > 0] = 1
      
      # reflect over the x-axis :
      if flip: d = d[::-1, :]
      
      # add to the dictionary of arrays :
      self.data[fn.split('.')[0]] = d

    # remove un-needed rows/cols from data: 
    if self.rem_nans:
      self.remove_nans()
    
    if gen_space:
      # define a FEniCS Rectangle over the domain :
      if mesh == None:
        self.mesh = RectangleMesh(self.x_min, self.y_min, 
                                  self.x_max, self.y_max,
                                  self.nx,    self.ny)
      else:
        self.mesh = mesh
      
      # define the function space of the problem :
      self.func_space      = FunctionSpace(self.mesh, "CG", 1)
      
      # if DG space is needed :
      if req_dg:
        self.func_space_dg = FunctionSpace(self.mesh, "DG", 1)
    
    # create projection : 
    proj =   " +proj="   + self.proj \
           + " +lat_0="  + self.lat_0 \
           + " +lat_ts=" + self.lat_ts \
           + " +lon_0="  + self.lon_0 \
           + " +k=1 +x_0=0 +y_0=0 +no_defs +a=6378137 +rf=298.257223563" \
           + " +towgs84=0.000,0.000,0.000 +to_meter=1"
    self.p = Proj(proj)

  def change_projection(self, di):
    """
    change the projection of this data to that of the <di> DataInput object's 
    projection.  The works only if the object was created with the parameter
    create_proj = True.
    """
    self.chg_proj = True
    self.new_p    = di.p

  def integrate_field(self, fn_spec, specific, fn_main, r=20, val=0.0):
    """
    Assimilate a field with filename <fn_spec>  from DataInput object 
    <specific> into this DataInput's field with filename <fn_main>.  The
    parameter <val> should be set to the specific dataset's value for 
    undefined regions, default is 0.0.  <r> is a parameter used to eliminate
    border artifacts from interpolation; increase this value to eliminate edge
    noise.
    """
    print "::: integrating %s field from %s :::" % (fn_spec, specific.name)
    # get the dofmap to map from mesh vertex indices to function indicies :
    df    = self.func_space.dofmap()
    dfmap = df.vertex_to_dof_map(self.mesh)
    
    unew  = self.get_projection(fn_main)      # existing dataset projection
    uocom = unew.compute_vertex_values()      # mesh indexed main vertex values
    
    uspec = specific.get_projection(fn_spec)  # specific dataset projection
    uscom = uspec.compute_vertex_values()     # mesh indexed spec vertex values

    d     = float64(specific.data[fn_spec])   # original matlab spec dataset

    # get arrays of x-values for specific domain
    xs    = specific.x
    ys    = specific.y
    nx    = specific.nx
    ny    = specific.ny
    
    for v in vertices(self.mesh):
      # mesh vertex x,y coordinate :
      i   = v.index()
      p   = v.point()
      x   = p.x()
      y   = p.y()
      
      # indexes of closest datapoint to specific dataset's x and y domains :
      idx = abs(xs - x).argmin()
      idy = abs(ys - y).argmin()
      
      # data value for closest value and square around the value in question :
      dv  = d[idy, idx] 
      db  = d[max(0,idy-r) : min(ny, idy+r),  max(0, idx-r) : min(nx, idx+r)]
      
      # if the vertex is in the domain of the specific dataset, and the value 
      # of the dataset at this point is not abov <val>, set the array value 
      # of the main file to this new specific region's value.
      if dv > val:
        #print "found:", x, y, idx, idy, v.index()
        # if the values is not near an edge, make the value equal to the 
        # nearest specific region's dataset value, otherwise, use the 
        # specific region's projected value :
        if all(db > val):
          uocom[i] = uscom[i]
        else :
          uocom[i] = dv
    
    # set the values of the projected original dataset equal to the assimilated
    # dataset :
    unew.vector().set_local(uocom[dfmap])
    return unew
  
  def identify_nans(self, data, fn):
    """ 
    private method to identify rows and columns of all nans from grids. This 
    happens when the data from multiple GIS databases don't quite align on 
    whatever the desired grid is.
    """
    #print "::: DataInput identifying NaNs for %s :::" % fn

    good_x = ~all(isnan(data), axis=0) & self.good_x  # good cols
    good_y = ~all(isnan(data), axis=1) & self.good_y  # good rows
    
    if any(good_x != self.good_x):
      total_nan_x = sum(good_x == False)
      self.rem_nans = True
      print "Warning: %d row(s) of \"%s\" are entirely NaN." % (total_nan_x, fn)

    if any(good_y != self.good_y):
      total_nan_y = sum(good_y == False)
      self.rem_nans = True
      print "Warning: %d col(s) of \"%s\" are entirely NaN." % (total_nan_y, fn)
    
    self.good_x = good_x
    self.good_y = good_y
  
  def remove_nans(self):
    """
    remove extra rows/cols from data where NaNs were identified and set the 
    extents to those of the good x and y values.
    """
    self.x     = self.x[self.good_x]
    self.y     = self.y[self.good_y]
    self.x_min = self.x.min()
    self.x_max = self.x.max()
    self.y_min = self.y.min()
    self.y_max = self.y.max()
    self.nx    = len(self.x)
    self.ny    = len(self.y)
    
    print "::::::::REMOVING NaNs::::::::"
    for i in self.data.keys():
      self.data[i] = self.data[i][self.good_y, :          ]
      self.data[i] = self.data[i][:,           self.good_x]

  def set_data_min(self, fn, boundary, val):
    """
    set the minimum value of a data array with filename <fn> below <boundary>
    to value <val>.
    """
    d                = self.data[fn]
    d[d <= boundary] = val
    self.data[fn]    = d

  def set_data_max(self, fn, boundary, val):
    """
    set the maximum value of a data array with filename <fn> above <boundary>
    to value <val>.
    """
    d                = self.data[fn]
    d[d >= boundary] = val
    self.data[fn]    = d

  def set_data_val(self, fn, old_val, new_val):
    """
    set all values of the matrix with filename <fn> equal to <old_val> 
    to <new_val>.
    """
    d                = self.data[fn]
    d[d == old_val]  = new_val
    self.data[fn]    = d

  def get_interpolation(self,fn,kx=3,ky=3):
    interp = self.get_spline_expression(fn,kx=kx,ky=ky)
    proj   = interpolate(interp, self.func_space)
    return proj

  def get_projection(self, fn, dg=False, near=False, 
                     bool_data=False, kx=3, ky=3):
    """
    Return a projection of data with filname <fn> on the functionspace.
    If multiple instances of the DataInput class are present, both initialized 
    with identical meshes, the projections returned by this function may be
    used by the same mathematical problem.

    If <dg> is True, use a discontinuous space, otherwise, continuous.

    If <bool_data> is True, convert all values > 0 to 1.
    """
    print "::: getting %s projection :::" % fn

    if dg:
      interp = self.get_nearest_expression(fn, bool_data=bool_data)
      proj   = project(interp, self.func_space_dg)
    
    else:
      if near:
        interp = self.get_nearest_expression(fn, bool_data=bool_data)
        proj   = project(interp, self.func_space)
      else:
        interp = self.get_spline_expression(fn,kx=kx,ky=ky,bool_data=bool_data)
        proj   = project(interp, self.func_space)
        
    return proj

  def get_nearest_expression(self, fn, bool_data=False):
    """
    Returns a dolfin expression using a nearest-neighbor interpolant of data 
    <fn>.  If <bool_data> is True, convert to boolean.
    """
    print "::: getting %s nearest expression from %s :::" % (fn, self.name)
    
    data = self.data[fn]
    if bool_data: data[data > 0] = 1
    
    if self.chg_proj:
      new_proj = self.new_p
      old_proj = self.p

    xs       = self.x
    ys       = self.y
    chg_proj = self.chg_proj

    class newExpression(Expression):
      def eval(self, values, x):
        if chg_proj:
          xn, yn = transform(new_proj, old_proj, x[0], x[1])
        else:
          xn, yn = x[0], x[1]
        idx       = abs(self.xs - xn).argmin()
        idy       = abs(self.ys - yn).argmin()
        values[0] = self.data[idy, idx]

    return newExpression(element = self.func_space.ufl_element())

  def get_spline_expression(self, fn, kx=3, ky=3, bool_data=False):
    """
    Creates a spline-interpolation expression for data <fn>.  Optional 
    arguments <kx> and <ky> determine order of approximation in x and y
    directions (default cubic).  If <bool_data> is True, convert to boolean.
    """
    print "::: getting %s spline expression from %s :::" % (fn, self.name)

    data = self.data[fn]
    if bool_data: data[data > 0] = 1
    
    if self.chg_proj:
      new_proj = self.new_p
      old_proj = self.p
  
    spline = RectBivariateSpline(self.x, self.y, data.T, kx=kx, ky=ky)
    chg_proj = self.chg_proj
    
    class newExpression(Expression):
      def eval(self, values, x):
        if chg_proj:
          xn, yn = transform(new_proj, old_proj, x[0], x[1])
        else:
          xn, yn = x[0], x[1]
        values[0] = spline(xn, yn)
  
    return newExpression(element = self.func_space.ufl_element())
  
  def get_nearest(self, fn):
    """
    returns a dolfin Function object with values given by interpolated 
    nearest-neighbor data <fn>.
    """
    #FIXME: get to work with a change of projection.
    # get the dofmap to map from mesh vertex indices to function indicies :
    df    = self.func_space.dofmap()
    dfmap = df.vertex_to_dof_map(self.mesh)
    
    unew  = Function(self.func_space)         # existing dataset projection
    uocom = unew.vector().array()             # mesh indexed main vertex values
    
    d     = float64(self.data[fn])            # original matlab spec dataset

    # get arrays of x-values for specific domain
    xs    = self.x
    ys    = self.y
    
    for v in vertices(self.mesh):
      # mesh vertex x,y coordinate :
      i   = v.index()
      p   = v.point()
      x   = p.x()
      y   = p.y()
      
      # indexes of closest datapoint to specific dataset's x and y domains :
      idx = abs(xs - x).argmin()
      idy = abs(ys - y).argmin()
      
      # data value for closest value :
      dv  = d[idy, idx] 
      if dv > 0:
        dv = 1.0
      uocom[i] = dv
    
    # set the values of the empty function's vertices to the data values :
    unew.vector().set_local(uocom[dfmap])
    return unew
Esempio n. 32
0
  def __init__(self, direc, files, flip=False, mesh=None, gen_space=True, 
               zero_edge=False, bool_data=False, req_dg=False):
    """
    The following data are used to initialize the class :
    
      direc     : Set the directory containing the input files. 
      files     : Tuple of file names.  All files are scanned for rows or 
                  columns of nans. Assume all files have the same extents.
      flip      : flip the data over the x-axis?
      mesh      : FEniCS mesh if there is one already created.
      zero_edge : Make edges of domain -0.002?
      bool_data : Convert data to boolean?
      req_dg    : Some field may require DG space?
    
    Based on thickness extents, create a rectangular mesh object.
    Also define the function space as continious galerkin, order 1.
    """
    self.directory  = direc
    self.data       = {}        # dictionary of converted matlab data
    self.rem_nans   = False
    self.chg_proj   = False     # change to other projection flag
    
    first = True  # initialize domain by first file's extents

    if direc == None and type(files) == dict:
      self.name = files.pop('dataset')
    elif direc != None:
      self.name = direc
    
    print "::: creating %s DataInput object :::" % self.name
    
    # process the data files :
    for fn in files:
     
      if direc == None and type(files) == dict:
        d_dict = files[fn]
    
      
      elif direc != None:
        d_dict = loadmat(direc + fn)
        d_dict['projection']     = d_dict['projection'][0]
        d_dict['standard lat']   = d_dict['standard lat'][0]
        d_dict['standard lon']   = d_dict['standard lon'][0]
        d_dict['lat true scale'] = d_dict['lat true scale'][0]
      
      d = d_dict["map_data"]
     
      # initialize extents :
      if first: 
        self.ny,self.nx = shape(d_dict['map_data'])
        self.x_min      = float(d_dict['map_western_edge'])
        self.x_max      = float(d_dict['map_eastern_edge'])
        self.y_min      = float(d_dict['map_southern_edge'])
        self.y_max      = float(d_dict['map_northern_edge'])
        self.proj       = str(d_dict['projection'])
        self.lat_0      = str(d_dict['standard lat'])
        self.lon_0      = str(d_dict['standard lon'])
        self.lat_ts     = str(d_dict['lat true scale'])
        self.x          = linspace(self.x_min, self.x_max, self.nx)
        self.y          = linspace(self.y_min, self.y_max, self.ny)
        self.good_x     = array(ones(len(self.x)), dtype=bool)      # no NaNs
        self.good_y     = array(ones(len(self.y)), dtype=bool)      # no NaNs
        first           = False
  
      # identify, but not remove the NaNs : 
      self.identify_nans(d, fn)
     
      # make edges all zero for interpolation of interior regions :
      if zero_edge:
        d[:,0] = d[:,-1] = d[0,:] = d[-1,:] = -0.002
        d[:,1] = d[:,-2] = d[1,:] = d[-2,:] = -0.002

      # convert to boolean : 
      if bool_data: d[d > 0] = 1
      
      # reflect over the x-axis :
      if flip: d = d[::-1, :]
      
      # add to the dictionary of arrays :
      self.data[fn.split('.')[0]] = d

    # remove un-needed rows/cols from data: 
    if self.rem_nans:
      self.remove_nans()
    
    if gen_space:
      # define a FEniCS Rectangle over the domain :
      if mesh == None:
        self.mesh = RectangleMesh(self.x_min, self.y_min, 
                                  self.x_max, self.y_max,
                                  self.nx,    self.ny)
      else:
        self.mesh = mesh
      
      # define the function space of the problem :
      self.func_space      = FunctionSpace(self.mesh, "CG", 1)
      
      # if DG space is needed :
      if req_dg:
        self.func_space_dg = FunctionSpace(self.mesh, "DG", 1)
    
    # create projection : 
    proj =   " +proj="   + self.proj \
           + " +lat_0="  + self.lat_0 \
           + " +lat_ts=" + self.lat_ts \
           + " +lon_0="  + self.lon_0 \
           + " +k=1 +x_0=0 +y_0=0 +no_defs +a=6378137 +rf=298.257223563" \
           + " +towgs84=0.000,0.000,0.000 +to_meter=1"
    self.p = Proj(proj)