Example #1
0
	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))
Example #2
0
    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
Example #3
0
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)
Example #4
0
 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
Example #5
0
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
Example #6
0
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
Example #7
0
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
Example #8
0
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))
Example #9
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)
Example #10
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_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)
Example #11
0
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)
Example #12
0
    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))
Example #13
0
    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)
Example #15
0
        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)])
Example #16
0
    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()
Example #19
0
    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)
Example #20
0
    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
Example #21
0
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()))
Example #22
0
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")
Example #23
0
    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