예제 #1
0
def compute_vertex_periodicity(mesh, master, slave, to_master):
    '''Compute mapping from slave vertices to master vertices'''
    f = MeshFunction('size_t', mesh, 0, 0)  # As a vertex function
    master.mark(f, 2)
    slave.mark(f, 3)

    master_vertices = [v.index() for v in SubsetIterator(f, 2)]
    slave_vertices = set(v.index() for v in SubsetIterator(f, 3))

    assert len(master_vertices) == len(slave_vertices), (len(master_vertices),
                                                         len(slave_vertices))

    x = mesh.coordinates()

    error, mapping = 0., {}
    while slave_vertices:
        s = slave_vertices.pop()
        xs = x[s]
        mapped = to_master(xs)
        # Local to master_vertex_x
        master_vertex_x = x[master_vertices]

        dist = np.sqrt(np.sum((master_vertex_x - mapped)**2, axis=1))
        mapped_index = np.argmin(dist)
        # Wrt to vertex numbering
        m = master_vertices[mapped_index]
        mapping[s] = m
        error = max(error, dist[mapped_index])

        master_vertices.remove(m)
    assert not slave_vertices and not master_vertices

    return error, mapping
예제 #2
0
def compute_entity_periodicity(tdim, mesh, master, slave, to_master):
    '''
    Compute mapping from slave tdim entities to master tdim entities

    INPUT:
      mesh = dolfin.Mesh
      master = dolfin.SubDomain instance (to mark master vertices)
      slave = dolfin.SubDomain instance (to mark slave vertices)
      to_mastar = x (a slave vertex coord) -> a master vertex coord

    OUTPUT:
      error = largest distance between master and slave vertex coordinates
      mapping = dict{slave tdim entity index -> master tdim entity index}
    '''
    assert 0 <= tdim < mesh.topology().dim()

    error, vertex_mapping = compute_vertex_periodicity(mesh, master, slave,
                                                       to_master)
    # Done for vertices
    if tdim == 0:
        return error, vertex_mapping

    # Other entities are established using their definition in terms
    # of vertex indices
    f = MeshFunction('size_t', mesh, tdim, 0)
    master.mark(f, 2)
    slave.mark(f, 3)

    master_entities = (e.index() for e in SubsetIterator(f, 2))
    slave_entities = (e.index() for e in SubsetIterator(f, 3))

    mesh.init(tdim, 0)
    e2v = mesh.topology()(tdim, 0)
    # Define in terms of vertices. Invert for look up
    master_vertices = {tuple(sorted(e2v(e))): e for e in master_entities}
    # For slave we define via mapped vertices
    slave_entities = {
        e: tuple(sorted(vertex_mapping[v] for v in e2v(e)))
        for e in slave_entities
    }

    assert len(master_vertices) == len(slave_entities)

    mapping = {}
    while slave_entities:
        s, vertices = slave_entities.popitem()
        # Look up the master entity
        m = master_vertices[vertices]
        mapping[s] = m

        master_vertices.pop(vertices)
    assert not slave_entities and not master_vertices

    return error, mapping
예제 #3
0
def load_data(mesh, mesh_f, dim, data):
    '''
    Represent mesh_f over dim entities of mesh as collection of vertices.
    Can have mesh as mesh function or (h5_file, data_set)
    '''
    try:
        h5_file, data_set = mesh_f
        mf = MeshFunction('size_t', mesh, dim, 0)
        h5_file.read(mf, data_set)
    except ValueError:
        mf = mesh_f
        data_set = '%d dim entites' % mf.dim()
            
    # Mapf for encoding entities as vertices
    mesh.init(dim, 0)
    e2v = mesh.topology()(dim, 0)

    tags = set(mf.array())
    # Don't encode zero - we initialize to it
    if 0 in tags: tags.remove(0)
    info('%s evolves tags %r' % (data_set, tags))

    for tag in tags:
        data[(dim, tag)] = np.array([e2v(e.index()) for e in SubsetIterator(mf, tag)],
                                    dtype='uintp')
    return data
예제 #4
0
def cell_chi(f, marker=1):
    '''
    Let f be a facet function. Build a DG0 function which is such 
    that cell connected to f == marker are 1 and are 0 otherwise.
    '''
    assert f.mesh().topology().dim() == 2
    assert f.dim() == 1

    mesh = f.mesh()
    mesh.init(1, 2)
    f2c = mesh.topology()(1, 2)

    V = FunctionSpace(mesh, 'DG', 0)

    dm = V.dofmap()
    first, last = dm.ownership_range()
    n = last - first

    is_local = lambda i, f=first, l=last: f <= i + f < l

    chi = Function(V)
    values = chi.vector().get_local()
    for facet in SubsetIterator(f, marker):
        fi = facet.index()

        for c in f2c(fi):
            dofs = filter(is_local, dm.cell_dofs(c))
            values[dofs] = 1.
    # Sync
    chi.vector().set_local(values)
    as_backend_type(chi.vector()).update_ghost_values()

    return chi
예제 #5
0
def compute_vertex_periodicity(mesh, master, slave, to_master):
    '''
    Compute mapping from slave vertices to master vertices

    INPUT:
      mesh = dolfin.Mesh
      master = dolfin.SubDomain instance (to mark master vertices)
      slave = dolfin.SubDomain instance (to mark slave vertices)
      to_mastar = x (a slave vertex coord) -> a master vertex coord

    OUTPUT:
      error = largest distance between master and slave vertex coordinates
      mapping = dict{slave vertex index -> master vertex index}
    '''
    f = MeshFunction('size_t', mesh, 0, 0)  # As a vertex function
    master.mark(f, 2)
    slave.mark(f, 3)

    master_vertices = [v.index() for v in SubsetIterator(f, 2)]
    slave_vertices = set(v.index() for v in SubsetIterator(f, 3))

    assert len(master_vertices) == len(slave_vertices), (len(master_vertices),
                                                         len(slave_vertices))

    x = mesh.coordinates()

    error, mapping = 0., {}
    while slave_vertices:
        s = slave_vertices.pop()
        xs = x[s]  # Its coord
        mapped = to_master(xs)  # Coord in master domain
        # Local to master_vertex_x
        master_vertex_x = x[master_vertices]
        # Perform search to find closest master vertex
        dist = np.sqrt(np.sum((master_vertex_x - mapped)**2, axis=1))
        mapped_index = np.argmin(dist)
        # Wrt to vertex numbering
        m = master_vertices[mapped_index]
        mapping[s] = m
        # Do we have a match ?
        error = max(error, dist[mapped_index])
        # Assume we do so no more match possible
        master_vertices.remove(m)
    assert not slave_vertices and not master_vertices

    return error, mapping
예제 #6
0
def DLT_trace_mat(V, TV, trace_mesh=None, tag_data=None):
    '''Inject dofs from facets to DLT'''
    mesh = V.mesh()

    if trace_mesh is None: trace_mesh = TV.mesh()

    fdim = trace_mesh.topology().dim()

    # None means all
    if tag_data is None:
        try:
            marking_function = trace_mesh.marking_function
            tag_data = (marking_function, set(marking_function.array()))
        except AttributeError:
            tag_data = (MeshFunction('size_t', trace_mesh,
                                     trace_mesh.topology().dim(), 0), set(
                                         (0, )))

    trace_mesh_subdomains, tags = tag_data
    # Init/extract the mapping
    # We can get it
    mapping = trace_mesh.parent_entity_map[mesh.id()][
        fdim]  # Map cell of TV to cells of V

    if TV.num_sub_spaces() == 0:
        Tdmaps = [TV.dofmap()]
    else:
        Tdmaps = [TV.sub(i).dofmap() for i in range(TV.num_sub_spaces())]

    if V.num_sub_spaces() == 0:
        dmap = V.dofmap()
        facet2dofs = [dmap.entity_dofs(mesh, fdim)]
    else:
        facet2dofs = [
            V.sub(i).dofmap().entity_dofs(mesh, fdim)
            for i in range(V.num_sub_spaces())
        ]

    assert len(Tdmaps) == len(facet2dofs)

    # Only look at tagged cells
    trace_cells = list(
        itertools.chain(*[
            map(operator.methodcaller('index'),
                SubsetIterator(trace_mesh_subdomains, tag)) for tag in tags
        ]))

    # Rows
    with petsc_serial_matrix(TV, V) as mat:

        for Tdmap, facet2dof in zip(Tdmaps, facet2dofs):
            for trace_cell in trace_cells:
                trace_dof, = Tdmap.cell_dofs(trace_cell)
                DLT_dof = facet2dof[mapping[trace_cell]]
                mat.setValues([trace_dof], [DLT_dof], [1.],
                              PETSc.InsertMode.INSERT_VALUES)
    return mat
예제 #7
0
def compute_entity_periodicity(tdim, mesh, master, slave, to_master):
    '''Mapping from slave entities of tdim to master'''
    assert 0 <= tdim < mesh.topology().dim()

    _, vertex_mapping = compute_vertex_periodicity(mesh, master, slave,
                                                   to_master)
    # Done for vertices
    if tdim == 0:
        return vertex_mapping

    f = MeshFunction('size_t', mesh, tdim, 0)
    master.mark(f, 2)
    slave.mark(f, 3)

    master_entities = (e.index() for e in SubsetIterator(f, 2))
    slave_entities = (e.index() for e in SubsetIterator(f, 3))

    mesh.init(tdim, 0)
    e2v = mesh.topology()(tdim, 0)
    # Define in terms of vertices. Invert for loopup
    master_vertices = {tuple(sorted(e2v(e))): e for e in master_entities}
    # For slave we define via mapped vertices
    slave_entities = {
        e: tuple(sorted(vertex_mapping[v] for v in e2v(e)))
        for e in slave_entities
    }

    assert len(master_vertices) == len(slave_entities)

    mapping = {}
    while slave_entities:
        s, vertices = slave_entities.popitem()

        m = master_vertices[vertices]
        mapping[s] = m

        master_vertices.pop(vertices)
    assert not slave_entities and not master_vertices

    return mapping
예제 #8
0
def analyse_connectivity(mesh, edge_f, subdomain):
    '''
    Compute connectivity between vertices of mesh and its edges that are marked
    by edge function with value of subdomain.
    '''
    # We are only interested in gdim == tdim meshes
    gdim = mesh.geometry().dim()
    tdim = mesh.topology().dim()
    assert gdim == tdim and tdim > 1

    # And building 1d in gdim meshes
    try:
        edim = edge_f.dim()
        assert edim == 1
        edges = SubsetIterator(edge_f, subdomain)

    except AttributeError:
        assert isinstance(edge_f, list)
        # Recreate edges from list
        mesh.init(1)
        edges = (Edge(mesh, index) for index in edge_f)

    # First compute connectivity edge <--> vertex for edge, vertex on edge_f
    mesh.init(1, 0)
    topology = mesh.topology()
    # Connect between all edge->c of mesh
    all_edge_vertex_c = topology(1, 0)

    # Connectivity edge->vertex on interval mesh
    # Edge function - extract marked
    # if isinstance(edge_f, MeshFunction):
    edge_vertex_c = dict(
        (edge.index(), set(all_edge_vertex_c(edge.index()))) for edge in edges)
    # Only marked are given in list
    # else:
    #     edge_vertex_c = dict((edge, set(all_edge_vertex_c(edge)))
    #                          for edge in edge_f)

    assert len(edge_vertex_c), 'No edges with value %d' % subdomain

    # Connectivity vertex->edge on interval mesh
    vertex_edge_c = defaultdict(list)
    for edge, vertices in edge_vertex_c.iteritems():
        for vertex in vertices:
            vertex_edge_c[vertex].append(edge)

    return edge_vertex_c, vertex_edge_c
예제 #9
0
def dof_chi(f, V, marker=1):
    '''
    Let f be a an edge function. Build a function in V which is such 
    that all dofs where f == marker are 1 and are 0 otherwise.
    '''
    tdim = f.mesh().topology().dim()
    assert f.dim() == 1

    assert V.mesh().id() == f.mesh().id()
    assert V.ufl_element().family() == 'Lagrange'

    mesh = V.mesh()
    mesh.init(1, tdim)
    mesh.init(tdim, 1)
    e2c = mesh.topology()(1, tdim)
    c2e = mesh.topology()(tdim, 1)

    dm = V.dofmap()
    first, last = dm.ownership_range()
    n = last - first

    is_local = lambda i, f=first, l=last: f <= i + f < l

    # Triangle has 3 facets/edges, tet has 6 edges
    nedges = mesh.ufl_cell().num_edges()
    edge_dofs = [dm.tabulate_entity_closure_dofs(1, i) for i in range(nedges)]

    chi = Function(V)
    values = chi.vector().get_local()
    for edge in SubsetIterator(f, marker):
        edgei = edge.index()

        c = e2c(edgei)[0]  # Any cell
        dofs = dm.cell_dofs(c)

        local_edge = c2e(c).tolist().index(edgei)
        dofs = filter(is_local, dofs[edge_dofs[local_edge]])
        values[dofs] = 1.
    # Sync
    chi.vector().set_local(values)
    as_backend_type(chi.vector()).update_ghost_values()

    return chi
예제 #10
0
def convert(msh_file, h5_file, save_mvc=False):
    '''Temporary version of convertin from msh to h5'''
    root, _ = os.path.splitext(msh_file)
    assert os.path.splitext(msh_file)[1] == '.msh'
    assert os.path.splitext(h5_file)[1] == '.h5'

    # Get the xml mesh
    xml_file = '.'.join([root, 'xml'])
    subprocess.call(['dolfin-convert %s %s' % (msh_file, xml_file)], shell=True)
    # Success?
    assert os.path.exists(xml_file)

    mesh = Mesh(xml_file)
    out = HDF5File(mesh.mpi_comm(), h5_file, 'w')
    out.write(mesh, 'mesh')

    print('Mesh has %d cells' % mesh.num_cells())
    print('Mesh size %g %g' % (mesh.hmin(), mesh.hmax()))
    
    # Save ALL data as facet_functions
    names = ('surfaces', 'volumes')
    if not save_mvc:
        for name, region in zip(names, ('facet_region.xml', 'physical_region.xml')):
            r_xml_file = '_'.join([root, region])

            f = MeshFunction('size_t', mesh, r_xml_file)
            print('%d %s with 1' % (sum(1 for _ in SubsetIterator(f, 1)), name))
            out.write(f, name)

        return True

    for name, region in zip(names, ('facet_region.xml', 'physical_region.xml')):
        r_xml_file = '_'.join([root, region])

        f = MeshFunction('size_t', mesh, r_xml_file)
        # With mesh value collection we only store nonzero tags
        mvc = MeshValueCollection('size_t', mesh, f.dim())
        # Fill
        fill_mvc_from_mf(f, mvc)
        # And save
        out.write(mvc, name)
                    
    return True
예제 #11
0
파일: test_tile.py 프로젝트: MiroK/tieler
    def test_tiling(self):

        tile = UnitSquareMesh(2, 2)

        mf = MeshFunction('size_t', tile, tile.topology().dim() - 1, 0)
        CompiledSubDomain('near(x[0], 0.5) || near(x[1], 0.5)').mark(mf, 1)

        mesh_data = {}
        mesh_data = load_data(tile, mf, dim=1, data=mesh_data)

        mesh, mesh_data = TileMesh(tile, shape=(23, 13), mesh_data=mesh_data)
        f = mf_from_data(mesh, mesh_data)[1]

        self.assertTrue(
            np.linalg.norm(mesh.coordinates().min(axis=0) -
                           np.zeros(2)) < 1E-13)

        self.assertTrue(
            np.linalg.norm(mesh.coordinates().max(axis=0) -
                           np.array([23., 13.])) < 1E-13)

        self.assertTrue(23 * 13 * 4 == sum(1 for _ in SubsetIterator(f, 1)))
예제 #12
0
def load_data(mesh, h5_file, data_set, dim, data):
    '''
    Fill the data dictionary with data_set representing mesh function with 
    dim over mesh read from h5_file according to key spec expected by tiling 
    algorithm.
    '''
    mf = MeshFunction('size_t', mesh, dim, 0)
    h5_file.read(mf, data_set)
            
    # Data to evolve
    mesh.init(dim, 0)
    e2v = tile.topology()(dim, 0)

    tags = set(mf.array())
    # Don't evolve zero - we initialize to it
    if 0 in tags: tags.remove(0)
    info('%s evolves tags %r' % (data_set, tags))

    for tag in tags:
        data[(dim, tag)] = np.array([e2v(e.index()) for e in SubsetIterator(mf, tag)],
                                    dtype='uintp')
    return data
예제 #13
0
def cells_of(cell_f, tag):
    '''Cells of tagged volume'''
    return list(
        map(operator.methodcaller('index'), SubsetIterator(cell_f, tag)))
예제 #14
0
def trace_mat_no_restrict(V, TV, trace_mesh=None, tag_data=None):
    '''The first cell connected to the facet gets to set the values of TV'''
    mesh = V.mesh()

    if trace_mesh is None: trace_mesh = TV.mesh()

    fdim = trace_mesh.topology().dim()

    # None means all
    if tag_data is None:
        tag_data = (MeshFunction('size_t', trace_mesh,
                                 trace_mesh.topology().dim(), 0), set((0, )))

    trace_mesh_subdomains, tags = tag_data
    # Init/extract the mapping
    try:
        assert get_entity_map(mesh, trace_mesh, trace_mesh_subdomains, tags)
    except (AssertionError, IndexError):
        warning('Using non-conforming trace')
        # So non-conforming matrix returns PETSc.Mat
        return nonconforming_trace_mat(V, TV)

    # We can get it
    mapping = trace_mesh.parent_entity_map[mesh.id()][
        fdim]  # Map cell of TV to cells of V

    mesh.init(fdim, fdim + 1)
    f2c = mesh.topology()(fdim, fdim + 1)  # Facets of V to cell of V

    # The idea is to evaluate TV's degrees of freedom at basis functions
    # of V
    Tdmap = TV.dofmap()
    TV_dof = DegreeOfFreedom(TV)

    dmap = V.dofmap()
    V_basis_f = FEBasisFunction(V)

    # Only look at tagged cells
    trace_cells = itertools.chain(*[
        itertools.imap(operator.methodcaller('index'),
                       SubsetIterator(trace_mesh_subdomains, tag))
        for tag in tags
    ])

    # Rows
    visited_dofs = [False] * TV.dim()
    # Column values
    dof_values = np.zeros(V_basis_f.elm.space_dimension(), dtype='double')
    with petsc_serial_matrix(TV, V) as mat:

        for trace_cell in trace_cells:
            # We might
            TV_dof.cell = trace_cell
            trace_dofs = Tdmap.cell_dofs(trace_cell)

            # Figure out the dofs of V to use here. Does not matter which
            # cell of the connected ones we pick
            cell = f2c(mapping[trace_cell])[0]
            V_basis_f.cell = cell

            dofs = dmap.cell_dofs(cell)
            for local_T, dof_T in enumerate(trace_dofs):

                if visited_dofs[dof_T]:
                    continue
                else:
                    visited_dofs[dof_T] = True

                # Define trace dof
                TV_dof.dof = local_T

                # Eval at V basis functions
                for local, dof in enumerate(dofs):
                    # Set which basis foo
                    V_basis_f.dof = local

                    dof_values[local] = TV_dof.eval(V_basis_f)

                # Can fill the matrix now
                col_indices = np.array(dofs, dtype='int32')
                # Insert
                mat.setValues([dof_T], col_indices, dof_values,
                              PETSc.InsertMode.INSERT_VALUES)
    return mat
예제 #15
0
def trace_mat_one_restrict(V,
                           TV,
                           restriction,
                           normal,
                           trace_mesh=None,
                           tag_data=None):
    '''
    Compute the trace values using +/- restriction. A + plus is the one 
    for which the vector cell.midpoint - facet.midpoint agrees in orientation
    with the normal on the facet.
    '''
    mesh = V.mesh()
    fdim = mesh.topology().dim() - 1

    if trace_mesh is None: trace_mesh = TV.mesh()

    # None means all
    if tag_data is None:
        tag_data = (MeshFunction('size_t', trace_mesh,
                                 trace_mesh.topology().dim(), 0), set((0, )))
    trace_mesh_subdomains, tags = tag_data

    # Only look at tagged cells
    trace_cells = itertools.chain(*[
        itertools.imap(operator.methodcaller('index'),
                       SubsetIterator(trace_mesh_subdomains, tag))
        for tag in tags
    ])

    # Init/extract entity map
    assert get_entity_map(mesh, trace_mesh, trace_mesh_subdomains, tags)
    # We can get it
    mapping = trace_mesh.parent_entity_map[mesh.id()][
        fdim]  # Map cell of TV to cells of V

    mesh.init(fdim, fdim + 1)
    f2c = mesh.topology()(fdim, fdim + 1)  # Facets of V to cell of V

    # The idea is to evaluate TV's degrees of freedom at basis functions
    # of V
    Tdmap = TV.dofmap()
    TV_dof = DegreeOfFreedom(TV)

    dmap = V.dofmap()
    V_basis_f = FEBasisFunction(V)

    gdim = mesh.geometry().dim()
    # Rows
    visited_dofs = [False] * TV.dim()
    # Column values
    dof_values = np.zeros(V_basis_f.elm.space_dimension(), dtype='double')
    with petsc_serial_matrix(TV, V) as mat:

        for trace_cell in trace_cells:
            TV_dof.cell = trace_cell
            trace_dofs = Tdmap.cell_dofs(trace_cell)

            # Figure out the dofs of V to use here
            facet_cells = f2c(mapping[trace_cell])

            assert 0 < len(facet_cells) < 3
            # Ignore boundary facets
            if len(facet_cells) == 1:
                cell = facet_cells[0]
            # Search which cell has the right sign
            else:
                signs = []
                for fcell in facet_cells:
                    t_mp = Cell(trace_mesh,
                                trace_cell).midpoint().array()[:gdim]
                    mp = Cell(mesh, fcell).midpoint().array()[:gdim]

                    sign = '+' if np.inner(mp -
                                           t_mp, normal(t_mp)) > 0 else '-'
                    signs.append(sign)
                cell = facet_cells[signs.index(restriction)]
            V_basis_f.cell = cell

            dofs = dmap.cell_dofs(cell)
            for local_T, dof_T in enumerate(trace_dofs):

                if visited_dofs[dof_T]:
                    continue
                else:
                    visited_dofs[dof_T] = True

                # Define trace dof
                TV_dof.dof = local_T

                # Eval at V basis functions
                for local, dof in enumerate(dofs):
                    # Set which basis foo
                    V_basis_f.dof = local

                    dof_values[local] = TV_dof.eval(V_basis_f)

                # Can fill the matrix now
                col_indices = np.array(dofs, dtype='int32')
                # Insert
                mat.setValues([dof_T], col_indices, dof_values,
                              PETSc.InsertMode.INSERT_VALUES)
    return mat
예제 #16
0
파일: hein_area.py 프로젝트: MiroK/tieler
    print('Area/Volume %.3f, Area(!port)/Volume %.3f' %
          ((area_port + area_no_port) / volume, area_no_port / volume))

    volume = intra + extra
    print('Area/Volume %.3f, Area(!port)/Volume %.3f' %
          ((area_port + area_no_port) / volume, area_no_port / volume))

    # Mesh size
    mesh.init(2)
    mesh.init(2, 0)
    f2v = mesh.topology()(2, 0)

    tri_area = lambda x: np.linalg.norm(np.cross(x[0] - x[1], x[0] - x[2]), 2
                                        ) / 2
    x = mesh.coordinates()
    areas = [tri_area(x[f2v(f.index())]) for f in SubsetIterator(surfaces, 1)]

    min_l = sqrt(4 * np.min(areas) / sqrt(3))
    max_l = sqrt(4 * np.max(areas) / sqrt(3))

    print('Mesh size %g %g' % (min_l, max_l))
    print('Domain sizes %g %g %g' %
          tuple(np.max(x, axis=0) - np.min(x, axis=0)))

    File('foo.pvd') << volumes
    File('bar.pvd') << surfaces

    map(
        os.remove,
        filter(lambda f: any(f.endswith(ext) for ext in ('.xml', '.msh')),
               os.listdir('.')))
예제 #17
0
    def test_convert_triangle(
            self):  # Disabled because it fails, see FIXME below

        # test no. 1
        from dolfin import Mesh, MPI

        fname = os.path.join(os.path.dirname(__file__), "data", "triangle")
        dfname = fname + ".xml"

        # Read triangle file and convert to a dolfin xml mesh file
        meshconvert.triangle2xml(fname, dfname)

        # Read in dolfin mesh and check number of cells and vertices
        mesh = Mesh(dfname)
        self.assertEqual(mesh.num_vertices(), 96)
        self.assertEqual(mesh.num_cells(), 159)

        # Clean up
        os.unlink(dfname)

        # test no. 2
        from dolfin import MPI, Mesh, MeshFunction, \
                           edges, Edge, faces, Face, \
                           SubsetIterator, facets

        fname = os.path.join(os.path.dirname(__file__), "data",
                             "test_Triangle_3")
        dfname = fname + ".xml"
        dfname0 = fname + ".attr0.xml"

        # Read triangle file and convert to a dolfin xml mesh file
        meshconvert.triangle2xml(fname, dfname)

        # Read in dolfin mesh and check number of cells and vertices
        mesh = Mesh(dfname)
        mesh.init()
        mfun = MeshFunction('double', mesh, dfname0)
        self.assertEqual(mesh.num_vertices(), 58)
        self.assertEqual(mesh.num_cells(), 58)

        # Create a size_t MeshFunction and assign the values based on the
        # converted Meshfunction
        cf = MeshFunction("size_t", mesh, mesh.topology().dim())
        cf.array()[mfun.array() == 10.0] = 0
        cf.array()[mfun.array() == -10.0] = 1

        # Meassure total area of cells with 1 and 2 marker
        add = lambda x, y: x + y
        area0 = reduce(add, (Face(mesh, cell.index()).area() \
                             for cell in SubsetIterator(cf, 0)), 0.0)
        area1 = reduce(add, (Face(mesh, cell.index()).area() \
                             for cell in SubsetIterator(cf, 1)), 0.0)
        total_area = reduce(add, (face.area() for face in faces(mesh)), 0.0)

        # Check that all cells in the two domains are either above or below y=0
        self.assertTrue(
            all(cell.midpoint().y() < 0 for cell in SubsetIterator(cf, 0)))
        self.assertTrue(
            all(cell.midpoint().y() > 0 for cell in SubsetIterator(cf, 1)))

        # Check that the areas add up
        self.assertAlmostEqual(area0 + area1, total_area)

        # Measure the edge length of the two edge domains
        #edge_markers = mesh.domains().facet_domains()
        edge_markers = mesh.domains().markers(mesh.topology().dim() - 1)
        self.assertTrue(edge_markers is not None)
        #length0 = reduce(add, (Edge(mesh, e.index()).length() \
        #                    for e in SubsetIterator(edge_markers, 0)), 0.0)
        length0, length1 = 0.0, 0.0
        for item in list(edge_markers.items()):
            if item[1] == 0:
                e = Edge(mesh, int(item[0]))
                length0 += Edge(mesh, int(item[0])).length()
            elif item[1] == 1:
                length1 += Edge(mesh, int(item[0])).length()

        # Total length of all edges and total length of boundary edges
        total_length = reduce(add, (e.length() for e in edges(mesh)), 0.0)
        boundary_length = reduce(add, (Edge(mesh, f.index()).length() \
                          for f in facets(mesh) if f.exterior()), 0.0)

        # Check that the edges add up
        self.assertAlmostEqual(length0 + length1, total_length)
        self.assertAlmostEqual(length1, boundary_length)

        # Clean up
        os.unlink(dfname)
        os.unlink(dfname0)
예제 #18
0
def trace_mat_no_restrict(V, TV, trace_mesh=None, tag_data=None):
    '''The first cell connected to the facet gets to set the values of TV'''
    mesh = V.mesh()

    if trace_mesh is None: trace_mesh = TV.mesh()

    fdim = trace_mesh.topology().dim()

    # None means all
    if tag_data is None:
        try:
            marking_function = trace_mesh.marking_function
            tag_data = (marking_function, set(marking_function.array()))
        except AttributeError:
            tag_data = (MeshFunction('size_t', trace_mesh,
                                     trace_mesh.topology().dim(), 0), set(
                                         (0, )))

    trace_mesh_subdomains, tags = tag_data
    # Init/extract the mapping
    try:
        assert get_entity_map(mesh, trace_mesh, trace_mesh_subdomains, tags)
    except (AssertionError, IndexError):
        warning('Using non-conforming trace')
        # So non-conforming matrix returns PETSc.Mat
        return nonconforming_trace_mat(V, TV)

    if V.ufl_element().family() == 'HDiv Trace':
        assert V.ufl_element().degree() == 0
        # In this case
        return DLT_trace_mat(V, TV, trace_mesh=trace_mesh, tag_data=tag_data)

    # We can get it
    mapping = trace_mesh.parent_entity_map[mesh.id()][
        fdim]  # Map cell of TV to cells of V

    mesh.init(fdim, fdim + 1)
    f2c = mesh.topology()(fdim, fdim + 1)  # Facets of V to cell of V

    # The idea is to evaluate TV's degrees of freedom at basis functions of V
    Tdmap = TV.dofmap()
    TV_dof = DegreeOfFreedom(TV)

    dmap = V.dofmap()
    V_basis_f = FEBasisFunction(V)

    # Only look at tagged cells
    trace_cells = list(
        itertools.chain(*[
            map(operator.methodcaller('index'),
                SubsetIterator(trace_mesh_subdomains, tag)) for tag in tags
        ]))

    ndofs_elm, nbasis_elm = TV_dof.elm.space_dimension(
    ), V_basis_f.elm.space_dimension()
    local_values = np.zeros((nbasis_elm, ndofs_elm))

    if len(trace_cells) > 10_000:
        print(f'Trace mat {TV.ufl_element()} -> {V.ufl_element()}')
        trace_cells = tqdm.tqdm(trace_cells, total=len(trace_cells))

    rows, cols, values = [], [], []
    # DG spaces don't share rows between cells so we take advantage of
    # this in special branch
    if TV.ufl_element().family() == 'Discontinuous Lagrange':
        for trace_cell in trace_cells:
            TV_dof.cell = trace_cell
            # Many rows at once
            trace_dofs = Tdmap.cell_dofs(trace_cell)
            # Figure out the dofs of V to use here. Does not matter which
            # cell of the connected ones we pick
            cell = f2c(mapping[trace_cell])[0]
            V_basis_f.cell = cell

            # Columns for the rows
            dofs = dmap.cell_dofs(cell)
            for local, dof in enumerate(dofs):
                # Set which basis foo
                V_basis_f.dof = local
                # Get all rows at once
                local_values[local][:] = TV_dof.eval_dofs(V_basis_f)
            # Indices for the filled piece
            rows_ = np.tile(trace_dofs, nbasis_elm)
            cols_ = np.repeat(dofs, ndofs_elm)

            rows.extend(rows_)
            cols.extend(cols_)
            values.extend(local_values.flat)
    # FIXME: Othewise we need to take care of duplicate entrieselse:
    else:
        needs_fill = np.ones(TV.dim(), dtype=bool)

        for trace_cell in trace_cells:
            TV_dof.cell = trace_cell
            # Many rows at once
            trace_dofs = Tdmap.cell_dofs(trace_cell)

            # Don't add duplicates
            unseen = needs_fill[trace_dofs]  # Some will be true and
            # For the future
            needs_fill[trace_dofs[unseen]] = False

            # Figure out the dofs of V to use here. Does not matter which
            # cell of the connected ones we pick
            cell = f2c(mapping[trace_cell])[0]
            V_basis_f.cell = cell

            # Columns for the rows
            dofs = dmap.cell_dofs(cell)
            for local, dof in enumerate(dofs):
                # Set which basis foo
                V_basis_f.dof = local
                # Get all rows at once
                local_values[local][:] = TV_dof.eval_dofs(V_basis_f)
            # Indices for the filled piece
            rows_ = np.tile(trace_dofs[unseen], nbasis_elm)
            cols_ = np.repeat(dofs, sum(unseen))

            rows.extend(rows_)
            cols.extend(cols_)
            values.extend(local_values[:, unseen].flat)

    mat = csr_matrix((values, (rows, cols)), shape=(TV.dim(), V.dim()))

    return PETSc.Mat().createAIJ(comm=PETSc.COMM_WORLD,
                                 size=mat.shape,
                                 csr=(mat.indptr, mat.indices, mat.data))
예제 #19
0
def deactivate_volumes(cell_f, tag, predicate):
    '''Tagged cells of cell_f that satisfy the predicate'''
    return [
        cell.index() for cell in SubsetIterator(cell_f, tag) if predicate(cell)
    ]
예제 #20
0
def union_mesh(meshes, tol=1E-12):
    '''Glue together meshes into a big one.'''
    assert meshes

    num_meshes = len(meshes)
    # Nothing to do
    if num_meshes == 1:
        return meshes[0]
    # Recurse
    if num_meshes > 2:
        return union_mesh([
            union_mesh(meshes[:num_meshes / 2 + 1]),
            union_mesh(meshes[num_meshes / 2 + 1:])
        ])

    gdim, = set(m.geometry().dim() for m in meshes)
    tdim, = set(m.topology().dim() for m in meshes)

    fdim = tdim - 1
    bdries = [MeshFunction('size_t', m, fdim, 0) for m in meshes]
    [DomainBoundary().mark(bdry, 1) for bdry in bdries]
    # We are after boundary vertices of both; NOTE that the assumption
    # here is that the meshes share only the boundary vertices
    [m.init(fdim) for m in meshes]
    [m.init(fdim, 0) for m in meshes]

    bdry_vertices0, bdry_vertices1 = map(
        list,
        (set(np.concatenate([f.entities(0) for f in SubsetIterator(bdry, 1)]))
         for bdry in bdries))

    x0, x1 = [m.coordinates() for m in meshes]

    x1 = x1[bdry_vertices1]
    shared_vertices = {}
    while bdry_vertices0:
        i = bdry_vertices0.pop()
        x = x0[i]
        # Try to match it
        dist = np.linalg.norm(x1 - x, 2, axis=1)
        imin = np.argmin(dist)
        if dist[imin] < tol:
            shared_vertices[bdry_vertices1[imin]] = i
            x1 = np.delete(x1, imin, axis=0)
            del bdry_vertices1[imin]

    mesh0, mesh1 = meshes
    # We make 0 the master - it adds all its vertices
    # The other on add all but those that are not shared
    unshared = list(
        set(range(mesh1.num_vertices())) - set(shared_vertices.keys()))

    merge_x = mesh0.coordinates()
    offset = len(merge_x)
    # Vertices of the merged mesh
    merge_x = np.row_stack([merge_x, mesh1.coordinates()[unshared]])
    # Mapping for cells from meshes
    lg1 = {k: v for v, k in enumerate(unshared, offset)}
    lg1.update(shared_vertices)
    # Collapse to list
    _, lg1 = zip(*sorted(lg1.items(), key=lambda v: v[0]))
    lg1 = np.array(lg1)

    mapped_cells = np.fromiter((lg1[v] for v in np.concatenate(mesh1.cells())),
                               dtype='uintp').reshape((mesh1.num_cells(), -1))
    merged_cells = np.row_stack([mesh0.cells(), mapped_cells])

    merged_mesh = make_mesh(coordinates=merge_x,
                            cells=merged_cells,
                            tdim=tdim,
                            gdim=gdim)

    lg0 = np.arange(mesh0.num_vertices())
    # Mapping from leafs
    if not hasattr(mesh0, 'leafs'):
        merged_mesh.leafs = [(mesh0.id(), lg0)]
    else:
        merged_mesh.leafs = mesh0.leafs

    if not hasattr(mesh1, 'leafs'):
        merged_mesh.leafs.append([mesh1.id(), lg1])
    else:
        for id_, map_ in mesh1.leafs:
            merged_mesh.leafs.append((id_, lg1[map_]))

    return merged_mesh
예제 #21
0
def vtk_surface(surfaces, tag, output, value):
    assert surfaces.dim() == 2

    mesh = surfaces.mesh()
    mesh.init(2, 0)
    f2v = mesh.topology()(2, 0)

    ncells = sum(1 for _ in SubsetIterator(surfaces, tag))
    nvertices = 3 * ncells

    x = mesh.coordinates()

    with open(output, 'w') as f:

        f.write("<?xml version=\"1.0\"?>\n")
        f.write(
            "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n"
        )
        f.write("  <UnstructuredGrid>\n")

        f.write("    <Piece NumberOfPoints=\"%i\" NumberOfCells=\"%i\">\n" %
                (nvertices, ncells))

        f.write("      <Points>\n")
        f.write(
            "        <DataArray type=\"Float32\" Name=\"vertices\" NumberOfComponents=\"3\" format=\"ascii\">\n"
        )

        for e in SubsetIterator(surfaces, tag):
            coords = x[f2v(e.index())]
            for v in coords:
                f.write("%g %g %g " % tuple(v))

        f.write("        </DataArray>\n")
        f.write("      </Points>\n")
        f.write("      <Cells>\n")

        f.write(
            "        <DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">\n"
        )
        f.write(" ".join(map(str, range(nvertices))))
        f.write("        </DataArray>\n")

        f.write(
            "        <DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">\n"
        )
        f.write(' '.join(map(str, range(0, 3 * ncells, 3))))
        f.write("        </DataArray>\n")

        f.write(
            "        <DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">\n"
        )
        f.write('5 ' * ncells)
        f.write('        </DataArray>\n')

        f.write("      </Cells>\n")

        value = '%d ' % value
        print value
        f.write('      <CellData Scalars="tags">\n')
        f.write(
            "        <DataArray type=\"Float32\" Name=\"tags\" format=\"ascii\">\n"
        )
        f.write(value * ncells)
        f.write("        </DataArray>\n")
        f.write("      </CellData>\n")

        f.write("    </Piece>\n")
        f.write("  </UnstructuredGrid>\n")
        f.write("</VTKFile>\n")
예제 #22
0
def test(path, type='mf'):
    '''Evolve the tile in (n, n) pattern checking volume/surface properties'''

    comm = mpi_comm_world()
    h5 = HDF5File(comm, path, 'r')
    tile = Mesh()
    h5.read(tile, 'mesh', False)

    init_container = lambda type, dim: (
        MeshFunction('size_t', tile, dim, 0)
        if type == 'mf' else MeshValueCollection('size_t', tile, dim))

    for n in (2, 4):
        data = {}
        checks = {}
        for dim, name in zip((2, 3), ('surfaces', 'volumes')):
            # Get the collection
            collection = init_container(type, dim)
            h5.read(collection, name)

            if type == 'mvc': collection = as_meshf(collection)

            # Data to evolve
            tile.init(dim, 0)
            e2v = tile.topology()(dim, 0)
            # Only want to evolve tag 1 (interfaces) for the facets.
            data[(dim, 1)] = np.array(
                [e2v(e.index()) for e in SubsetIterator(collection, 1)],
                dtype='uintp')

            if dim == 2:
                check = lambda m, f: assemble(
                    FacetArea(m) * ds(domain=m,
                                      subdomain_data=f,
                                      subdomain_id=1) + avg(FacetArea(m)) *
                    dS(domain=m, subdomain_data=f, subdomain_id=1))
            else:
                check = lambda m, f: assemble(
                    CellVolume(m) * dx(
                        domain=m, subdomain_data=f, subdomain_id=1))

            checks[
                dim] = lambda m, f, t=tile, c=collection, n=n, check=check: abs(
                    check(m, f) - n**2 * check(t, c)) / (n**2 * check(t, c))

        t = Timer('x')
        mesh, mesh_data = TileMesh(tile, (n, n), mesh_data=data)
        info('\tTiling took %g s. Ncells %d, nvertices %d, \n' %
             (t.stop(), mesh.num_vertices(), mesh.num_cells()))

        foos = mf_from_data(mesh, mesh_data)
        # Mesh Functions
        from_mf = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        mvcs = mvc_from_data(mesh, mesh_data)
        foos = as_meshf(mvcs)
        # Mesh ValueCollections
        from_mvc = np.array([checks[dim](mesh, foos[dim]) for dim in (2, 3)])

        assert np.linalg.norm(from_mf - from_mvc) < 1E-13
        # I ignore shared facets so there is bound to be some error in facets
        # Volume should match well
        print from_mf
예제 #23
0
# -------------------------------------------------------------------

if __name__ == '__main__':
    from dolfin import (CompiledSubDomain, DomainBoundary, SubsetIterator,
                        UnitSquareMesh, Facet)
    from xii import EmbeddedMesh

    mesh = UnitSquareMesh(4, 4)
    surfaces = MeshFunction('size_t', mesh, 2, 0)
    CompiledSubDomain('x[0] > 0.5-DOLFIN_EPS').mark(surfaces, 1)

    # What should be trasfered
    f = MeshFunction('size_t', mesh, 1, 0)
    DomainBoundary().mark(f, 1)
    CompiledSubDomain('near(x[0], 0.5)').mark(f, 1)
    # Assign funky colors
    for i, e in enumerate(SubsetIterator(f, 1), 1): f[e] = i

    ch_mesh = EmbeddedMesh(surfaces, 1)
    ch_f = transfer_markers(ch_mesh, f)

    # Every color in child is found in parent and we get the midpoint right
    p_values, ch_values = list(f.array()), list(ch_f.array())

    for ch_value in set(ch_f.array()) - set((0, )):
        assert ch_value in p_values

        x = Facet(mesh, p_values.index(ch_value)).midpoint()
        y = Facet(ch_mesh, ch_values.index(ch_value)).midpoint()
        assert x.distance(y) < 1E-13