Exemple #1
0
def curvilinear_coordinate_1d(mb, p0=0, function=None):
    "Returns parametrization of a curve"

    # edge-to-vertex connectivity
    EE = np.zeros((mb.num_cells(), mb.num_vertices()), dtype=bool)
    for e in edges(mb):
        EE[e.index(), e.entities(0)] = True

    # vertex-to-vertex connectivity (via edges)
    PP = EE.T @ EE
    np.fill_diagonal(PP, False)
    mmap = -np.ones(PP.shape[0], dtype=int)

    # order vertices
    mmap[0] = p0
    for k in range(PP.shape[0] - 1):
        neig = np.where(PP[mmap[k], :])[0]
        mmap[k + 1] = neig[1] if neig[0] in mmap else neig[0]

    # cumulative length of edges
    l = np.linalg.norm(np.diff(mb.coordinates()[mmap, :], axis=0), axis=1)
    s = np.r_[0, np.cumsum(l)]

    if function is None:
        P1e = FiniteElement("CG", mb.ufl_cell(), 1)
        Ve = FunctionSpace(mb, P1e)
        function = Function(Ve)
        function.vector()[vertex_to_dof_map(Ve)[mmap]] = s
        return function
    else:
        Ve = function.function_space()
        function.vector()[vertex_to_dof_map(Ve)[mmap]] = s
Exemple #2
0
    def build_mapping(self, S3, V3):
        """
        S3 is the vector function space of the 2d mesh
        V3 is the vector function space of the corresponding 3d mesh
        """
        vert_to_dof2 = df.vertex_to_dof_map(S3)
        dof_to_vert2 = df.dof_to_vertex_map(S3)

        vert_to_dof3 = df.vertex_to_dof_map(V3)
        dof_to_vert3 = df.dof_to_vertex_map(V3)

        map_2d_to_3d = np.zeros(V3.dim(), dtype=np.int32)

        n2d = S3.dim()
        for i in range(n2d):
            map_2d_to_3d[i] = vert_to_dof3[dof_to_vert2[i]]
            map_2d_to_3d[i + n2d] = vert_to_dof3[dof_to_vert2[i] + n2d]

        self.map_2d_to_3d = map_2d_to_3d
        # print map_2d_to_3d

        n3d = V3.dim()
        map_3d_to_2d = np.zeros(V3.dim(), dtype=np.int32)
        for i in range(V3.dim()):
            map_3d_to_2d[i] = vert_to_dof2[dof_to_vert3[i] % n2d]

        self.map_3d_to_2d = map_3d_to_2d
Exemple #3
0
def test_invariance():
    """Asserts invariance of cost functional w.r.t. translation and rotation"""
    centers, J = _get_macadam()
    n = 1
    problem = PiecewiseEllipse(centers, J.copy(), n)

    alpha = problem.alpha.copy()

    c0 = problem.cost_min(alpha)
    alpha += 1.23
    c1 = problem.cost_min(alpha)
    assert abs(c0 - c1) < 1.0e-12 * c0

    d2v = dof_to_vertex_map(problem.V)
    v2d = vertex_to_dof_map(problem.V)

    alpha = problem.alpha.copy()
    alpha = alpha.reshape(2, -1).T
    coords = alpha[v2d]
    # rotate
    theta = 0.35 * numpy.pi
    sin = numpy.sin(theta)
    cos = numpy.cos(theta)
    R = numpy.array([[cos, -sin], [sin, cos]])
    rcoords = numpy.dot(R, coords.T)
    # map back to alpha)
    alpha = numpy.concatenate(rcoords[:, d2v])
    c2 = problem.cost_min(alpha)
    assert abs(c0 - c2) < 1.0e-12 * c0
    return
def test_pointsource_vector_fs(mesh, point):
    """Tests point source when given constructor PointSource(V, point,
    mag) with a vector for a vector function space that isn't placed
    at a node for 1D, 2D and 3D. Global points given to constructor
    from rank 0 processor.

    """

    rank = MPI.rank(mesh.mpi_comm())
    V = VectorFunctionSpace(mesh, "CG", 1)
    v = TestFunction(V)
    b = assemble(dot(Constant([0.0]*mesh.geometry().dim()), v)*dx)
    if rank == 0:
        ps = PointSource(V, point, 10.0)
    else:
        ps = PointSource(V, [])
    ps.apply(b)

    # Checks array sums to correct value
    b_sum = b.sum()
    assert round(b_sum - 10.0*V.num_sub_spaces()) == 0

    # Checks point source is added to correct part of the array
    v2d = vertex_to_dof_map(V)
    for v in vertices(mesh):
        if near(v.midpoint().distance(point), 0.0):
            for spc_idx in range(V.num_sub_spaces()):
                ind = v2d[v.index()*V.num_sub_spaces() + spc_idx]
                if ind < len(b.get_local()):
                    assert np.round(b.get_local()[ind] - 10.0) == 0
def test_pointsource_matrix_second_constructor(mesh, point):
    """Tests point source when given different constructor PointSource(V1,
    V2, point, mag) with a matrix and when placed at a node for 1D, 2D
    and 3D. Global points given to constructor from rank 0
    processor. Currently only implemented if V1=V2.

    """

    V1 = FunctionSpace(mesh, "CG", 1)
    V2 = FunctionSpace(mesh, "CG", 1)

    rank = MPI.rank(mesh.mpi_comm())
    u, v = TrialFunction(V1), TestFunction(V2)
    w = Function(V1)
    A = assemble(Constant(0.0)*u*v*dx)
    if rank == 0:
        ps = PointSource(V1, V2, point, 10.0)
    else:
        ps = PointSource(V1, V2, [])
    ps.apply(A)

    # Checks array sums to correct value
    a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array()))
    assert round(a_sum - 10.0) == 0

    # Checks point source is added to correct part of the array
    A.get_diagonal(w.vector())
    v2d = vertex_to_dof_map(V1)
    for v in vertices(mesh):
        if near(v.midpoint().distance(point), 0.0):
            ind = v2d[v.index()]
            if ind < len(A.array()):
                assert np.round(w.vector()[ind] - 10.0) == 0
Exemple #6
0
def entity_to_dofs(V):
    assert isinstance(V, d.FunctionSpaceBase)
    mesh = V.mesh()
    dim = mesh.topology().dim()
    dm = V.dofmap()
    if V.ufl_element().family() == "Lagrange":
        return d.vertex_to_dof_map(V)

    # FIXME: np.uintp?
    # Create an array
    num_entity_dofs = dm.num_entity_dofs(dim)
    entity_to_dof = np.zeros(mesh.num_cells()*num_entity_dofs, np.intc)
    num_fields = V.num_sub_spaces()
    if num_fields > 0:
        dms = [V.sub(i).dofmap() for i in range(num_fields)]
    else:
        num_fields = 1
        dms = [dm]

    for cell in d.cells(mesh):
        index = cell.index()
        for field_ind, dm_l in enumerate(dms):
            entity_to_dof[index*num_entity_dofs+field_ind:(index+1)*\
                          num_entity_dofs+field_ind:num_fields] = \
                          dms[field_ind].cell_dofs(index)

    return entity_to_dof
Exemple #7
0
def transfer_vertex_function(mesh_fine, mesh_foo_coarse, output=VertexFunction):
    '''
    Assuming that mesh_fine is created by meshing around the mesh underlying
    mesh_foo_coarse this function interpolates the data from mesh_foo_coarse
    '''
    assert isinstance(mesh_fine, EmbeddedMesh)
    mesh_fine = mesh_fine.mesh  # FIXME: remove when EmbeddedMesh <: Mesh
    assert mesh_fine.topology().dim() == 1 and mesh_fine.geometry().dim() > 1
    
    mesh = mesh_foo_coarse.mesh()
    assert mesh.topology().dim() == 1 and mesh.geometry().dim() > 1

    # The strategy here is to interpolate into a CG1 function on mesh_fine
    # and then turn it to vertex function. NOTE: consider CG1 as function
    # for it is easier to get e.g. DG0 (midpoint values) out of it
    Vf = FunctionSpace(mesh_fine, 'CG', 1)
        
    assert mesh_foo_coarse.cpp_value_type() == 'double'
    assert mesh_foo_coarse.dim() == 0
    mesh_coarse = mesh_foo_coarse.mesh()
    Vc = FunctionSpace(mesh, 'CG', 1)
    fc = Function(Vc)
    # Fill the data
    fc.vector().set_local(mesh_foo_coarse.array()[dof_to_vertex_map(Vc)])
    fc.vector().apply('insert')

    ff = interpolate(fc, Vf)

    if output == Function: return ff
    
    # Combe back to vertex function
    vertex_foo = VertexFunction('double', mesh_fine, 0.0)
    vertex_foo.set_values(ff.vector().array()[vertex_to_dof_map(Vf)])
        
    return vertex_foo
Exemple #8
0
 def add_function_group(self, functions, key, *, scale_to_one=False):
     group = self.file.create_group(key)
     index_map = dolfin.vertex_to_dof_map(functions[0].function_space())
     if scale_to_one:
         for ii, uu in enumerate(functions):
             data = uu.vector()[index_map]
             umin = numpy.min(data)
             umax = numpy.max(data)
             if umax < -umin:
                 data /= -umin
             elif 0 < umax:
                 data /= umax
             group.create_dataset(f'{ii}',
                                  data.shape,
                                  data=data,
                                  compression=self.compression)
     else:
         for ii, uu in enumerate(functions):
             data = uu.vector()[index_map]
             group.create_dataset(f'{ii}',
                                  data.shape,
                                  data=data,
                                  compression=self.compression)
     if data.shape[0] == self.num_vertices:
         self.scalar_groups.append(key)
     else:
         assert (data.shape[0] / self.num_vertices == self.basedim)
         self.vector_groups.append(key)
Exemple #9
0
    def __init__(self, V, points, values, tol=1e-5):
        if V.component().shape[0] > 0:  # V is subspace
            V = V.collapse()
        self.V = V
        if callable(values):
            self.values = [values(p) for p in points]
        else:
            self.values = values
        self.points = points
        self.bc_f = dolfin.Function(V)
        mesh = V.mesh()

        co = mesh.coordinates()
        dim = co.shape[1]
        dof_map = dolfin.vertex_to_dof_map(V)
        node_set = set()
        bc_values = self.bc_f.vector().array()
        for p, v in zip(points, self.values):
            wh = np.where(sum(
                (co[:, j] - p[j])**2 for j in range(dim)) < tol)[0]
            if wh.shape[0]:
                i = wh[0]
                bc_values[dof_map[i]] = v
                node_set.add(i)
                #print "found:", p
            else:
                pass
                #print "not found:", p
        print "Found %d of %d points." % (len(node_set), len(points))

        self.bc_f.vector().set_local(bc_values)
        self.bc_f.vector().apply("insert")  # TODO: what does this do?
        self.dof_set = np.array(dof_map[list(node_set)], dtype="intc")
Exemple #10
0
def test_pointsource_vector_fs(mesh, point):
    """Tests point source when given constructor PointSource(V, point,
    mag) with a vector for a vector function space that isn't placed
    at a node for 1D, 2D and 3D. Global points given to constructor
    from rank 0 processor.

    """

    rank = MPI.rank(mesh.mpi_comm())
    V = VectorFunctionSpace(mesh, "CG", 1)
    v = TestFunction(V)
    b = assemble(dot(Constant([0.0] * mesh.geometry().dim()), v) * dx)
    if rank == 0:
        ps = PointSource(V, point, 10.0)
    else:
        ps = PointSource(V, [])
    ps.apply(b)

    # Checks array sums to correct value
    b_sum = b.sum()
    assert round(b_sum - 10.0 * V.num_sub_spaces()) == 0

    # Checks point source is added to correct part of the array
    v2d = vertex_to_dof_map(V)
    for v in vertices(mesh):
        if near(v.midpoint().distance(point), 0.0):
            for spc_idx in range(V.num_sub_spaces()):
                ind = v2d[v.index() * V.num_sub_spaces() + spc_idx]
                if ind < len(b.get_local()):
                    assert np.round(b.get_local()[ind] - 10.0) == 0
Exemple #11
0
def test_pointsource_matrix_second_constructor(mesh, point):
    """Tests point source when given different constructor PointSource(V1,
    V2, point, mag) with a matrix and when placed at a node for 1D, 2D
    and 3D. Global points given to constructor from rank 0
    processor. Currently only implemented if V1=V2.

    """

    V1 = FunctionSpace(mesh, "CG", 1)
    V2 = FunctionSpace(mesh, "CG", 1)

    rank = MPI.rank(mesh.mpi_comm())
    u, v = TrialFunction(V1), TestFunction(V2)
    w = Function(V1)
    A = assemble(Constant(0.0) * u * v * dx)
    if rank == 0:
        ps = PointSource(V1, V2, point, 10.0)
    else:
        ps = PointSource(V1, V2, [])
    ps.apply(A)

    # Checks array sums to correct value
    a_sum = MPI.sum(mesh.mpi_comm(), np.sum(A.array()))
    assert round(a_sum - 10.0) == 0

    # Checks point source is added to correct part of the array
    A.get_diagonal(w.vector())
    v2d = vertex_to_dof_map(V1)
    for v in vertices(mesh):
        if near(v.midpoint().distance(point), 0.0):
            ind = v2d[v.index()]
            if ind < len(A.array()):
                assert np.round(w.vector()[ind] - 10.0) == 0
Exemple #12
0
def _inputsort(obj):
    # def _inputsort_dolfin(obj):
    import dolfin

    u = None
    mesh = None
    if not utils.isSequence(obj):
        obj = [obj]

    for ob in obj:
        inputtype = str(type(ob))

        # printc('inputtype is', inputtype, c=2)

        if "vedo" in inputtype:  # skip vtk objects, will be added later
            continue

        if "dolfin" in inputtype or "ufl" in inputtype:
            if "MeshFunction" in inputtype:
                mesh = ob.mesh()

                if ob.dim() > 0:
                    printc('MeshFunction of dim>0 not supported.', c='r')
                    printc('Try e.g.:  MeshFunction("size_t", mesh, 0)',
                           c='r',
                           italic=1)
                    printc('instead of MeshFunction("size_t", mesh, 1)',
                           c='r',
                           strike=1)
                else:
                    #printc(ob.dim(), mesh.num_cells(), len(mesh.coordinates()), len(ob.array()))
                    V = dolfin.FunctionSpace(mesh, "CG", 1)
                    u = dolfin.Function(V)
                    v2d = dolfin.vertex_to_dof_map(V)
                    u.vector()[v2d] = ob.array()
            elif "Function" in inputtype or "Expression" in inputtype:
                u = ob
            elif "ufl.mathfunctions" in inputtype:  # not working
                u = ob
            elif "Mesh" in inputtype:
                mesh = ob
            elif "algebra" in inputtype:
                mesh = ob.ufl_domain()
                #print('algebra', ob.ufl_domain())

    if u and not mesh and hasattr(u, "function_space"):
        V = u.function_space()
        if V:
            mesh = V.mesh()
    if u and not mesh and hasattr(u, "mesh"):
        mesh = u.mesh()

    #printc('------------------------------------')
    #printc('mesh.topology dim=', mesh.topology().dim())
    #printc('mesh.geometry dim=', mesh.geometry().dim())
    #if u: printc('u.value_rank()', u.value_rank())
    #if u and u.value_rank(): printc('u.value_dimension()', u.value_dimension(0)) # axis=0
    ##if u: printc('u.value_shape()', u.value_shape())
    return (mesh, u)
Exemple #13
0
def _inputsort_dolfinx(obj):  # dolfinx
    import dolfin

    u = None
    mesh = None
    if not utils.isSequence(obj):
        obj = [obj]

    for ob in obj:
        inputtype = str(type(ob))
        #print('inputtype is', inputtype)

        if "vtk" in inputtype:  # skip vtk objects, will be added later
            continue

        if "dolfin" in inputtype or "ufl" in inputtype:
            if "MeshFunction" in inputtype:
                mesh = ob.mesh  # dolfin 2019.2

                if ob.dim > 0:
                    print('MeshFunction of dim>0 not supported.')
                    print('Try e.g.:  MeshFunction("size_t", mesh, 0)')
                    print('instead of MeshFunction("size_t", mesh, 1)')
                else:
                    #print(ob.dim, mesh.num_cells, len(mesh.coordinates, len(ob.array()))
                    V = dolfin.FunctionSpace(mesh, "CG", 1)
                    u = dolfin.Function(V)
                    v2d = dolfin.vertex_to_dof_map(V)
                    u.vector[v2d] = ob.array
            elif "Function" in inputtype or "Expression" in inputtype:
                u = ob
                mesh = ob.function_space.mesh
            elif "Mesh" in inputtype:
                mesh = ob
            elif "algebra" in inputtype:
                mesh = ob.ufl_domain
                #print('algebra', ob.ufl_domain)

        if "str" in inputtype:
            mesh = dolfin.Mesh(ob)

    if u and not mesh and hasattr(u, "function_space"):
        V = u.function_space
        if V:
            mesh = V.mesh

    if u and not mesh and hasattr(u, "mesh"):
        mesh = u.function_space.mesh

    print('------------------------------------')
    print('mesh.topology dim=', mesh.topology.dim)
    print('mesh.geometry dim=', mesh.geometry.dim)
    if u: print('u.value_rank', u.value_rank)
    if u and u.value_rank:
        print('u.value_dimension', u.value_dimension(0))  # axis=0
    if u: print('u.value_shape', u.value_shape())
    return (mesh, u)
Exemple #14
0
def mesh_vertex_to_dof(V, species_index, index):
    num_species = V.num_sub_spaces()
    if num_species == 0: num_species = 1

    mapping = d.vertex_to_dof_map(V)

    mapping = mapping[range(species_index, len(mapping), num_species)]

    return [mapping[x] for x in index]
Exemple #15
0
    def extract_coupling_boundary_vertices1(self, function_space):
        """Extracts verticies which lay on the boundary. Currently handles 2D
        case properly, 3D is circumvented.

        :raise Exception: if no correct coupling interface is defined
        :return: stack of verticies
        """
        n = 0
        local_dofs = []
        vertices_x = []
        vertices_y = []
        if self._dimensions == 3:
            vertices_z = []
        con = []

        if not issubclass(type(self._coupling_subdomain), SubDomain):
            raise Exception("no correct coupling interface defined!")

        mesh = function_space.mesh()
        v2d = vertex_to_dof_map(function_space)
        value_size = function_space.ufl_element().value_size()
        for f in facets(mesh):
            interface = True
            #if f.exterior():
            for v in vertices(f):
                if self._dimensions == 2:
                    if not self._coupling_subdomain.inside(
                        [v.x(0), v.x(1)], True):
                        interface = False
                elif self._dimensions == 3:
                    if not self._coupling_subdomain.inside(
                        [v.x(0), v.x(1), v.x(2)], True):
                        interface = False
            #else:
            #    interface=False
            if interface:
                for v in vertices(f):
                    for ii in range(value_size):
                        local_dof = v2d[value_size * v.index() + ii]
                        if ii == 0:
                            con.append(local_dof)
                        if local_dof not in local_dofs:
                            local_dofs.append(local_dof)
                            if ii == 0:
                                n += 1
                                vertices_x.append(v.x(0))
                                vertices_y.append(v.x(1))
                                if self._dimensions == 3:
                                    vertices_z.append(v.x(2))

        if self._dimensions == 2:
            return np.column_stack([vertices_x,
                                    vertices_y]), n, local_dofs, con
        elif self._dimensions == 3:
            return np.column_stack([vertices_x, vertices_y,
                                    vertices_z]), n, local_dofs, con
Exemple #16
0
def u_to_matlab(mesh, u, name="u"):
    # save real-valued P1 Function u at the mesh nodes to matlab arrays X, U
    # X = mesh.coordinates() = [x1_1, .., x1_d; ...; xN_1, .., xN_d]
    # U = u(X)
    X = mesh.coordinates()
    v2d = dolfin.vertex_to_dof_map(u.function_space())
    U = u.vector()[v2d]
    from scipy.io import savemat
    dic = {"X": X, "U": U[:, None]}
    savemat("%s.mat" % name, dic)
Exemple #17
0
def eikonal_1d(mb, p0=0, function=None):
    "Compute distance from p0 on set of edges"

    # edge-to-vertex connectivity
    EE = np.zeros((mb.num_cells(), mb.num_vertices()), dtype=bool)
    for e in edges(mb):
        EE[e.index(), e.entities(0)] = True

    # vertex-to-vertex connectivity (via edges)
    PP = EE.T @ EE
    np.fill_diagonal(PP, False)

    # initial solution is inf everywhere
    sol = np.empty(PP.shape[0])
    sol.fill(np.inf)

    # initial conditions
    active = deque([p0])
    sol[p0] = 0.0

    # fast marching on edges
    x = mb.coordinates()
    while active:
        curr = active.pop()
        neig = np.where(PP[curr, :])[0]
        ll = sol[curr] + np.linalg.norm(x[neig, :] - x[curr, :], axis=1)
        up = neig[ll < sol[neig]]
        active.extend(up)
        sol[neig] = np.minimum(sol[neig], ll)

    # return solution
    if function is None:
        P1e = FiniteElement("CG", mb.ufl_cell(), 1)
        Ve = FunctionSpace(mb, P1e)
        function = Function(Ve)
        function.vector()[vertex_to_dof_map(Ve)] = sol
        return function
    else:
        Ve = function.function_space()
        function.vector()[vertex_to_dof_map(Ve)] = sol
Exemple #18
0
    def normalise_dofmap(self):
        """
        Overwrite own field values with normalised ones.

        """
        dofmap = df.vertex_to_dof_map(self.functionspace)
        reordered = self.f.vector().array()[
            dofmap]  # [x1, y1, z1, ..., xn, yn, zn]
        vectors = reordered.reshape(
            (3, -1))  # [[x1, y1, z1], ..., [xn, yn, zn]]
        lengths = np.sqrt(np.add.reduce(vectors * vectors, axis=1))
        normalised = np.dot(vectors.T, np.diag(1 / lengths)).T.ravel()
        vertexmap = df.dof_to_vertex_map(self.functionspace)
        normalised_original_order = normalised[vertexmap]
        self.from_array(normalised_original_order)
Exemple #19
0
def voronoi_length(V, Ld, periodic=True, inv=True, raw=True):
    """
    Returns the length of 1D Voronoi cells centered at the DOFs as a FEniCS
    function. V is the function space for the function to be returned (must be
    CG1), Ld is the size of the domain and periodic indicates it's length.

    See also voronoi_volume() which implements 1D, 2D and 3D using the Voro++
    library. This is an independent 1D implementation for comparison.
    """

    vertices = V.mesh().coordinates()[:, 0]

    # Sort vertices in incresing order
    srt = np.argsort(vertices)
    vertices = vertices[srt]

    # Dual grid has nodes on average positions
    dual = 0.5 * (vertices[1:] + vertices[:-1])

    # For finite non-periodic grid we must add edges
    if not periodic:
        dual = np.concatenate([[0], dual, Ld])

    # Compute volume of Voronoi cells
    volume = dual[1:] - dual[:-1]

    # Add volume of "wrapping" cell for periodic boundaries
    if periodic:
        first = Ld[0] - dual[-1] + dual[0]
        volume = np.concatenate([[first], volume, [first]])

    # volume is now the Voronoi volume for the vertices in mesh
    # sort volume back to same ordering as mesh.coordinates()
    srt_back = np.argsort(srt)
    volume = volume[srt_back]

    if inv:
        volume = volume**(-1)

    # Store as Function using correct dof-ordering.
    v2d = df.vertex_to_dof_map(V)
    dv = df.Function(V)
    dv.vector()[v2d] = volume

    if raw:
        return dv.vector().get_local()
    else:
        return dv
Exemple #20
0
    def coords_and_values(self, t=None):
        """
        If the field is defined on a function space with degrees of freedom
        at mesh vertices only, return a list of mesh coordinates and associated
        field values (in the same order).

        """
        # The function values are defined at mesh nodes only for
        # specific function space families. In finmag, the only families
        # of interest are Lagrange (CG) and Discontinuous Lagrange (DG).
        # Therefore, if the function space is not CG-family-type,
        # values cannot be associated to mesh nodes.
        functionspace_family = self.f.ufl_element().family()
        if functionspace_family == 'Discontinuous Lagrange':
            # Function values are not defined at nodes.
            raise TypeError('The function space is Discontinuous Lagrange '
                            '(DG) family type, for which the function values '
                            'are not defined at mesh nodes.')

        elif functionspace_family == 'Lagrange':
            # Function values are defined at nodes.
            coords = self.functionspace.mesh().coordinates()
            num_nodes = self.functionspace.mesh().num_vertices()
            f_array = self.f.vector().array()  # numpy array
            vtd_map = df.vertex_to_dof_map(self.functionspace)

            value_dim = self.value_dim()
            values = np.empty((num_nodes, value_dim))
            for i in xrange(num_nodes):
                try:
                    values[i, :] = f_array[vtd_map[value_dim * i:value_dim *
                                                   (i + 1)]]
                except IndexError:
                    # This only occurs in parallel and is probably related
                    # to ghost nodes. I thought we could ignore those, but
                    # this doesn't seem to be true since the resulting
                    # array of function values has the wrong size. Need to
                    # investigate.  (Max, 15/05/2014)
                    raise NotImplementedError("TODO")

            if value_dim == 1:
                values.shape = (num_nodes, )  # convert to scalar field
            return coords, values

        else:
            raise NotImplementedError('This method is not implemented '
                                      'for {} family type function '
                                      'spaces.'.format(functionspace_family))
Exemple #21
0
def fem2contour(u):
    mesh = u.function_space().mesh()
    v2d = dolfin.vertex_to_dof_map(u.function_space())

    # extract x and y coordinates of nodes
    x = mesh.coordinates()[:, 0]
    y = mesh.coordinates()[:, 1]
    triangles = mesh.cells()

    # Create triangulation.
    triang = mtri.Triangulation(x, y, triangles)

    # create array of node values from function
    z = u.vector()[v2d]

    # Plot the triangulation.
    plt.figure()
    plt.tricontourf(triang, z)
    def step(self, displacement, theta, B, T):
        # Update BCs and loads
        self.r.displacement = displacement
        self.r.theta = theta
        self.B.assign(dolfin.Constant((0.0, 0.0, B)))
        self.T.assign(dolfin.Constant((0.0, 0.0, T)))

        dolfin.solve(self.F == 0,
                     self.u,
                     self.bcs,
                     J=self.J,
                     form_compiler_parameters={
                         "cpp_optimize": True,
                         "representation": "uflacs"
                     })

        return self.mesh.coordinates() + \
            self.u.vector()[dolfin.vertex_to_dof_map(self.V)].reshape(-1, 3)
Exemple #23
0
def get_voronoi_points(V, Ld, periodic, tol=1e-13):
    """
    Returns the center points (in 3D) of the Voronoi diagram being the dual of
    the mesh of function space V. It also returns the corresponding FEniCS DOF
    index of each point:

        points, indices = get_voronoi_points(V, Ld, periodic)

    Ld is the size of the mesh and periodic is a list of three bools signifying
    whether each dimension is periodic or not.

    Points within tol of the boundary are shifted an amount tol inwards.
    """

    # All center points are vertices in the Delaunay mesh. Let them be 3D.
    mesh = V.mesh()
    N = mesh.num_vertices()
    dim = mesh.geometry().dim()
    points = np.zeros((N, 3))
    points[:, :dim] = mesh.coordinates()  # replace with df.vertices(mesh)?
    dof_indices = df.vertex_to_dof_map(V)

    # Remove vertices on upper periodic boundaries
    i = 0
    while i < len(points):
        if any([
                df.near(a, b, tol) and p
                for a, b, p in zip(points[i], list(Ld), periodic)
        ]):
            points = np.delete(points, [i], axis=0)
            dof_indices = np.delete(dof_indices, [i], axis=0)
        else:
            i = i + 1

    # Shift points on boundary inwards
    for d in range(3):
        points[:, d] = [
            x + tol if df.near(x, 0, tol) else x for x in points[:, d]
        ]
        points[:, d] = [
            x - tol if df.near(x, Ld[d], tol) else x for x in points[:, d]
        ]

    return points, dof_indices
Exemple #24
0
 def __init__(self, a=None, b=None, N=100, domain=None):
     if domain is None:
         domain = nanopores.Interval(a, b)
         domain.addsubdomains(fluid = domain)
         domain.addboundaries(upperb = domain.boundary("right"),
                              lowerb = domain.boundary("left"))
     else:
         a = domain.a[0]
         b = domain.b[0]
     self.a = a
     self.b = b
     self.N = N
     self.domain = domain
     geo = domain.create_geometry(lc=(b-a)/N)
     self.geo = geo
     mesh = geo.mesh
     self.V = dolfin.FunctionSpace(mesh, "CG", 1)
     self.v2d = dolfin.vertex_to_dof_map(self.V)
     self.Z = geo.mesh.coordinates()[:, 0] # numpy array
     self.Zlin = numpy.linspace(a, b, N+1)
Exemple #25
0
def bifurcation_function(mesh, bf, num_edges_bf=1, default=-1):
    '''Each vertex that is bifucation gets value bf[edges@bifurcation]'''
    mesh.init(0, 1)
    e2v, v2e = mesh.topology()(1, 0), mesh.topology()(0, 1)
    x = mesh.coordinates()

    V = df.FunctionSpace(mesh, 'CG', 1)
    v2d = df.vertex_to_dof_map(V)

    values = default * np.ones(V.dim())
    for v in range(mesh.num_vertices()):
        edges = v2e(v)
        if len(edges) > num_edges_bf:
            edges = [x[sorted(e2v(e), key=lambda vi: vi == v)] for e in edges]
            values[v2d[v]] = bf(edges)

    f = df.Function(V)
    f.vector().set_local(values)

    return f
Exemple #26
0
def get_surface_of_3d_function(Vh_2d, z, function):
    for V in Vh_2d.split():
        assert V.ufl_element().degree() == 1
    mesh_coords = Vh_2d.mesh().coordinates().reshape((-1, 2))
    v_2d = dl.vertex_to_dof_map(Vh_2d)
    #v_2d = Vh_2d.dofmap().dofs()
    values = np.zeros(Vh_2d.dim(), dtype=float)
    for ii in range(mesh_coords.shape[0]):
        y = function(mesh_coords[ii, 0], mesh_coords[ii, 1], z)
        if np.isscalar(y):
            stride = 1
        else:
            stride = len(y)
        dofs = [v_2d[stride * ii + jj] for jj in range(stride)]
        #print(dofs,y)
        values[dofs] = y

    function_2d = dla.Function(Vh_2d)
    function_2d.vector()[:] = values
    return function_2d
Exemple #27
0
def voronoi_volume_approx(V, inv=True, raw=True):
    """
    Returns the approximated volume for every Voronoi cell centered at
    the a DOF as a FEniCS function. V is the function space for the function
    to be returned (must be CG1). Works for
    1D, 2D and 3D, with and without periodic boundaries and objects.

    The approximated volume of a Voronoi cell centered at a vertex is the
    sum of the neighboring cells divided by the number of geometric dimensions
    plus one. This approximation is better the closer to equilateral the cells
    are, a feature which is desirable in a FEM mesh anyhow.

    Curiously, the result of this function happens to be exact not only for
    completely equilateral cells, but also for entirely periodic simple
    meshes as created using simple_mesh(). For non-periodic simple meshes it
    becomes inaccurate on the boundary nodes. The total volume of all cells is
    always correct.
    """
    assert V.ufl_element().family() == 'Lagrange'
    assert V.ufl_element().degree() == 1

    n_dofs = V.dim()
    dof_indices = df.vertex_to_dof_map(V)
    volumes = np.zeros(n_dofs)

    # These loops inherently deal with periodic boundaries
    for i, v in enumerate(df.vertices(V.mesh())):
        for c in df.cells(v):
            volumes[dof_indices[i]] += c.volume()

    volumes /= (V.mesh().geometry().dim() + 1)

    if inv:
        volumes = volumes**(-1)

    if raw:
        return volumes
    else:
        dv = df.Function(V)
        dv.vector()[:] = volumes
        return dv
Exemple #28
0
def curve_distance(edge_f, nlayers=4, outside_val=-1):
    '''
    Compute distance (P1) function that has for each vertex distance 
    from curve edge_f == 1.
    '''
    # Want to build a P1 function
    mesh = edge_f.mesh()
    V = df.FunctionSpace(mesh, 'CG', 1)
    d = df.Function(V)
    d_values = d.vector().get_local()
    # Default
    d_values[:] = outside_val

    # Want to set points layer by layer
    v2d = df.vertex_to_dof_map(V)
    layers = layer_neighbor_vertex_generator(edge_f, nlayers=nlayers + 1)

    curve_points = next(layers)
    # On curve is 0
    d_values[v2d[list(curve_points)]] = 0.

    x = mesh.coordinates()
    # For others we need to compute distance from edges
    mesh.init(1, 0)
    e2v = mesh.topology()(1, 0)
    segments = np.row_stack(map(e2v, np.where(edge_f.array() == 1)[0]))
    # In local numbering
    vtx_idx, segments = np.unique(segments.flatten(), return_inverse=True)

    line_mesh = make_line_mesh(x[vtx_idx], segments.reshape((-1, 2)))
    tree = line_mesh.bounding_box_tree()

    for points in map(list, layers):
        d_values[v2d[points]] = np.fromiter(
            (tree.compute_closest_entity(df.Point(x[p]))[1] for p in points),
            dtype=float)
    d.vector().set_local(d_values)

    return d
Exemple #29
0
def funvec2imgseq(v: np.array, m: int, n: int, o: int) -> np.array:
    """Takes values of piecewise linear interpolation of a function at the
    vertices and returns a 3-dimensional array.

    Each degree of freedom corresponds to one pixel in the array of
    size (m, n, o).

    Args:
        v (np.array): Values at vertices of triangle mesh.
        m (int): The number of rows.
        n (int): The number of columns.

    Returns:
        np.array: An array of size (m, n, o).

    """
    # Create image.
    img = np.zeros((m, n, o))

    # Create mesh and function space.
    mesh = UnitCubeMesh(m-1, n-1, o-1)
    mc = mesh.coordinates().reshape((-1, 3))

    # Evaluate function at vertices.
    hx, hy, hz = 1./(m-1), 1./(n-1), 1./(o-1)
    x = np.array(np.round(mc[:, 0]/hx), dtype=int)
    y = np.array(np.round(mc[:, 1]/hy), dtype=int)
    z = np.array(np.round(mc[:, 2]/hz), dtype=int)

    # Create function space and function.
    V = FunctionSpace(mesh, 'CG', 1)

    # Create image from function.
    v2d = vertex_to_dof_map(V)
    values = v[v2d]
    for (i, j, k, v) in zip(x, y, z, values):
        img[i, j, k] = v
    return img
Exemple #30
0
    def _extend_to_full_mesh(self, w):
        """
        The argument `w` should be a vector representing a dolfin Function
        on the mesh belonging to the simulation class. If we are using
        periodic boundary conditions then `w` may have fewer elements than
        there are mesh nodes (because some nodes will be identified). This
        helper function extends `w` to a 'full' vector which has one element
        for each mesh node.
        """
        # XXX TODO: This is a mess; we should accept a dolfin Function instead of a numpy array w
        #           and extract its function space and dofmap from that directly. Or even better,
        #           this should all be handled in the Field class.
        n = len(self.llg.S1.dofmap().dofs())
        dim = len(w.ravel()) // n
        assert(len(w.ravel()) == dim * n)
        w.shape = (-1, n)
        # XXX TODO: The following line assumes that a function with vector shape m x n has the
        #           same dofmap as one with shape 1 x n, which is probably not true in general.
        #           But hopefully this will be solved with the Field class.
        v2d = df.vertex_to_dof_map(self.llg.S1)

        w_extended = w[:, v2d[range(self.mesh.num_vertices())]]
        return w_extended.ravel()
Exemple #31
0
def funvec2img_pb(v: np.array, m: int, n: int) -> np.array:
    """Takes values of piecewise linear interpolation of a function at the
    vertices and returns a 2-dimensional array.

    Each degree of freedom corresponds to one pixel in the array of
    size (m, n).

    Args:
        v (np.array): Values at vertices of triangle mesh.
        m (int): The number of rows.
        n (int): The number of columns.

    Returns:
        np.array: An array of shape (m, n).

    """
    # Create image.
    img = np.zeros((m, n))

    # Create mesh and function space.
    mesh = UnitSquareMesh(m - 1, n - 1)
    xm = mesh.coordinates().reshape((-1, 2))

    # Create function space.
    V = create_function_space(mesh, 'periodic')

    # Evaluate function at vertices.
    hx, hy = 1 / (m - 1), 1 / (n - 1)
    x = np.array(np.round(xm[:, 0] / hx), dtype=int)
    y = np.array(np.round(xm[:, 1] / hy), dtype=int)

    # Create image from function.
    v2d = vertex_to_dof_map(V)
    values = v[v2d]
    for (i, j, v) in zip(x, y, values):
        img[i, j] = v
    return img
Exemple #32
0
def patch_volume(V, inv=True, raw=True):
    """
    Returns an array containing the volumes (or their reciprocal values) of each 
    patch M_j, where M_j is the set of all the cells sharing vertex x_j. 
    """
    assert V.ufl_element().family() == 'Lagrange'
    assert V.ufl_element().degree() == 1

    n_dofs = V.dim()
    dof_indices = df.vertex_to_dof_map(V)
    volumes = np.zeros(n_dofs)

    for i, v in enumerate(df.vertices(V.mesh())):
        for c in df.cells(v):
            volumes[dof_indices[i]] += c.volume()
    if inv:
        volumes = volumes**(-1)

    if raw:
        return volumes
    else:
        dv = df.Function(V)
        dv.vector()[:] = volumes
        return dv
 def gradient_dof_to_vertex(self):
     vertex_to_dof = dolfin.vertex_to_dof_map(self.lattice.get_function_space())
     print vertex_to_dof