Beispiel #1
0
    def build_mesh(self):
        self.length = 1.
        self.height = 1.

        self.mesh = fe.Mesh()
        editor = fe.MeshEditor()
        editor.open(self.mesh, 'triangle', 2, 2)
        editor.init_vertices(10)
        editor.init_cells(8)
        editor.add_vertex(0, fe.Point(0.5, 0.5))
        editor.add_vertex(1, fe.Point(1., 0.5))
        editor.add_vertex(2, fe.Point(1., 1.))
        editor.add_vertex(3, fe.Point(0.5, 1.))
        editor.add_vertex(4, fe.Point(0., 1.))
        editor.add_vertex(5, fe.Point(0., 0.5))
        editor.add_vertex(6, fe.Point(0., 0.))
        editor.add_vertex(7, fe.Point(0.5, 0.))
        editor.add_vertex(8, fe.Point(1., 0.))
        editor.add_vertex(9, fe.Point(0., 0.5))
        editor.add_cell(0, [0, 1, 3])
        editor.add_cell(1, [1, 2, 3])
        editor.add_cell(2, [0, 3, 4])
        editor.add_cell(3, [0, 4, 5])
        editor.add_cell(4, [0, 9, 7])
        editor.add_cell(5, [6, 7, 9])
        editor.add_cell(6, [0, 7, 8])
        editor.add_cell(7, [0, 8, 1])
        editor.close()

        base_refinement = 4
        self.total_refinement = base_refinement + self.local_refinement_iteration

        for i in range(self.total_refinement):
            self.mesh = fe.refine(self.mesh)
Beispiel #2
0
def refine_near_left_boundary(mesh, cycles):
    """ Refine mesh near the left boundary.
    The usual approach of using SubDomain and EdgeFunction isn't appearing to work
    in 1D, so I'm going to just loop through the cells of the mesh and set markers manually.
    """
    for i in range(cycles):

        cell_markers = fenics.CellFunction("bool", mesh)

        cell_markers.set_all(False)

        for cell in fenics.cells(mesh):

            found_left_boundary = False

            for vertex in fenics.vertices(cell):

                if fenics.near(vertex.x(0), 0.):

                    found_left_boundary = True

            if found_left_boundary:

                cell_markers[cell] = True

                break  # There should only be one such point.

        mesh = fenics.refine(mesh, cell_markers)

    return mesh
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
    def initial_mesh(self):

        self.initial_hot_wall_refinement_cycles = 8

        mesh = self.coarse_mesh()

        for i in range(self.initial_hot_wall_refinement_cycles):

            cell_markers = fenics.MeshFunction("bool", mesh,
                                               mesh.topology().dim(), False)

            cell_markers.set_all(False)

            for cell in fenics.cells(mesh):

                found_left_boundary = False

                for vertex in fenics.vertices(cell):

                    if fenics.near(vertex.x(0), 0.):

                        found_left_boundary = True

                        break

                if found_left_boundary:

                    cell_markers[cell] = True

                    break  # There should only be one such point in 1D.

            mesh = fenics.refine(mesh, cell_markers)

        return mesh
    def refine_initial_mesh(self):
        """ Replace 2D refinement method with 3D method. Perhaps one could make an n-dimensional method. """
        for i in range(self.initial_hot_wall_refinement_cycles):

            cell_markers = fenics.MeshFunction("bool", self.mesh,
                                               self.mesh.topology().dim(),
                                               False)

            for cell in fenics.cells(self.mesh):

                found_left_boundary = False

                for vertex in fenics.vertices(cell):

                    if fenics.near(vertex.x(0), 0.):

                        found_left_boundary = True

                        break

                if found_left_boundary:

                    cell_markers[cell] = True

            self.mesh = fenics.refine(self.mesh, cell_markers)
    def refine_initial_mesh(self):
        """ Locally refine near the hot boundary """
        for i in range(self.initial_hot_boundary_refinement_cycles):

            cell_markers = fenics.MeshFunction("bool", self.mesh,
                                               self.mesh.topology().dim(),
                                               False)

            cell_markers.set_all(False)

            for cell in fenics.cells(self.mesh):

                found_left_boundary = False

                for vertex in fenics.vertices(cell):

                    if fenics.near(vertex.x(0), 0.):

                        found_left_boundary = True

                        break

                if found_left_boundary:

                    cell_markers[cell] = True

                    break  # There should only be one such point in 1D.

            self.mesh = fenics.refine(
                self.mesh, cell_markers)  # Does this break references?
Beispiel #7
0
def adapt_coarse_solution_to_fine_solution(scalar,
                                           coarse_solution,
                                           fine_solution,
                                           element,
                                           absolute_tolerance=1.e-2,
                                           maximum_refinement_cycles=6,
                                           circumradius_threshold=0.01):
    """ Refine the mesh of the coarse solution until the interpolation error tolerance is met. """
    adapted_coarse_mesh = fenics.Mesh(coarse_solution.function_space().mesh())

    adapted_coarse_function_space = fenics.FunctionSpace(
        adapted_coarse_mesh, element)

    adapted_coarse_solution = fenics.Function(adapted_coarse_function_space)

    adapted_coarse_solution.leaf_node().vector(
    )[:] = coarse_solution.leaf_node().vector()

    for refinement_cycle in range(maximum_refinement_cycles):

        cell_markers = fenics.MeshFunction(
            "bool", adapted_coarse_mesh.leaf_node(),
            adapted_coarse_mesh.topology().dim(), False)

        for coarse_cell in fenics.cells(adapted_coarse_mesh.leaf_node()):

            coarse_value = scalar(adapted_coarse_solution.leaf_node(),
                                  coarse_cell.midpoint())

            fine_value = scalar(fine_solution.leaf_node(),
                                coarse_cell.midpoint())

            if (abs(coarse_value - fine_value) > absolute_tolerance):

                cell_markers[coarse_cell] = True

        cell_markers = unmark_cells_below_circumradius(
            adapted_coarse_mesh.leaf_node(), cell_markers,
            circumradius_threshold)

        if any(cell_markers):

            adapted_coarse_mesh = fenics.refine(adapted_coarse_mesh,
                                                cell_markers)

            adapted_coarse_function_space = fenics.FunctionSpace(
                adapted_coarse_mesh, element)

            adapted_coarse_solution = fenics.project(
                fine_solution.leaf_node(),
                adapted_coarse_function_space.leaf_node())

        else:

            break

    return adapted_coarse_solution, adapted_coarse_function_space, adapted_coarse_mesh
def local_refine(mesh, center, r):
    xc, yc = center
    cell_markers = MeshFunction("bool", mesh, mesh.topology().dim())
    for c in cells(mesh):
        mp = c.midpoint()
        cell_markers[c] = sqrt((mp[0] - xc) * (mp[0] - xc) + (mp[1] - yc) *
                               (mp[1] - yc)) < r
    mesh = refine(mesh, cell_markers)
    return mesh
Beispiel #9
0
    def build_mesh(self):
        self.length = 8.
        self.height = 2.
        self.notch_length = 0.2
        self.notch_height = 0.4

        domain = mshr.Polygon([fe.Point(0., 0.), 
                  fe.Point(self.length/2. - self.notch_length/2., 0.),
                  fe.Point(self.length/2., self.notch_height),
                  fe.Point(self.length/2. + self.notch_length/2., 0.),
                  fe.Point(self.length, 0.),
                  fe.Point(self.length, self.height),
                  fe.Point(self.length/2. + self.notch_length/2., self.height),
                  fe.Point(self.length/2., self.height),
                  fe.Point(self.length/2. - self.notch_length/2., self.height),
                  fe.Point(0., self.height)])

        # resolution = 100 if self.local_refinement_iteration == 0 else 200
        # self.mesh = mshr.generate_mesh(domain, resolution)

        self.mesh = mshr.generate_mesh(domain, 100)
        for i in range(self.local_refinement_iteration):
            cell_markers = fe.MeshFunction('bool', self.mesh, self.mesh.topology().dim())
            cell_markers.set_all(False)
            for cell in fe.cells(self.mesh):
                p = cell.midpoint()
                if  p[0] > 14./32.*self.length and p[0] < 18./32.*self.length and p[1] < self.height - self.notch_height:
                    cell_markers[cell] = True
            self.mesh = fe.refine(self.mesh, cell_markers)

        length = self.length
        height = self.height
        notch_length = self.notch_length

        class Upper(fe.SubDomain):
            def inside(self, x, on_boundary):
                # return on_boundary
                return on_boundary and fe.near(x[1], height) 


        class LeftCorner(fe.SubDomain):
            def inside(self, x, on_boundary):
                return fe.near(x[0], 0.) and fe.near(x[1], 0.)

        class RightCorner(fe.SubDomain):
            def inside(self, x, on_boundary):
                return fe.near(x[0], length) and fe.near(x[1], 0.)

        class MiddlePoint(fe.SubDomain):
            def inside(self, x, on_boundary):                    
                # return fe.near(x[0], length/2.) and fe.near(x[1], height)
                return x[0] > length/2. - notch_length/2.  and  x[0] < length/2. + notch_length/2. and fe.near(x[1], height)

        self.upper = Upper()
        self.left = LeftCorner()
        self.right = RightCorner()
        self.middle = MiddlePoint()
    def coarsen(self):
        """ Remesh and refine the new mesh until the interpolation error tolerance is met. 
    
        For simplicity, for now we'll consider only one scalar component of the solution.
        """
        time = 0. + self.old_state.time

        fine_solution = self.state.solution.copy(deepcopy=True)

        self.setup_coarse_mesh()

        for refinement_cycle in range(
                self.coarsening_maximum_refinement_cycles):

            self.setup_function_space()

            self.setup_states()

            self.old_state.time = 0. + time

            self.old_state.solution = fenics.project(
                fine_solution.leaf_node(), self.function_space.leaf_node())

            if refinement_cycle == self.coarsening_maximum_refinement_cycles:

                break

            exceeds_tolerance = fenics.MeshFunction("bool",
                                                    self.mesh.leaf_node(),
                                                    self.mesh.topology().dim(),
                                                    False)

            exceeds_tolerance.set_all(False)

            for cell in fenics.cells(self.mesh.leaf_node()):

                coarse_value = self.old_state.solution.leaf_node()(cell.midpoint())\
                    [self.coarsening_scalar_solution_component_index]

                fine_value = fine_solution.leaf_node()(cell.midpoint())\
                    [self.coarsening_scalar_solution_component_index]

                if (abs(coarse_value - fine_value) >
                        self.coarsening_absolute_tolerance):

                    exceeds_tolerance[cell] = True

            if any(exceeds_tolerance):

                self.mesh = fenics.refine(self.mesh, exceeds_tolerance)

            else:

                break

        self.setup_problem_and_solver()  # We broke important references.
    def refine_mesh(self, tolerance: float) -> Optional[bool]:
        """Generate refined mesh.

        This method locates cells of the mesh where the error of the
        eigenfunction is above a certain threshold and generates a new mesh
        with finer resolution on the problematic regions.

        For a given eigenfunction $u$ with corresponding eigenvalue
        $\lambda$, it must be true that $a(u, v) = \lambda b(u, v)$ for all
        functions $v$. We make $v$ go through all the basis functions on the
        mesh and locate the cells where the previous identity fails to hold.

        Parameters
        ----------
        tolerance : float
            Criterion to determine whether a cell needs to be refined or not.

        Returns
        -------
        refined_mesh : Optional[fenics.Mesh]
            A new mesh derived from `mesh` with higher level of granularity
            on certain regions. If no refinements are needed, None is
            returned.

        """
        ew, ev = self.eigenvalues[1:], self.eigenfunctions[1:]
        dofs_needing_refinement = set()

        # Find all the degrees of freedom needing refinement.
        for k, (l, u) in enumerate(zip(ew, ev)):
            v = fenics.TrialFunction(self.vector_space)
            a, b = self._construct_eigenproblem(u, v)
            A = fenics.assemble(a * fenics.dx)
            B = fenics.assemble(b * fenics.dx)

            error = np.abs((A - l * B).sum())
            indices = np.flatnonzero(error > tolerance)
            dofs_needing_refinement.update(indices)

        if not dofs_needing_refinement:
            return

        # Refine the cells corresponding to the degrees of freedom needing
        # refinement.
        dofmap = self.vector_space.dofmap()
        cell_markers = fenics.MeshFunction('bool', self.mesh,
                                           self.mesh.topology().dim())
        cell_markers.set_all(False)
        for cell in fenics.cells(self.mesh):
            cell_dofs = set(dofmap.cell_dofs(cell.index()))
            if cell_dofs.intersection(dofs_needing_refinement):
                cell_markers[cell] = True

        return fenics.refine(self.mesh, cell_markers)
Beispiel #12
0
import matplotlib.pyplot as plt

config.update("jax_enable_x64", True)
fn.set_log_level(fn.LogLevel.ERROR)

# Create mesh, refined in the center
n = 64
mesh = fn.UnitSquareMesh(n, n)

cf = fn.MeshFunction("bool", mesh, mesh.geometry().dim())
subdomain = fn.CompiledSubDomain(
    "std::abs(x[0]-0.5) < 0.25 && std::abs(x[1]-0.5) < 0.25"
)
subdomain.mark(cf, True)
mesh = fa.Mesh(fn.refine(mesh, cf))

# Define discrete function spaces and functions
V = fn.FunctionSpace(mesh, "CG", 1)
W = fn.FunctionSpace(mesh, "DG", 0)

solve_templates = (fa.Function(W),)
assemble_templates = (fa.Function(V), fa.Function(W))

# Define and solve the Poisson equation
@build_jax_fem_eval(solve_templates)
def fenics_solve(f):
    u = fa.Function(V, name="State")
    v = fn.TestFunction(V)
    F = (ufl.inner(ufl.grad(u), ufl.grad(v)) - f * v) * ufl.dx
    bcs = [fa.DirichletBC(V, 0.0, "on_boundary")]
Beispiel #13
0
def refine(mesh, N=1):

    for i in range(N):
        mesh = df.refine(mesh)

    return mesh