def init_submeshes(self): self.oversampled_submeshes = [] self.patch_submeshes = [] self.patch_vertex_parent_maps = [] self.patch_cell_parent_maps = [] for marker in self.markers: patch_submesh = dolfin.SubMesh(self.mesh, marker, 2) self.patch_submeshes.append(patch_submesh) patch_vertex_parent_map = patch_submesh.data().array("parent_vertex_indices", 0) self.patch_vertex_parent_maps.append(patch_vertex_parent_map) patch_cell_parent_map = patch_submesh.data().array("parent_cell_indices", self.basedim) self.patch_cell_parent_maps.append(patch_cell_parent_map) oversampled_marker = dolfin.MeshFunction('size_t', self.mesh, self.basedim, 0) oversampled_marker.array()[numpy.where(marker.array() > 0)] = 1 self.oversampled_submeshes.append(dolfin.SubMesh(self.mesh, oversampled_marker, 1))
def restrictfunc(self,function,submesh): """ Restricts a function in a P1 space to a submesh using the fact that the verticies and DOFS are numbered the same way. A function defined on a P1 space is returned. This will ONLY work for P1 elements For other elements the dolfin FunctionSpace.restrict() should be used when it is implemented. """ wholemesh = function.function_space().mesh() #Since compute_vertex_map only accepts a SubMesh object we need to #create a trivial "SubMesh" of the whole mesh dummymeshfunc = df.MeshFunction("uint",wholemesh,wholemesh.topology().dim()) dummymeshfunc.set_all(1) #This is actually the whole mesh, but compute_vertex_map, only accepts a SubMesh wholesubmesh = df.SubMesh(wholemesh,dummymeshfunc,1) #Mapping from the wholesubmesh to the wholemesh map_to_mesh = wholesubmesh.data().mesh_function("parent_vertex_indices") #This is a dictionary mapping the matching DOFS from a Submesh to a SubMesh vm = df.compute_vertex_map(submesh,wholesubmesh) #Now we want to "restrict" the function to the restricted space restrictedspace = df.FunctionSpace(submesh,"CG",1) restrictedfunction = df.Function(restrictedspace) for index,dof in enumerate(restrictedfunction.vector()): restrictedfunction.vector()[index] = function.vector()[map_to_mesh[vm[index]]] return restrictedfunction
def plot_sliced_mesh(geo, **kwargs): tol = 1e-5 class Back(dolfin.SubDomain): def inside(self, x, on_boundary): return x[1] >= -tol back = dolfin.CellFunction("size_t", geo.mesh, 0) Back().mark(back, 1) submesh = dolfin.SubMesh(geo.mesh, back, 1) dolfin.plot(submesh, **kwargs)
def generate_mesh(self, nx=52, ny=52): """ Generate regular grid mesh instead of triangular mesh on the domain Omega """ sqmesh = dl.UnitSquareMesh(nx=nx - 1, ny=ny - 1) submf = dl.MeshFunction('size_t', sqmesh, sqmesh.topology().dim()) submf.set_all(1) codomain().mark(submf, 0) mesh = dl.SubMesh(sqmesh, submf, 1) return mesh
def _1d2d_mesh(n, m=None): '''Line mesh in 2d''' if m is None: m = n mesh1d = df.UnitSquareMesh(n, m) mesh1d = df.BoundaryMesh(mesh1d, 'exterior') cell_f = df.MeshFunction('size_t', mesh1d, 1, 0) df.CompiledSubDomain('near(x[0], 0) || near(x[1], 0)').mark(cell_f, 1) mesh1d = df.SubMesh(mesh1d, cell_f, 1) return mesh1d
def get_submesh(sim, region=None): """ Return the submesh associated with the given region. """ if region == None: submesh = sim.mesh else: region_id = sim._get_region_id(region) submesh = df.SubMesh(sim.mesh, sim.region_markers, region_id) return submesh
def _1d3d_mesh(n): '''Line mesh in 3d''' mesh1d = df.UnitCubeMesh(n, n, n) cell_f = df.MeshFunction('size_t', mesh1d, 3, 0) df.CompiledSubDomain('x[0] > x[1] - DOLFIN_EPS').mark(cell_f, 1)# mesh1d = df.BoundaryMesh(df.SubMesh(mesh1d, cell_f, 1), 'exterior') cell_f = df.MeshFunction('size_t', mesh1d, 2, 0) df.CompiledSubDomain('near(x[0], x[1])').mark(cell_f, 1) mesh1d = df.SubMesh(mesh1d, cell_f, 1) cell_f = df.MeshFunction('size_t', mesh1d, 2, 0) df.CompiledSubDomain('x[2] < x[1] + DOLFIN_EPS').mark(cell_f, 1) mesh1d = df.BoundaryMesh(df.SubMesh(mesh1d, cell_f, 1), 'exterior') cell_f = df.MeshFunction('size_t', mesh1d, 1, 0) df.CompiledSubDomain('near(x[2], x[1])').mark(cell_f, 1) mesh1d = df.SubMesh(mesh1d, cell_f, 1) return mesh1d
def make_submesh(mesh, use_indices): '''Submesh + mapping of child to parent cell and vertex indices''' length0 = sum(c.volume() for c in df.cells(mesh)) tdim = mesh.topology().dim() f = df.MeshFunction('size_t', mesh, tdim, 0) f.array()[use_indices] = 1 submesh = df.SubMesh(mesh, f, 1) length1 = sum(c.volume() for c in df.cells(submesh)) print_red('Reduced mesh has %g volume of original' % (length1 / length0, )) return (submesh, submesh.data().array('parent_cell_indices', tdim), submesh.data().array('parent_vertex_indices', 0))
def _write_projected_solution(self, i): """ take domain :param str i: and project solution there """ self.sub_mesh = d.SubMesh(self.mesh.mesh, self.mesh.cells, self.mesh.subdomaininfo[i]) V_sub = d.FunctionSpace(self.sub_mesh, self.element) # real part, mumps to avoid memory overflow u_sub = d.project( self.u, V_sub, solver_type=self.data['properties']['project_solver'], preconditioner_type=self.data['properties'] ['project_preconditioner']) u_sub.rename('potential', 'potential') self.datafileXDMF.write(u_sub)
def _write_projected_solution(self, i): """ take domain :param str i: and project solution there """ self.sub_mesh = d.SubMesh(self.mesh.mesh, self.mesh.cells, self.mesh.subdomaininfo[i]) V_sub = d.FunctionSpace(self.sub_mesh, self.element) # real part, mumps to avoid memory overflow # u_sub = d.project(self.u_r, V_sub, solver_type='mumps') u_sub = d.project(self.u.sub(0), V_sub, solver_type='mumps') u_sub.rename('potential real part', 'potential real part sub') self.datafileXDMFreal.write(u_sub) # imag part u_sub.rename('potential imag part', 'potential imag part sub') # u_sub = d.project(self.u_i, V_sub, solver_type='mumps') u_sub = d.project(self.u.sub(1), V_sub, solver_type='mumps') self.datafileXDMFimag.write(u_sub)
def plot_sliced(geo, **params): tol = 1e-5 class Back(dolfin.SubDomain): def inside(self, x, on_boundary): return x[1] >= -tol back = dolfin.CellFunction("size_t", geo.mesh, 0) Back().mark(back, 1) submesh = dolfin.SubMesh(geo.mesh, back, 1) #plot(submesh) bb = geo.mesh.bounding_box_tree() subsub = dolfin.CellFunction("size_t", submesh, 0) sub = geo.subdomains for cell in dolfin.cells(submesh): iparent = bb.compute_first_entity_collision(cell.midpoint()) subsub[cell] = sub[int(iparent)] plot_params = dict(title="sliced geometry with subdomains", elevate=-90., **params) dolfin.plot(subsub, **plot_params)
def compute(u, uh): # We expect u is {tag -> Expression} # The idea is to restict uh to marked subdomains V = uh.function_space() mesh = V.mesh() cell_f = df.MeshFunction('size_t', mesh, mesh.topology().dim(), 0) errors = [] for tag in u: cell_f.set_all(0) # Restriction ... subdomains[tag].mark(cell_f, tag) sub_mesh = df.SubMesh(mesh, cell_f, tag) if not sub_mesh.num_cells(): continue # ... and restrict uh_sub = df.interpolate(uh, df.FunctionSpace(sub_mesh, V.ufl_element())) e_sub = norm_f(u[tag], uh_sub) errors.append(e_sub) # Combine errors from subdomains return np.sqrt(sum(e**2 for e in errors))
def test(self): # Very basic mesh = df.UnitCubeMesh(10, 10, 10) f = df.MeshFunction('size_t', mesh, mesh.topology().dim() - 1, 0) chi = df.CompiledSubDomain('near(x[i], 0.5)', i=0) for i in range(3): setattr(chi, 'i', i) chi.mark(f, i + 1) mesh = EmbeddedMesh(f, [1, 2, 3]) f = mesh.marking_function for i in range(3): mesh_i = df.SubMesh(mesh, f, i + 1) x = mesh_i.coordinates() self.assertTrue(np.linalg.norm(x[:, i] - 0.5) < 1E-13) self.assertTrue( abs(xj) < 1E-13 for j, xj in enumerate(x.min(axis=0)) if j != i) self.assertTrue( abs(xj - 1) < 1E-13 for j, xj in enumerate(x.min(axis=0)) if j != i)
def __init__(self, mesh, get_domain_id, m_vals, Ms, unit_length=1e-9): """ `get_domain_id` is a function of the form (x, y, z) -> id which maps some point coordinates in the mesh to an integer identifying the domain which the point belongs to. """ self.mesh = mesh self.get_domain_id = get_domain_id self.domain_ids = [get_domain_id(pt) for pt in mesh.coordinates()] self.Ms = Field(df.FunctionSpace(mesh, 'DG', 0), Ms) self.unit_length = unit_length #self.rtol = rtol domain_classes = {} for k in self.domain_ids: class DomainK(df.SubDomain): def inside(self, pt, on_boundary): return get_domain_id(pt) == k domain_classes[k] = DomainK() domains = df.CellFunction("size_t", mesh) domains.set_all(0) for k, d in domain_classes.items(): d.mark(domains, k) self.submeshes = [df.SubMesh(mesh, domains, i) for i in self.domain_ids] self.dx = df.Measure("dx")[domains] def m_init(pt): return m_vals[self.get_domain_id(pt)] self.V = df.VectorFunctionSpace(mesh, 'CG', 1, dim=3) self.m = Field(self.V) self.m.set(m_init, normalised=True)
def restricted(self, dofs): from pymor.tools.mpi import parallel if parallel: raise NotImplementedError('SubMesh does not work in parallel') with self.logger.block( f'Restricting operator to {len(dofs)} dofs ...'): if len(dofs) == 0: return ZeroOperator(NumpyVectorSpace(0), NumpyVectorSpace(0)), np.array( [], dtype=np.int) if self.source.V.mesh().id() != self.range.V.mesh().id(): raise NotImplementedError self.logger.info('Computing affected cells ...') mesh = self.source.V.mesh() range_dofmap = self.range.V.dofmap() affected_cell_indices = set() for c in df.cells(mesh): cell_index = c.index() local_dofs = range_dofmap.cell_dofs(cell_index) for ld in local_dofs: if ld in dofs: affected_cell_indices.add(cell_index) continue affected_cell_indices = list(sorted(affected_cell_indices)) if any(i.integral_type() not in ('cell', 'exterior_facet') for i in self.form.integrals()): # enlarge affected_cell_indices if needed raise NotImplementedError self.logger.info('Computing source DOFs ...') source_dofmap = self.source.V.dofmap() source_dofs = set() for cell_index in affected_cell_indices: local_dofs = source_dofmap.cell_dofs(cell_index) source_dofs.update(local_dofs) source_dofs = np.array(sorted(source_dofs), dtype=np.intc) self.logger.info('Building submesh ...') subdomain = df.MeshFunction('size_t', mesh, mesh.geometry().dim()) for ci in affected_cell_indices: subdomain.set_value(ci, 1) submesh = df.SubMesh(mesh, subdomain, 1) self.logger.info('Building UFL form on submesh ...') form_r, V_r_source, V_r_range, source_function_r = self._restrict_form( submesh, source_dofs) self.logger.info('Building DirichletBCs on submesh ...') bc_r = self._restrict_dirichlet_bcs(submesh, source_dofs, V_r_source) self.logger.info('Computing source DOF mapping ...') restricted_source_dofs = self._build_dof_map( self.source.V, V_r_source, source_dofs) self.logger.info('Computing range DOF mapping ...') restricted_range_dofs = self._build_dof_map( self.range.V, V_r_range, dofs) op_r = FenicsOperator(form_r, FenicsVectorSpace(V_r_source), FenicsVectorSpace(V_r_range), source_function_r, dirichlet_bcs=bc_r, parameter_setter=self.parameter_setter, parameters=self.parameters) return (RestrictedFenicsOperator(op_r, restricted_range_dofs), source_dofs[np.argsort(restricted_source_dofs)])
def compute_derrick(self): D = self.physics.D r = Expression('x[0]', degree=self.fem.func_degree) # r^(D-1) rD = Expression('pow(x[0],D-1)', D=D, degree=self.fem.func_degree) mu, M = Constant(self.physics.mu), Constant(self.physics.M) lam = Constant(self.physics.lam) mn = Constant(self.mn) r_values, Phi_values = get_values(self.Phi, output_mesh=True) # the numerical value of the potential energy goes below the machine precision on # its biggest component after some radius (at those radii the biggest component is the vacuum energy) # analytically, we know the integral over that and bigger radii should be close to 0 # to avoid integrating numerical noise (and blowing it up by r^D) we restrict integration # on the submesh where the potential energy is resolved within machine precision # find radius at which potential energy drops below machine precision vacuum_energy = self.physics.mu**4 / (4. * self.physics.lam) eV = lam / 4. * self.Phi**4 - mu**2 / 2. * self.Phi**2 + Constant( vacuum_energy) eV_values = self.physics.lam / 4. * Phi_values**4 - self.physics.mu**2 / 2. * Phi_values**2 + vacuum_energy eV_idx_wrong = np.where(eV_values < d.DOLFIN_EPS * vacuum_energy)[0][0] eV_r_wrong = r_values[eV_idx_wrong] # define a submesh where the potential energy density is resolved class eV_Resolved(SubDomain): def inside(self, x, on_boundary): return x[0] < eV_r_wrong eV_resolved = eV_Resolved() eV_subdomain = d.CellFunction('size_t', self.fem.mesh.mesh) eV_subdomain.set_all(0) eV_resolved.mark(eV_subdomain, 1) eV_submesh = d.SubMesh(self.fem.mesh.mesh, eV_subdomain, 1) # integrate potential energy density E_V = d.assemble(eV * rD * dx(eV_submesh)) E_V /= self.mn**D # get physical distances - integral now has mass dimension 4 - D # kinetic energy - here we are limited by the machine precision on the gradient # the numerical value of the field is limited by the machine precision on the VEV, which # we are going to use as threshold eK_idx_wrong = np.where( abs(Phi_values - self.physics.Vev) < d.DOLFIN_EPS * self.physics.Vev)[0][0] eK_r_wrong = r_values[eK_idx_wrong] # define a submesh where the kinetic energy density is resolved class eK_Resolved(SubDomain): def inside(self, x, on_boundary): return x[0] < eK_r_wrong eK_resolved = eK_Resolved() eK_subdomain = d.CellFunction('size_t', self.fem.mesh.mesh) eK_subdomain.set_all(0) eK_resolved.mark(eK_subdomain, 1) eK_submesh = d.SubMesh(self.fem.mesh.mesh, eK_subdomain, 1) # integrate kinetic energy density eK = Constant(0.5) * self.grad_Phi**2 E_K = d.assemble(eK * rD * dx(eK_submesh)) E_K /= self.mn**D # get physical distances - integral now has mass dimension 4 - D # matter coupling energy erho = self.source.rho / M * self.Phi E_rho = d.assemble( erho * rD * dx) # rescaled rho, and so the integral, has mass dimension 4 - D # integral terms of Derrick's theorem derrick1 = (D - 2.) * E_K + D * (E_V + E_rho) derrick4 = 2. * (D - 2.) * E_K # non-integral terms of Derrick's theorem - these have mass dimension 4 - D derrick2 = self.source.Rho_bar * self.source.Rs**D * \ self.Phi(self.fem.mesh.rs) / self.physics.M derrick3 = self.source.Rho_bar * self.source.Rs**(D+1.) * \ self.grad_Phi(self.fem.mesh.rs) / self.physics.M self.derrick = [derrick1, derrick2, derrick3, derrick4]
def spreadFunction(u, mesh, x_max=None): """ This routine computes the following quantities as a function of the distance x from the inflow: - The centerline velocity: u_cl - The integral jet thickness: L - The spread function (derivative of jet thickness): S - The jet thickness: y_1/2 INPUTS: - the velocity u - the mesh mesh """ boundary_mesh = dl.BoundaryMesh(mesh, "exterior") x = boundary_mesh.coordinates() x_coord = x[np.abs(x[:, 1]) < 1e-9, 0] if x_max is not None: x_coord = x_coord[x_coord <= x_max] e1 = dl.Expression(("1.", "0.")) u1, u2 = u.split(deepcopy=True) Vh_grad = dl.FunctionSpace(mesh, 'RT', 1) grad_u1 = dl.Function(Vh_grad) test = dl.TestFunction(Vh_grad) n = dl.FacetNormal(mesh) dl.solve( dl.inner(grad_u1, test) * dl.dx + u1 * dl.div(test) * dl.dx - u1 * dl.dot(test, n) * dl.ds == 0, grad_u1) axis = dl.AutoSubDomain(lambda x: dl.near(x[1], 0.)) axis_mesh = dl.SubMesh(boundary_mesh, axis) Vh_axis = dl.FunctionSpace(axis_mesh, "CG", 2) u1_axis = dl.interpolate(u1, Vh_axis) Vh_axis_grad = dl.FunctionSpace(axis_mesh, 'CG', 1) du1_dx = dl.Function(Vh_axis_grad) test_axis = dl.TestFunction(Vh_axis_grad) left_point = dl.AutoSubDomain( lambda x, on_boundary: dl.near(x[0], x_coord[0]) and on_boundary) right_point = dl.AutoSubDomain( lambda x, on_boundary: dl.near(x[0], x_coord[-1]) and on_boundary) bb_marker = dl.FacetFunction("size_t", axis_mesh) bb_marker.set_all(0) left_point.mark(bb_marker, 1) right_point.mark(bb_marker, 2) dss = dl.Measure("ds")[bb_marker] dl.solve( du1_dx * test_axis * dl.dx + u1_axis * test_axis.dx(0) * dl.dx + u1_axis * test_axis * dss(1) - u1_axis * test_axis * dss(2) == 0, du1_dx) u_cl = np.zeros(x_coord.shape) L = np.zeros(x_coord.shape) S = np.zeros(x_coord.shape) y_half = np.zeros(x_coord.shape) i = 0 for xi in x_coord: line_segment = dl.AutoSubDomain(lambda x: dl.near(x[0], xi)) markers = dl.FacetFunction("size_t", mesh) markers.set_all(0) line_segment.mark(markers, 1) if i == 0 or (i == (x_coord.shape[0] - 1) and x_max is None): ds = dl.ds[markers] int_u1 = dl.assemble(u1 * ds(1)) int_du1_dx = dl.assemble(dl.dot(grad_u1, e1) * ds(1)) else: dS = dl.dS[markers] int_u1 = dl.assemble(dl.avg(u1) * dS(1)) int_du1_dx = dl.assemble(dl.avg(dl.dot(grad_u1, e1)) * dS(1)) u_cl[i] = u1((xi, 0.)) du_cl_dx = du1_dx((xi, 0.)) L[i] = int_u1 / u_cl[i] S[i] = (int_du1_dx * u_cl[i] - int_u1 * du_cl_dx) / (u_cl[i] * u_cl[i]) y_half[i] = _bisection(u1, 9., 0., .5 * u_cl[i], xi) i += 1 out = np.zeros((x_coord.shape[0], 5), dtype=x_coord.dtype) out[:, 0] = x_coord out[:, 1] = u_cl out[:, 2] = L out[:, 3] = S out[:, 4] = y_half return out
back.mark(facets, 4) coeff = problems.PoissonProblem.default_coefficient problem = problems.PoissonProblem(mesh, coefficients = [coeff(), coeff(aa = 100)], domains = domains, facets = facets) ff = dolfin.Constant(-1.) gg = [(dolfin.Constant(1), 1), (dolfin.Constant(-1), 2)] lower = dolfin.MeshFunction('size_t', mesh, 2, 0) lower_subdomain = dolfin.AutoSubDomain(lambda xx, on: xx[1] > 0) lower_subdomain.mark(lower, 1) h5file = io.H5File('whole_2d', 'w') h5file.set_mesh(mesh) h5file.add_attribute(lower, 'lower') uu = problem.assemble_and_solve(ff, gg) h5file.add_function_group([uu], 'p_variable') h5file.write_xdmf() h5file.close() h5file = io.H5File('lower_2d', 'w') submesh = dolfin.SubMesh(mesh, lower, 1) h5file.set_mesh(submesh) subfacets = dolfin.MeshFunction('size_t', submesh, 1, 0) left.mark(subfacets, 1) right.mark(subfacets, 2) front.mark(subfacets, 3) back.mark(subfacets, 4) uu = problem.assemble_and_solve(ff, gg, mesh = submesh, facets = subfacets) h5file.add_function_group([uu], 'p_variable') h5file.write_xdmf() h5file.close()
def __init__(self, marking_function, markers): if not isinstance(markers, (list, tuple, set)): markers = [markers] base_mesh = marking_function.mesh() assert base_mesh.topology().dim() >= marking_function.dim() # Work in serial only (much like submesh) assert df.MPI.size(base_mesh.mpi_comm()) == 1 gdim = base_mesh.geometry().dim() tdim = marking_function.dim() assert tdim > 0, 'No Embedded mesh from vertices' assert markers, markers # NOTE: treating submesh as a separate case is done for performance # as it seems that pure python as done below is about 2x slower # We reuse a lot of Submesh capabilities if marking by cell_f if base_mesh.topology().dim() == marking_function.dim(): # Submesh works only with one marker so we conform color_array = marking_function.array() color_cells = dict( (m, np.where(color_array == m)[0]) for m in markers) # So everybody is marked as 1 one_cell_f = df.MeshFunction('size_t', base_mesh, tdim, 0) for cells in color_cells.values(): one_cell_f.array()[cells] = 1 # The Embedded mesh now steals a lot from submesh submesh = df.SubMesh(base_mesh, one_cell_f, 1) df.Mesh.__init__(self, submesh) # The entity mapping attribute; # NOTE: At this point there is not reason to use a dict as # a lookup table mapping_0 = submesh.data().array('parent_vertex_indices', 0) mapping_tdim = submesh.data().array('parent_cell_indices', tdim) mesh_key = marking_function.mesh().id() self.parent_entity_map = { mesh_key: { 0: dict(enumerate(mapping_0)), tdim: dict(enumerate(mapping_tdim)) } } # Finally it remains to preserve the markers f = df.MeshFunction('size_t', self, tdim, 0) f_values = f.array() if len(markers) > 1: old2new = dict( list(zip(mapping_tdim, list(range(len(mapping_tdim)))))) for color, old_cells in color_cells.items(): new_cells = np.array([old2new[o] for o in old_cells], dtype='uintp') f_values[new_cells] = color else: f.set_all(next(iter(markers))) self.marking_function = f # Declare which tagged cells are found self.tagged_cells = set(markers) # https://stackoverflow.com/questions/2491819/how-to-return-a-value-from-init-in-python return None # Otherwise the mesh needs to by build from scratch _, e2v = (base_mesh.init(tdim, 0), base_mesh.topology()(tdim, 0)) entity_values = marking_function.array() colorings = [np.where(entity_values == tag)[0] for tag in markers] # Represent the entities as their vertices tagged_entities = np.hstack(colorings) tagged_entities_v = np.array([e2v(e) for e in tagged_entities], dtype='uintp') # Unique vertices that make them up are vertices of our mesh tagged_vertices = np.unique(tagged_entities_v.flatten()) # Representing the entities in the numbering of the new mesh will # give us the cell makeup mapping = dict( list(zip(tagged_vertices, list(range(len(tagged_vertices)))))) # So these are our new cells tagged_entities_v.ravel()[:] = np.fromiter( (mapping[v] for v in tagged_entities_v.flat), dtype='uint') # With acquired data build the mesh df.Mesh.__init__(self) # Fill vertex_coordinates = base_mesh.coordinates()[tagged_vertices] make_mesh(coordinates=vertex_coordinates, cells=tagged_entities_v, tdim=tdim, gdim=gdim, mesh=self) # The entity mapping attribute mesh_key = marking_function.mesh().id() self.parent_entity_map = { mesh_key: { 0: dict(enumerate(tagged_vertices)), tdim: dict(enumerate(tagged_entities)) } } f = df.MeshFunction('size_t', self, tdim, 0) # Finally the inherited marking function. We colored sequentially so if len(markers) > 1: f_ = f.array() offsets = np.cumsum(np.r_[0, list(map(len, colorings))]) for i, marker in enumerate(markers): f_[offsets[i]:offsets[i + 1]] = marker else: f.set_all(next(iter(markers))) self.marking_function = f # Declare which tagged cells are found self.tagged_cells = set(markers)
def __init__(self, marking_function, markers): base_mesh = marking_function.mesh() assert base_mesh.topology().dim() >= marking_function.dim() # Work in serial only (much like submesh) assert df.MPI.size(base_mesh.mpi_comm()) == 1 gdim = base_mesh.geometry().dim() tdim = marking_function.dim() assert tdim > 0, 'No Embedded mesh from vertices' if isinstance(markers, int): markers = [markers] assert markers, markers # We reuse a lot of Submesh capabilities if marking by cell_f if base_mesh.topology().dim() == marking_function.dim(): # Submesh works only with one marker so we conform color_array = marking_function.array() color_cells = dict( (m, np.where(color_array == m)[0]) for m in markers) # So everybody is marked as 1 one_cell_f = df.MeshFunction('size_t', base_mesh, tdim, 0) for cells in color_cells.itervalues(): one_cell_f.array()[cells] = 1 # The Embedded mesh now steals a lot from submesh submesh = df.SubMesh(base_mesh, one_cell_f, 1) df.Mesh.__init__(self, submesh) # The entity mapping attribute mesh_key = marking_function.mesh().id() self.parent_entity_map = { mesh_key: { 0: submesh.data().array('parent_vertex_indices', 0), tdim: submesh.data().array('parent_cell_indices', tdim) } } # Finally it remains to preserve the markers f = df.MeshFunction('size_t', self, tdim, 0) if len(markers) > 1: # We turn the old cells to set for faster lookup color_cells = {k: set(v) for k, v in color_cells.iteritems()} # And then use the new -> old mapping to color for new_cell, old_cell in enumerate( self.parent_entity_map[mesh_key][tdim]): for color, cells in color_cells.iteritems(): if old_cell in cells: f[new_cell] = color break else: f.set_all(markers[0]) self.marking_function = f return None # https://stackoverflow.com/questions/2491819/how-to-return-a-value-from-init-in-python # Otherwise the mesh needs to by build from scratch base_mesh.init(tdim, 0) # Collect unique vertices based on their new-mesh indexing, the cells # of the embedded mesh are defined in terms of their embedded-numbering new_vertices, new_cells = [], [] # NOTE: new_vertices is actually new -> old vertex map # Map from cells of embedded mesh to tdim entities of base mesh, and cell_map = [] cell_colors = defaultdict(list) # Preserve the markers new_cell_index, new_vertex_index = 0, 0 for marker in markers: for entity in df.SubsetIterator(marking_function, marker): vs = entity.entities(0) cell = [] # Vertex lookup for v in vs: try: local = new_vertices.index(v) except ValueError: local = new_vertex_index new_vertices.append(v) new_vertex_index += 1 # Cell, one by one in terms of vertices cell.append(local) # The cell new_cells.append(cell) # Into map cell_map.append(entity.index()) # Colors cell_colors[marker].append(new_cell_index) new_cell_index += 1 # With acquired data build the mesh df.Mesh.__init__(self) editor = df.MeshEditor() if df.__version__ == '2017.2.0': cell_type = {1: 'interval', 2: 'triangle', 3: 'tetrahedron'}[tdim] editor.open(self, cell_type, tdim, gdim) else: editor.open(self, tdim, gdim) editor.init_vertices(len(new_vertices)) editor.init_cells(len(new_cells)) vertex_coordinates = base_mesh.coordinates()[new_vertices] for vi, x in enumerate(vertex_coordinates): editor.add_vertex(vi, x) for ci, c in enumerate(new_cells): editor.add_cell(ci, *c) editor.close() # The entity mapping attribute mesh_key = marking_function.mesh().id() self.parent_entity_map = {mesh_key: {0: new_vertices, tdim: cell_map}} f = df.MeshFunction('size_t', self, tdim, 0) f_ = f.array() # Finally the inherited marking function if len(markers) > 1: for marker, cells in cell_colors.iteritems(): f_[cells] = marker else: f.set_all(markers[0]) self.marking_function = f
def test_restriction(tmpdir): """ Create a mesh consisting of two separate regions and define a dolfin Function on it which is constant in either region. Then extract the two subfunctions corresponding to these regions and check that they are constant and their function vectors have the correct lengths. """ os.chdir(str(tmpdir)) sphere1 = Sphere(10, center=(-20, 0, 0), name="sphere1") sphere2 = Sphere(20, center=(+30, 0, 0), name="sphere2") mesh = (sphere1 + sphere2).create_mesh(maxh=5.0) class Sphere1(df.SubDomain): def inside(self, pt, on_boundary): return pt[0] < 0 class Sphere2(df.SubDomain): def inside(self, pt, on_boundary): return pt[0] > 0 region_markers = df.CellFunction('size_t', mesh) subdomain1 = Sphere1() subdomain2 = Sphere2() subdomain1.mark(region_markers, 1) subdomain2.mark(region_markers, 2) submesh1 = df.SubMesh(mesh, region_markers, 1) submesh2 = df.SubMesh(mesh, region_markers, 2) r1 = restriction(mesh, submesh1) r2 = restriction(mesh, submesh2) # Define a Python function which is constant in either subregion def fun_f(pt): return 42.0 if (pt[0] < 0) else 23.0 # Convert the Python function to a dolfin.Function f = scalar_valued_function(fun_f, mesh) # Restrict the function to each of the subregions f1 = r1(f) f2 = r2(f) assert (np.allclose(f1.vector().array(), 42.0)) assert (np.allclose(f2.vector().array(), 23.0)) assert (len(f1.vector().array()) == submesh1.num_vertices()) assert (len(f2.vector().array()) == submesh2.num_vertices()) a = f.vector().array() a1 = r1(a) a2 = r2(a) assert (set(a) == set([23.0, 42.0])) assert (np.allclose(a1, 42.0)) assert (np.allclose(a2, 23.0)) assert (len(a1) == submesh1.num_vertices()) assert (len(a2) == submesh2.num_vertices()) # Check a multi-dimensional array, too b = np.concatenate([a, a]) b.shape = (2, -1) b1 = r1(b) b2 = r2(b) assert (set(b.ravel()) == set([23.0, 42.0])) assert (np.allclose(b1, 42.0)) assert (np.allclose(b2, 23.0)) assert (b1.shape == (2, submesh1.num_vertices())) assert (b2.shape == (2, submesh2.num_vertices()))
k_values = [10, 100] DG0 = df.FunctionSpace(mesh, "DG", 0) k = df.Function(DG0) # Will this work with the new ordering introduced in dolfin-1.1.0? # (dofs ordering won't correspond to geometry anymore) for cell_no, region_no in enumerate(regions.array()): k.vector()[cell_no] = k_values[region_no - 1] # # Example 3 # FunctionSpaces defined on regions instead of the whole mesh. # disk_mesh = df.SubMesh(mesh, regions, 1) CG1_disk = df.FunctionSpace(disk_mesh, "Lagrange", 1) cuboid_mesh = df.SubMesh(mesh, regions, 2) CG1_cuboid = df.FunctionSpace(cuboid_mesh, "Lagrange", 1) # # Visualise the different regions and the values of k # k_CG1 = df.interpolate(k, df.FunctionSpace(mesh, "CG", 1)) k_disk = df.project(k, CG1_disk) k_cuboid = df.project(k, CG1_cuboid) df.common.plotting.Viper.write_png(df.plot(k), "k_DG0.png") df.common.plotting.Viper.write_png(df.plot(k_CG1), "k_interpolated_CG1.png")
def __init__(self, marking_function, markers): if not isinstance(markers, (list, tuple)): markers = [markers] # Convenience option to specify only subdomains is_number = lambda m: isinstance(m, int) new_markers = [] # Build a new list int list with facet_function marked if not all(map(is_number, markers)): numbers = filter(is_number, markers) next_int_marker = max(numbers) if numbers else 0 for marker in markers: if is_number(marker): new_markers.append(marker) else: next_int_marker += 1 # SubDomain try: marker.mark(marking_function, next_int_marker) except AttributeError: # A string try: df.CompiledSubDomain(marker).mark( marking_function, next_int_marker) # A lambda except TypeError: df.CompiledSubDomain(*marker()).mark( marking_function, next_int_marker) new_markers.append(next_int_marker) markers = new_markers base_mesh = marking_function.mesh() assert base_mesh.topology().dim() >= marking_function.dim() # Work in serial only (much like submesh) assert df.MPI.size(base_mesh.mpi_comm()) == 1 gdim = base_mesh.geometry().dim() tdim = marking_function.dim() assert tdim > 0, 'No Embedded mesh from vertices' assert markers, markers # We reuse a lot of Submesh capabilities if marking by cell_f if base_mesh.topology().dim() == marking_function.dim(): # Submesh works only with one marker so we conform color_array = marking_function.array() color_cells = dict( (m, np.where(color_array == m)[0]) for m in markers) # So everybody is marked as 1 one_cell_f = df.MeshFunction('size_t', base_mesh, tdim, 0) for cells in color_cells.itervalues(): one_cell_f.array()[cells] = 1 # The Embedded mesh now steals a lot from submesh submesh = df.SubMesh(base_mesh, one_cell_f, 1) df.Mesh.__init__(self, submesh) # The entity mapping attribute; # NOTE: At this point there is not reason to use a dict as # a lookup table mesh_key = marking_function.mesh().id() mapping_0 = submesh.data().array('parent_vertex_indices', 0) mapping_tdim = submesh.data().array('parent_cell_indices', tdim) self.parent_entity_map = { mesh_key: { 0: dict(enumerate(mapping_0)), tdim: dict(enumerate(mapping_tdim)) } } # Finally it remains to preserve the markers f = df.MeshFunction('size_t', self, tdim, 0) f_values = f.array() if len(markers) > 1: old2new = dict(zip(mapping_tdim, range(len(mapping_tdim)))) for color, old_cells in color_cells.iteritems(): new_cells = np.array([old2new[o] for o in old_cells], dtype='uintp') f_values[new_cells] = color else: f.set_all(markers[0]) self.marking_function = f # Declare which tagged cells are found self.tagged_cells = set(markers) # https://stackoverflow.com/questions/2491819/how-to-return-a-value-from-init-in-python return None # Otherwise the mesh needs to by build from scratch base_mesh.init(tdim, 0) # Collect unique vertices based on their new-mesh indexing, the cells # of the embedded mesh are defined in terms of their embedded-numbering new_vertices, new_cells = [], [] # NOTE: new_vertices is actually new -> old vertex map # Map from cells of embedded mesh to tdim entities of base mesh, and cell_map = [] cell_colors = defaultdict(list) # Preserve the markers new_cell_index, new_vertex_index = 0, 0 for marker in markers: for entity in df.SubsetIterator(marking_function, marker): vs = entity.entities(0) cell = [] # Vertex lookup for v in vs: try: local = new_vertices.index(v) except ValueError: local = new_vertex_index new_vertices.append(v) new_vertex_index += 1 # Cell, one by one in terms of vertices cell.append(local) # The cell new_cells.append(cell) # Into map cell_map.append(entity.index()) # Colors cell_colors[marker].append(new_cell_index) new_cell_index += 1 vertex_coordinates = base_mesh.coordinates()[new_vertices] new_cells = np.array(new_cells, dtype='uintp') # With acquired data build the mesh df.Mesh.__init__(self) # Fill make_mesh(coordinates=vertex_coordinates, cells=new_cells, tdim=tdim, gdim=gdim, mesh=self) # The entity mapping attribute mesh_key = marking_function.mesh().id() self.parent_entity_map = { mesh_key: { 0: dict(enumerate(new_vertices)), tdim: dict(enumerate(cell_map)) } } f = df.MeshFunction('size_t', self, tdim, 0) f_ = f.array() # Finally the inherited marking function if len(markers) > 1: for marker, cells in cell_colors.iteritems(): f_[cells] = marker else: f.set_all(markers[0]) self.marking_function = f # Declare which tagged cells are found self.tagged_cells = set(markers)
def create_patches(box=np.array([0, 0, 0, 1, 1, 1]), patch_num=3, patch_nums=None, alpha=1.25, beta=2.0, max_resolution=0.5, num=6, create_inclusions=False, skip_patches=[], prefix='test', logger=None, ldomain=False, corner_refine=3, hole=False, hole_radius=None, layers=1, max_refines=1, elem_per_layer=3): if logger is not None: info = logger.info else: info = print basedim = 3 low = box[:basedim].copy() high = box[basedim:].copy() lengths = high - low diameter = np.sqrt(lengths @ lengths) myeps = sa_utils.myeps * diameter center = (high + low) * .5 info('low {:s}, high {:s}, lengths {:s}, center {:s}, diameter {:.2e}'. format(str(low), str(high), str(lengths), str(center), diameter)) layer_bricks = [] layer_hz = lengths[2] / layers layer_low = np.array( [low[0] - lengths[0], low[1] - lengths[1], low[2] - lengths[2]]) layer_high = np.array( [low[0] + lengths[0], low[1] + lengths[1], low[2] + 2 * lengths[2]]) for ii in range(layers - 1): for jj in range(1, elem_per_layer + 1): layer_bricks.append( OrthoBrick( Pnt(*layer_low), Pnt(low[0] + lengths[0], low[1] + lengths[1], low[2] + (ii + jj * 1. / elem_per_layer) * layer_hz))) info('layer [{:d}/{:d}], {:s}, {:s}'.format( ii, layers, str(layer_low), str( np.array([ low[0] + lengths[0], low[1] + lengths[1], low[2] + ii * layer_hz ])))) for jj in range(1, elem_per_layer): layer_bricks.append( OrthoBrick( Pnt(*layer_low), Pnt( low[0] + lengths[0], low[1] + lengths[1], low[2] + (layers - 1 + jj * 1. / elem_per_layer) * layer_hz))) layer_bricks.append(OrthoBrick(Pnt(*layer_low), Pnt(*layer_high))) sublayers = len(layer_bricks) info('layer [{:d}/{:d}], {:s}, {:s}'.format(layers, layers, str(layer_low), str(layer_high))) info('{:d} layers, {:d} sublayers, {:d} bricks'.format( layers, sublayers, len(layer_bricks))) bc_dict = dict() left = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[0], low[0], eps=myeps)) bc_dict[1] = left right = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[0], high[0], eps=myeps)) bc_dict[2] = right front = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[1], low[1], eps=myeps)) bc_dict[3] = front back = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[1], high[1], eps=myeps)) bc_dict[4] = back bottom = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[2], low[2], eps=myeps)) bc_dict[5] = bottom top = dolfin.AutoSubDomain( lambda xx, on: on and dolfin.near(xx[2], high[2], eps=myeps)) bc_dict[6] = top border = dolfin.AutoSubDomain(lambda xx, on: on) if ldomain: corner_lr = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[0], center[0], eps=myeps)) bc_dict[7] = corner_lr corner_fb = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[1], center[1], eps=myeps)) bc_dict[8] = corner_fb corner_bt = dolfin.AutoSubDomain( lambda xx, on: on and (xx >= center - myeps).all() and dolfin.near( xx[2], center[2], eps=myeps)) bc_dict[9] = corner_bt corner_subdomains = [] corner_close = 0.1 * diameter + myeps for ii in range(corner_refine): corner_subdomains.append( dolfin.AutoSubDomain( (lambda what: lambda xx, on: np.sqrt(xx @ xx) < what )(corner_close))) corner_close *= 0.5 if create_inclusions and num: info('random inclusions') if num: number = num * num * num info('n = ' + str(number)) inc_radius = 0.5 / num info('r = ' + str(inc_radius)) nodes = [] radii = [] rnd_low = low - 0.5 * inc_radius rnd_high = high + 0.5 * inc_radius width = rnd_high - rnd_low while (len(nodes) < number): notok = True while (notok): new = rnd.rand(3) * width + rnd_low radius = (0.5 + rnd.rand()) * inc_radius notok = False for old, rr in zip(nodes, radii): diff = new - old if np.sqrt(diff.dot(diff)) < 1.3 * (radius + rr): notok = True break nodes.append(new.copy()) radii.append(radius) nodes = np.array(nodes) radii = np.array(radii) info('found locations for ' + str(len(nodes)) + ' inclusions') np.savetxt(prefix + '/' + prefix + '_inclusions.csv', np.hstack((nodes, radii.reshape(len(nodes), 1))), fmt='%.15e', delimiter=', ') del nodes, radii, number, inc_radius nohole_whole = OrthoBrick(Pnt(*low), Pnt(*high)) if ldomain is True: nohole_whole = nohole_whole - OrthoBrick( Pnt(*center), Pnt(*(center + 2 * (high - center)))) if num: data = np.loadtxt(prefix + '/' + prefix + '_inclusions.csv', delimiter=', ') number = len(data) else: number = 0 if number: nodes = data[:, :3] radii = data[:, 3] inclusions = Sphere(Pnt(*nodes[0]), radii[0]) for kk in range(1, len(nodes)): inclusions += Sphere(Pnt(*nodes[kk]), radii[kk]) nohole_matrix = nohole_whole - inclusions nohole_incs = nohole_whole * inclusions if hole_radius is not None: hole = True if hole: if hole_radius is None: hole_radius = lengths[1] / 9. near_hole = dolfin.AutoSubDomain(lambda xx, on: on and np.sqrt( (xx[0] - center[0]) * (xx[0] - center[0]) + (xx[1] - center[1]) * (xx[1] - center[1])) < hole_radius + 1e4 * myeps) bc_dict[10] = near_hole if patch_nums is None: hh = lengths[0] / float(patch_num) patch_nums = np.array(np.ceil(lengths / hh), dtype=int) hs = lengths / patch_nums hs_alpha = hs * alpha * 0.5 hs_beta = hs_alpha * beta patches = [] patches_ext = [] for kk in range(patch_nums[2]): pt_z = low[0] + (0.5 + kk) * hs[2] for jj in range(patch_nums[1]): pt_y = low[1] + (0.5 + jj) * hs[1] for ii in range(patch_nums[0]): pt_x = low[2] + (0.5 + ii) * hs[0] pt_center = np.array([pt_x, pt_y, pt_z]) pt_low = pt_center - hs_alpha if ldomain and (p_low >= center - myeps).all(): print('[{:d}, {:d}, {:d}] skipped'.format(ii, jj, kk)) continue patches.append( OrthoBrick(Pnt(*(pt_center - hs_alpha)), Pnt(*(pt_center + hs_alpha)))) patches_ext.append( OrthoBrick(Pnt(*(pt_center - hs_beta)), Pnt(*(pt_center + hs_beta))) - patches[-1]) patch_num = len(patches) print('[{:d}] patches total'.format(patch_num)) patch_fill = int(np.log(patch_num) / np.log(10.)) + 1 pt_low = dict() pt_high = dict() pt_inside = dict() info('Patch size computations') sa_utils.makedirs_norace(prefix + '/' + prefix + '_patch_descriptors') ff = open(prefix + '/' + prefix + '_patch_descriptors/0.csv', 'w') ff.write('idx, left, right, front, back, bottom, top\n') for kk in range(patch_num): info(str(kk + 1) + '/' + str(patch_num)) geo = CSGeometry() geo.Add(nohole_whole * patches[kk]) mesh = geo.GenerateMesh(maxh=max_resolution) del geo mesh.Export('tmp.msh', 'Gmsh2 Format') del mesh meshconvert.convert2xml('tmp.msh', 'tmp.xml') os.remove('tmp.msh') os.remove('tmp_facet_region.xml') os.remove('tmp_physical_region.xml') mesh = dolfin.Mesh('tmp.xml') os.remove('tmp.xml') nodes = mesh.coordinates() del mesh pt_low[kk] = np.min(nodes, axis=0) pt_high[kk] = np.max(nodes, axis=0) ff.write('%d, %.15e, %.15e, %.15e, %.15e, %.15e, %.15e\n' % (kk, pt_low[kk][0], pt_high[kk][0], pt_low[kk][1], pt_high[kk][1], pt_low[kk][2], pt_high[kk][2])) del nodes pt_inside[kk] = dolfin.AutoSubDomain(lambda xx, on: (pt_low[ kk] - myeps <= xx).all() and (xx <= pt_high[kk] + myeps).all()) ff.close() info('Patch size computations finished') hole_ratio = hole_radius / lengths[1] for ref in range(max_refines): info('Start meshing resolution {:d}/{:d}'.format(ref + 1, max_refines)) res = max_resolution * 0.5**ref if hole: hole_maxh = res * hole_ratio # hole_maxh = np.min([res*hole_ratio, lengths[2]/layers]) if number: matrix = nohole_matrix - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) incs = nohole_matrix - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) else: whole = nohole_whole - Cylinder( Pnt(center[0], center[1], center[2] - diameter), Pnt(center[0], center[1], center[2] + diameter), hole_radius).maxh(hole_maxh) dirname = '{:s}/{:s}_{:d}_patches/0/'.format(prefix, prefix, ref) sa_utils.makedirs_norace(dirname) basename = '{:s}/{:s}_{:d}'.format(prefix, prefix, ref) info('Global CSG') geo = CSGeometry() if number: geo.Add(matrix * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1])) geo.Add(incs * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1])) else: geo.Add(whole * layer_bricks[0]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1])) info('Global CSG constructed') mesh = geo.GenerateMesh(maxh=res) info('Global surface meshed') del geo gc.collect() mesh.GenerateVolumeMesh() mesh.Export(basename + '.msh', 'Gmsh2 Format') meshconvert.convert2xml(basename + '.msh', basename + '.xml') del mesh os.remove(basename + '.msh') os.remove(basename + '_facet_region.xml') info('Global volume meshed') gc.collect() global_mesh = dolfin.Mesh(basename + '.xml') tmp_nodes = global_mesh.coordinates() tmp_low = np.min(tmp_nodes, axis=0) tmp_high = np.max(tmp_nodes, axis=0) info('global mesh: {:s}, {:s}, {:s}'.format( str(tmp_low), str(tmp_high), str(top.inside(tmp_high, True)))) os.remove(basename + '.xml') info('Correcting cell markers') global_domains_tmp = dolfin.MeshFunction( 'size_t', global_mesh, basename + '_physical_region.xml') os.remove(basename + '_physical_region.xml') global_domains_tmp.array()[:] -= np.min(global_domains_tmp.array()) global_domains_tmp.array()[:] //= elem_per_layer global_domains = dolfin.MeshFunction('size_t', global_mesh, basedim, 0) if number: where = np.where(global_domains_tmp.array() < layers) global_domains.array( )[where] = 4 * global_domains_tmp.array()[where] where = np.where(layers <= global_domains_tmp.array()) global_domains.array( )[where] = 4 * (global_domains_tmp.array()[where] - layers) + 1 del where else: global_domains.array()[:] = 4 * global_domains_tmp.array() del global_domains_tmp if ldomain: for ii in range(corner_refine): mf = dolfin.CellFunction('bool', global_mesh, False) corner_subdomains[ii].mark(mf, True) global_mesh = dolfin.refine(global_mesh, mf) global_domains = dolfin.adapt(global_domains, global_mesh) del mf inside_fun = dolfin.MeshFunction('bool', global_mesh, basedim, True) global_mesh = dolfin.refine(global_mesh, inside_fun) global_domains = dolfin.adapt(global_domains, global_mesh) info('Correcting facet markers') global_facets = dolfin.MeshFunction('size_t', global_mesh, basedim - 1, 0) for key in bc_dict: bc_dict[key].mark(global_facets, key) sa_hdf5.write_dolfin_mesh(global_mesh, basename, cell_function=global_domains, facet_function=global_facets) del global_facets, global_mesh, global_domains, basename gc.collect() for kk in range(patch_num): if kk in skip_patches: continue info(str(kk) + '/' + str(patch_num)) basename = 'patch_' + str(kk).zfill(patch_fill) extname = basename + '_' + str(beta) info(' csg') geo = CSGeometry() if number: geo.Add(matrix * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(incs * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(matrix * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(matrix * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) geo.Add(incs * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(incs * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) else: geo.Add(whole * layer_bricks[0] * patches[kk]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches[kk]) geo.Add(whole * layer_bricks[0] * patches_ext[kk]) for ii in range(1, sublayers): geo.Add(whole * (layer_bricks[ii] - layer_bricks[ii - 1]) * patches_ext[kk]) info(' csg done') mesh = geo.GenerateMesh(maxh=res) info(' surface meshed') del geo gc.collect() mesh.GenerateVolumeMesh() info(' volume meshed') mesh.Export(dirname + '/' + basename + '.msh', 'Gmsh2 Format') meshconvert.convert2xml(dirname + '/' + basename + '.msh', dirname + '/' + basename + '.xml') del mesh os.remove(dirname + '/' + basename + '.msh') os.remove(dirname + '/' + basename + '_facet_region.xml') gc.collect() ext_mesh = dolfin.Mesh(dirname + '/' + basename + '.xml') os.remove(dirname + '/' + basename + '.xml') info(' cell function') ext_domains_tmp = dolfin.MeshFunction( 'size_t', ext_mesh, dirname + '/' + basename + '_physical_region.xml') os.remove(dirname + '/' + basename + '_physical_region.xml') ext_domains_tmp.array()[:] -= np.min(ext_domains_tmp.array()) ext_domains_tmp.array()[:] //= elem_per_layer ext_domains = dolfin.MeshFunction('size_t', ext_mesh, basedim, 0) if number: where = np.where(ext_domains_tmp.array() < layers) ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where] where = np.where( layers <= ext_domains_tmp.array() < 2 * layers) ext_domains.array( )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 1 where = np.where( 2 * layers <= ext_domains_tmp.array() < 3 * layers) ext_domains.array()[where] = 4 * ( ext_domains_tmp.array()[where] - 2 * layers) + 2 where = np.where(3 * layers <= ext_domains_tmp.array()) ext_domains.array()[where] = 4 * ( ext_domains_tmp.array()[where] - 3 * layers) + 3 del where else: where = np.where(ext_domains_tmp.array() < layers) ext_domains.array()[where] = 4 * ext_domains_tmp.array()[where] where = np.where(layers <= ext_domains_tmp.array()) ext_domains.array( )[where] = 4 * (ext_domains_tmp.array()[where] - layers) + 2 del ext_domains_tmp if ldomain: for ii in range(corner_refine): mf = dolfin.CellFunction('bool', ext_mesh, False) corner_subdomains[ii].mark(mf, True) ext_mesh = dolfin.refine(ext_mesh, mf) ext_domains = dolfin.adapt(ext_domains, ext_mesh) del mf inside_fun = dolfin.MeshFunction('bool', ext_mesh, basedim, False) pt_inside[kk].mark(inside_fun, True) ext_mesh = dolfin.refine(ext_mesh, inside_fun) del inside_fun ext_domains = dolfin.adapt(ext_domains, ext_mesh) info(' cell function done') pt_mesh = dolfin.SubMesh(ext_mesh, pt_inside[kk]) pt_domains = dolfin.MeshFunction('size_t', pt_mesh, basedim, 0) tree = ext_mesh.bounding_box_tree() for cell in dolfin.cells(pt_mesh): global_index = tree.compute_first_entity_collision( cell.midpoint()) pt_domains[cell] = ext_domains[dolfin.Cell( ext_mesh, global_index)] del tree pt_facets = dolfin.MeshFunction('size_t', pt_mesh, basedim - 1, 0) border.mark(pt_facets, 100) for key in bc_dict: bc_dict[key].mark(pt_facets, key) sa_hdf5.write_dolfin_mesh(pt_mesh, '{:s}/{:s}'.format(dirname, basename), cell_function=pt_domains, facet_function=pt_facets) tmp_nodes = ext_mesh.coordinates() tmp_low = np.min(tmp_nodes, axis=0) tmp_high = np.max(tmp_nodes, axis=0) is_part = (tmp_low > low + myeps).any() or (tmp_high < high - myeps).any() del tmp_low, tmp_high, tmp_nodes info('patch [{:d}/{:d}], beta [{:.2e}] is real subdomain [{:}]'. format(kk + 1, patch_num, beta, is_part)) if is_part: vals = np.arange(1, 11) else: vals = np.unique(pt_facets.array()) vals = vals[np.where(vals > 0)] patch_dict = dict() for key in bc_dict: if key in vals: patch_dict[key] = bc_dict[key] else: patch_dict[key] = dolfin.AutoSubDomain( (lambda what: (lambda xx, on: bc_dict[what].inside( xx, on) and pt_inside[kk].inside(xx, on)))(key)) ext_facets = dolfin.MeshFunction('size_t', ext_mesh, basedim - 1, 0) border.mark(ext_facets, 100) for key in patch_dict: patch_dict[key].mark(ext_facets, key) del patch_dict, vals sa_hdf5.write_dolfin_mesh(ext_mesh, dirname + '/' + basename + '_' + str(beta), cell_function=ext_domains, facet_function=ext_facets) del ext_mesh, ext_domains, ext_facets, pt_mesh, pt_domains, pt_facets gc.collect() del pt_low, pt_high, pt_inside
#------------------------------------------------------------------------------# # import initial mesh #------------------------------------------------------------------------------# mesh_name = "../meshes/sphereInCube" mesh = dlfn.Mesh(mesh_name + ".xml") dim = mesh.geometry().dim() ncells = mesh.num_cells() # load facet and cell ids cellMeshFun = dlfn.MeshFunctionSizet(mesh, mesh_name + "_physical_region.xml") facetMeshFun = dlfn.MeshFunctionSizet(mesh, mesh_name + "_facet_region.xml") #------------------------------------------------------------------------------# # sub meshes #------------------------------------------------------------------------------# # create submeshes subMeshes = { intId: dlfn.SubMesh(mesh, cellMeshFun, intId), extId: dlfn.SubMesh(mesh, cellMeshFun, extId) } # transfer mesh functions facetSubMeshFuns = dict() cellSubMeshFuns = dict() for i in subIds: facetSubMeshFuns[i] = transferMeshFunToSubMesh(subMeshes[i], facetMeshFun) cellSubMeshFuns[i] = transferMeshFunToSubMesh(subMeshes[i], cellMeshFun) #------------------------------------------------------------------------------# # function spaces, test/trial functions, ... #------------------------------------------------------------------------------# # finite element spaces P1Curl = dlfn.FiniteElement("N1curl", mesh.ufl_cell(), 1) P1 = dlfn.FiniteElement("Lagrange", mesh.ufl_cell(), 1) # function spaces