def cyclic3D(u): """ Symmetrize with respect to (xyz) cycle. """ try: nrm = np.linalg.norm(u.vector()) V = u.function_space() assert V.mesh().topology().dim() == 3 mesh1 = Mesh(V.mesh()) mesh1.coordinates()[:, :] = mesh1.coordinates()[:, [1, 2, 0]] W1 = FunctionSpace(mesh1, 'CG', 1) # testing if symmetric bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) test = interpolate(Function(W1, test.vector()), V) assert max(test.vector()) - min(test.vector()) < 1.1 v1 = interpolate(Function(W1, u.vector()), V) mesh2 = Mesh(mesh1) mesh2.coordinates()[:, :] = mesh2.coordinates()[:, [1, 2, 0]] W2 = FunctionSpace(mesh2, 'CG', 1) v2 = interpolate(Function(W2, u.vector()), V) pr = project(u + v1 + v2) assert np.linalg.norm(pr.vector()) / nrm > 0.01 return pr except: print "Cyclic symmetrization failed!" return u
def symmetrize(u, d, sym): """ Symmetrize function u. """ if len(d) == 3: # three dimensions -> cycle XYZ return cyclic3D(u) elif len(d) >= 4: # four dimensions -> rotations in 2D return rotational(u, d[-1]) nrm = np.linalg.norm(u.vector()) V = u.function_space() mesh = Mesh(V.mesh()) # test if domain is symmetric using function equal 0 inside, 1 on boundary # extrapolation will force large values if not symmetric since the flipped # domain is different bc = DirichletBC(V, 1, DomainBoundary()) test = Function(V) bc.apply(test.vector()) if len(d) == 2: # two dimensions given: swap dimensions mesh.coordinates()[:, d] = mesh.coordinates()[:, d[::-1]] else: # one dimension given: reflect mesh.coordinates()[:, d[0]] *= -1 # FIXME functionspace takes a long time to construct, maybe copy? W = FunctionSpace(mesh, 'CG', 1) try: # testing test = interpolate(Function(W, test.vector()), V) # max-min should be around 1 if domain was symmetric # may be slightly above due to boundary approximation assert max(test.vector()) - min(test.vector()) < 1.1 v = interpolate(Function(W, u.vector()), V) if sym: # symmetric pr = project(u + v) else: # antisymmetric pr = project(u - v) # small solution norm most likely means that symmetrization gives # trivial function assert np.linalg.norm(pr.vector()) / nrm > 0.01 return pr except: # symmetrization failed for some reason print "Symmetrization " + str(d) + " failed!" return u
def before_first_compute(self, get): u = get("Velocity") assert len(u) == 2, "Can only compute stream function for 2D problems" V = u.function_space() spaces = SpacePool(V.mesh()) degree = V.ufl_element().degree() V = spaces.get_space(degree, 0) psi = TrialFunction(V) self.q = TestFunction(V) a = dot(grad(psi), grad(self.q)) * dx() self.bc = DirichletBC(V, Constant(0), DomainBoundary()) self.A = assemble(a) self.L = Vector() self.bc.apply(self.A) self.solver = KrylovSolver(self.A, "cg") self.psi = Function(V)
return child_f # ------------------------------------------------------------------- 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()
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