Ejemplo n.º 1
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
Ejemplo n.º 2
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))
Ejemplo n.º 3
0
for n in (8, 16, 32):
    mesh = UnitSquareMesh(*(n, ) * 2)

    mesh_fine = UnitSquareMesh(*(3 * n, ) * 2)
    cell_f = MeshFunction('size_t', mesh_fine, 1, 0)
    CompiledSubDomain('near(x[0], 0)').mark(cell_f, 1)
    bmesh = EmbeddedMesh(cell_f, 1)

    V = VectorFunctionSpace(mesh, 'DG', 1)
    bar = Expression(('x[0]', 'x[1]'), degree=1)

    v = interpolate(bar, V)
    Q = VectorFunctionSpace(bmesh, 'DG', 1)

    T = PETScMatrix(nonconforming_trace_mat(V, Q))

    v = interpolate(bar, V)
    q = Function(Q, T * v.vector())

    L = inner(bar[0] - q[0], bar[0] - q[0]) * dx
    print sqrt(abs(assemble(L)))

    L = inner(bar[1] - q[1], bar[1] - q[1]) * dx
    print sqrt(abs(assemble(L)))

    q0, q1 = q.split(deepcopy=True)

    x = bmesh.coordinates()
    y = np.array([q1(xi) for xi in x])
    x = x[:, 1]
Ejemplo n.º 4
0
def trace_mat_no_restrict(V, TV, trace_mesh=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()

    # Init/extract the mapping
    try:
        assert get_entity_map(mesh, trace_mesh)
    except AssertionError:
        warning('Using non-conforming trace')

        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)

    # 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 range(TV.mesh().num_cells()):
            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
Ejemplo n.º 5
0
def trace_mat_no_restrict(V, TV, trace_mesh=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()

    # Init/extract the mapping
    try:
        assert get_entity_map(mesh, trace_mesh)
    except AssertionError:
        warning('Using non-conforming trace')

        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)

    # 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 range(TV.mesh().num_cells()):
            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