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)
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?
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
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)
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")]
def refine(mesh, N=1): for i in range(N): mesh = df.refine(mesh) return mesh