def identity_test(n, shape, subd=I_curve): '''Averaging over indep coords of f''' true = df.Expression('x[2]*x[2]', degree=2) mesh = df.UnitCubeMesh(n, n, n) V = df.FunctionSpace(mesh, 'CG', 2) v = df.interpolate(true, V) f = df.MeshFunction('size_t', mesh, 1, 0) subd.mark(f, 1) line_mesh = EmbeddedMesh(f, 1) Q = average_space(V, line_mesh) q = df.Function(Q) Pi = avg_mat(V, Q, line_mesh, {'shape': shape}) Pi.mult(v.vector(), q.vector()) q0 = true # Error L = df.inner(q0 - q, q0 - q) * df.dx e = q.vector().copy() e.axpy(-1, df.interpolate(q0, Q).vector()) return df.sqrt(abs(df.assemble(L)))
def square_test(n, subd=I_curve): '''Averaging over indep coords of f''' size = 0.1 shape = Square(P=lambda x0: x0 - np.array( [size + size * x0[2], size + size * x0[2], 0]), degree=10) foo = df.Expression('x[2]*((x[0]-0.5)*(x[0]-0.5) + (x[1]-0.5)*(x[1]-0.5))', degree=3) mesh = df.UnitCubeMesh(n, n, n) V = df.FunctionSpace(mesh, 'CG', 3) v = df.interpolate(foo, V) f = df.MeshFunction('size_t', mesh, 1, 0) subd.mark(f, 1) true = df.Expression('x[2]*2./3*(size+size*x[2])*(size+size*x[2])', degree=4, size=size) line_mesh = EmbeddedMesh(f, 1) Q = average_space(V, line_mesh) q = df.Function(Q) Pi = avg_mat(V, Q, line_mesh, {'shape': shape}) Pi.mult(v.vector(), q.vector()) q0 = true # Error L = df.inner(q0 - q, q0 - q) * df.dx e = q.vector().copy() e.axpy(-1, df.interpolate(q0, Q).vector()) return df.sqrt(abs(df.assemble(L)))
def disk_test(n, subd=I_curve): '''Averaging over indep coords of f''' shape = Disk(radius=lambda x0: 0.1 + 0.0 * x0[2] / 2, degree=10) foo = df.Expression('x[2]*((x[0]-0.5)*(x[0]-0.5) + (x[1]-0.5)*(x[1]-0.5))', degree=3) mesh = df.UnitCubeMesh(n, n, n) V = df.FunctionSpace(mesh, 'CG', 3) v = df.interpolate(foo, V) f = df.MeshFunction('size_t', mesh, 1, 0) subd.mark(f, 1) true = df.Expression('x[2]*(0.1+0.0*x[2]/2)*(0.1+0.0*x[2]/2)/2', degree=4) line_mesh = EmbeddedMesh(f, 1) Q = average_space(V, line_mesh) q = df.Function(Q) Pi = avg_mat(V, Q, line_mesh, {'shape': shape}) Pi.mult(v.vector(), q.vector()) q0 = true # Error L = df.inner(q0 - q, q0 - q) * df.dx e = q.vector().copy() e.axpy(-1, df.interpolate(q0, Q).vector()) return df.sqrt(abs(df.assemble(L)))
def sanity_test(n, subd, shape): '''Constant is preserved''' mesh = df.UnitCubeMesh(n, n, n) V = df.FunctionSpace(mesh, 'CG', 2) v = df.interpolate(df.Constant(1), V) f = df.MeshFunction('size_t', mesh, 1, 0) subd.mark(f, 1) line_mesh = EmbeddedMesh(f, 1) Q = average_space(V, line_mesh) q = df.Function(Q) Pi = avg_mat(V, Q, line_mesh, {'shape': shape}) Pi.mult(v.vector(), q.vector()) q0 = df.Constant(1) # Error L = df.inner(q0 - q, q0 - q) * df.dx e = q.vector().copy() e.axpy(-1, df.interpolate(q0, Q).vector()) return df.sqrt(abs(df.assemble(L)))
from xii.meshing.embedded_mesh import EmbeddedMesh import dolfin as df import numpy as np def is_close(a, b=0): return abs(a - b) < 1E-12 mesh = df.UnitCubeMesh(4, 4, 8) u = df.Function(df.FunctionSpace(mesh, 'CG', 2)) # Make 1d f = df.MeshFunction('size_t', mesh, 1, 0) df.CompiledSubDomain('near(x[0], 0.5) && near(x[1], 0.5)').mark(f, 1) line_mesh = EmbeddedMesh(f, 1) # Grow thicker with z ci = Circle(radius=lambda x0: x0[2] / 2., degree=8) reduced = Average(u, line_mesh, ci) f = MeasureFunction(reduced) # Circumnference of the circle true = df.Expression('2*pi*x[2]/2', degree=1) L = df.inner(f - true, f - true) * df.dx assert is_close(df.sqrt(abs(df.assemble(L)))) di = Disk(radius=lambda x0: x0[2] / 2., degree=8) reduced = Average(u, line_mesh, di) f = MeasureFunction(reduced) # Circumnference of the circle true = df.Expression('pi*(x[2]/2)*(x[2]/2)', degree=2)
def mortar_meshes(subdomains, markers, ifacet_iter=None, strict=True, tol=1E-14): ''' Let subdomains a cell function. We assume that domains (cells) marked with the given markers are adjecent and an interface can be defined between these domains which is a continuous curve. Then for each domain we create a (sub)mesh and a single interface mesh which holds a connectivity map of its cells to facets of the submeshes. The submeshes are returned as a list. The connectivity map is of the form submesh.id -> facets. The marking function f of the EmbeddedMesh that is the interface is colored such that f[color] is the interface of meshes (submeshes[m] for m color_map[color]). ''' assert len(markers) > 1 # Need a cell function mesh = subdomains.mesh() tdim = mesh.topology().dim() assert subdomains.dim() == tdim markers = list(markers) # For each facet we want to know which 2 cells share it tagged_iface = defaultdict(dict) if ifacet_iter is None: mesh.init(tdim - 1) ifacet_iter = df.facets(mesh) mesh.init(tdim - 1, tdim) for facet in ifacet_iter: cells = map(int, facet.entities(tdim)) if len(cells) > 1: c0, c1 = cells tag0, tag1 = subdomains[c0], subdomains[c1] if tag0 != tag1 and tag0 in markers and tag1 in markers: # A key of sorted tags if tag0 < tag1: key = (tag0, tag1) # The cells connected to facet order to match to tags value = (c0, c1) else: key = (tag1, tag0) value = (c1, c0) # A facet to 2 cells map for the facets of tagged pair tagged_iface[key][facet.index()] = value # order -> tagged keys color_to_tag_map = tagged_iface.keys() # Set to color which won't be encounred interface = df.MeshFunction('size_t', mesh, tdim - 1, len(color_to_tag_map)) values = interface.array() # Mark facets corresponding to tagged pair by a color for color, tags in enumerate(color_to_tag_map): values[tagged_iface[tags].keys()] = color # Finally create an interface mesh for all the colors interface_mesh = EmbeddedMesh(interface, range(len(color_to_tag_map))) # Try to recogninze the meshes which violates assumptions by counting assert not strict or is_continuous(interface_mesh) # And subdomain mesh for each marker subdomain_meshes = {tag: EmbeddedMesh(subdomains, tag) for tag in markers} # Alloc the entity maps for the embedded mesh interface_map = { subdomain_meshes[tag].id(): [None] * interface_mesh.num_cells() for tag in markers } # THe maps are filled by the following idea. Using marking function # of interface mesh one cat get cells of that color and useing entity # map for (original) mesh map the cells to mesh facet. A color also # corresponds to a pair of tags which identifies the two meshes which # share the facet - facet connected to 2 cells one for each mesh. The # final step is to lean to map submesh cells to mesh cells # local submesh <- global of parent mesh sub_mesh_map = lambda tag: dict( (mesh_c, submesh_c) for submesh_c, mesh_c in enumerate( subdomain_meshes[tag].parent_entity_map[mesh.id()][tdim])) # Thec cell-cell connectivity of each submesh c2c = {tag: sub_mesh_map(tag) for tag in markers} # A connectivity of interface mesh cells to facets of global mesh c2f = interface_mesh.parent_entity_map[mesh.id()][tdim - 1] for color, tags in enumerate(color_to_tag_map): # Precompute for the 2 tags submeshes = [subdomain_meshes[tag] for tag in tags] for cell in df.SubsetIterator(interface_mesh.marking_function, color): cell_index = cell.index() # The corresponding global cell facet facet = c2f[cell_index] # The two cells in global mesh numbering global_cells = tagged_iface[tags][facet] # Let's find the facet in submesh for tag, gc, submesh in zip(tags, global_cells, submeshes): # The map uses local cell local_cell = c2c[tag][gc] mesh_id = submesh.id() found = False for submesh_facet in df.facets(df.Cell(submesh, local_cell)): found = df.near( cell.midpoint().distance(submesh_facet.midpoint()), 0, tol) if found: interface_map[mesh_id][ cell_index] = submesh_facet.index() break # Collapse to list; I want list indexing subdomain_meshes = np.array([subdomain_meshes[m] for m in markers]) color_map = [map(markers.index, tags) for tags in color_to_tag_map] # Parent in the sense that the colored piece of interface # could have been created from mesh interface_mesh.parent_entity_map.update( dict((k, { tdim - 1: v }) for k, v in interface_map.items())) return subdomain_meshes, interface_mesh, color_map