Exemple #1
0
    def __init__(self, U_m, mesh):
        """Function spaces and BCs"""
        V = VectorFunctionSpace(mesh, 'P', 2)
        Q = FunctionSpace(mesh, 'P', 1)
        self.mesh = mesh
        self.vu, self.vp = TestFunction(V), TestFunction(Q)  # for integration
        self.u_, self.p_ = Function(V), Function(Q)  # for the solution
        self.u_1, self.p_1 = Function(V), Function(Q)  # for the prev. solution
        self.u_k, self.p_k = Function(V), Function(Q)  # for the prev. solution
        self.u, self.p = TrialFunction(V), TrialFunction(Q)  # unknown!

        U0_str = "4.*U_m*x[1]*(.41-x[1])/(.41*.41)"
        x = [0,
             .41 / 2]  # evaluate the Expression at the center of the channel
        self.U_mean = np.mean(2 / 3 * eval(U0_str))

        U0 = Expression((U0_str, "0"), U_m=U_m, degree=2)
        bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall)
        bc1 = DirichletBC(V, Constant((0, 0)), topandbottom)
        bc2 = DirichletBC(V, U0, inlet)
        bc3 = DirichletBC(Q, Constant(0), outlet)
        self.bcu = [bc0, bc1, bc2]
        self.bcp = [bc3]
        # ds is needed to compute drag and lift.
        ASD1 = AutoSubDomain(topandbottom)
        ASD2 = AutoSubDomain(cylinderwall)
        mf = MeshFunction("size_t", mesh, 1)
        mf.set_all(0)
        ASD1.mark(mf, 1)
        ASD2.mark(mf, 2)
        self.ds_ = ds(subdomain_data=mf, domain=mesh)
        return
Exemple #2
0
class QuarterSphereGrid(object):
	def __init__(self, x0, y0, z0, R, n):
		class SphereSurface(SubDomain):
			def inside(self, x, on_boundary):
				return on_boundary
		class X_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x0)
		class Y_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y0)
		class Z_Symmetric(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z0)
		self.geometry = Sphere(Point(x0, y0, z0), R, segments=n) - Box(Point(x0 + R, y0, z0 - R), Point(x0 - R, y0 - R, z0 + R)) - Box(Point(x0 - R, y0 + R, z0), Point(x0 + R, y0, z0 - R)) - Box(Point(x0, y0, z0), Point(x0 - R, y0 + R, z0 + R))
		self.mesh = generate_mesh(self.geometry, n)
		self.domains = MeshFunction("size_t", self.mesh, self.mesh.topology().dim())
		self.domains.set_all(0)
		self.dx = Measure('dx', domain=self.mesh, subdomain_data=self.domains)
		self.boundaries = MeshFunction("size_t", self.mesh, self.mesh.topology().dim()-1)
		self.boundaries.set_all(0)
		self.sphereSurface = SphereSurface()
		self.sphereSurface.mark(self.boundaries, 1)
		self.x_symmetric = X_Symmetric()
		self.x_symmetric.mark(self.boundaries, 2)
		self.y_symmetric = Y_Symmetric()
		self.y_symmetric.mark(self.boundaries, 3)
		self.z_symmetric = Z_Symmetric()
		self.z_symmetric.mark(self.boundaries, 4)
		self.ds = Measure('ds', domain=self.mesh, subdomain_data=self.boundaries)
		self.dS = Measure('dS', domain=self.mesh, subdomain_data=self.boundaries)
Exemple #3
0
def convert_meshfunctions_to_submesh(mesh, submesh, meshfunctions_on_mesh):
    assert meshfunctions_on_mesh is None or (isinstance(
        meshfunctions_on_mesh, list) and len(meshfunctions_on_mesh) > 0)
    if meshfunctions_on_mesh is None:
        return None
    meshfunctions_on_submesh = list()
    # Create submesh subdomains
    for mesh_subdomain in meshfunctions_on_mesh:
        submesh_subdomain = MeshFunction("size_t", submesh,
                                         mesh_subdomain.dim())
        submesh_subdomain.set_all(0)
        assert submesh_subdomain.dim() in (submesh.topology().dim(),
                                           submesh.topology().dim() - 1)
        if submesh_subdomain.dim() == submesh.topology().dim():
            for submesh_cell in cells(submesh):
                submesh_subdomain.array()[
                    submesh_cell.index()] = mesh_subdomain.array()[
                        submesh.submesh_to_mesh_cell_local_indices[
                            submesh_cell.index()]]
        elif submesh_subdomain.dim() == submesh.topology().dim() - 1:
            for submesh_facet in facets(submesh):
                submesh_subdomain.array()[
                    submesh_facet.index()] = mesh_subdomain.array()[
                        submesh.submesh_to_mesh_facet_local_indices[
                            submesh_facet.index()]]
        else:  # impossible to arrive here anyway, thanks to the assert
            raise TypeError(
                "Invalid arguments in convert_meshfunctions_to_submesh.")
        meshfunctions_on_submesh.append(submesh_subdomain)
    return meshfunctions_on_submesh
Exemple #4
0
def test_closed_boundary(advection_scheme):
    # FIXME: rk3 scheme does not bounces off the wall properly
    xmin, xmax = 0., 1.
    ymin, ymax = 0., 1.

    mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 10, 10)

    # Particle
    x = np.array([[0.975, 0.475]])

    # Given velocity field:
    vexpr = Constant((1., 0.))
    # Given time do_step:
    dt = 0.05
    # Then bounced position is
    x_bounced = np.array([[0.975, 0.475]])

    p = particles(x, [x, x], mesh)

    V = VectorFunctionSpace(mesh, "CG", 1)
    v = Function(V)
    v.assign(vexpr)

    # Different boundary parts
    bound_left = UnitSquareLeft()
    bound_right = UnitSquareRight()
    bound_top = UnitSquareTop()
    bound_bottom = UnitSquareBottom()

    # Mark all facets
    facet_marker = MeshFunction('size_t', mesh, mesh.topology().dim() - 1)
    facet_marker.set_all(0)

    # Mark as closed
    bound_right.mark(facet_marker, 1)

    # Mark other boundaries as open
    bound_left.mark(facet_marker, 2)
    bound_top.mark(facet_marker, 2)
    bound_bottom.mark(facet_marker, 2)

    if advection_scheme == 'euler':
        ap = advect_particles(p, V, v, facet_marker)
    elif advection_scheme == 'rk2':
        ap = advect_rk2(p, V, v, facet_marker)
    elif advection_scheme == 'rk3':
        ap = advect_rk3(p, V, v, facet_marker)
    else:
        assert False

    # Do one timestep, particle must bounce from wall of
    ap.do_step(dt)
    xpE = p.positions()

    # Check if particle correctly bounced off from closed wall
    xpE_root = comm.gather(xpE, root=0)
    if comm.rank == 0:
        xpE_root = np.float64(np.vstack(xpE_root))
        error = np.linalg.norm(x_bounced - xpE_root)
        assert(error < 1e-10)
Exemple #5
0
def _test_eigen_solver_sparse(callback_type):
    from rbnics.backends.dolfin import EigenSolver

    # Define mesh
    mesh = UnitSquareMesh(10, 10)

    # Define function space
    V_element = VectorElement("Lagrange", mesh.ufl_cell(), 2)
    Q_element = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W_element = MixedElement(V_element, Q_element)
    W = FunctionSpace(mesh, W_element)

    # Create boundaries
    class Wall(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and (x[1] < 0 + DOLFIN_EPS
                                    or x[1] > 1 - DOLFIN_EPS)

    boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    wall = Wall()
    wall.mark(boundaries, 1)

    # Define variational problem
    vq = TestFunction(W)
    (v, q) = split(vq)
    up = TrialFunction(W)
    (u, p) = split(up)
    lhs = inner(grad(u), grad(v)) * dx - div(v) * p * dx - div(u) * q * dx
    rhs = -inner(p, q) * dx

    # Define boundary condition
    bc = [DirichletBC(W.sub(0), Constant((0., 0.)), boundaries, 1)]

    # Define eigensolver depending on callback type
    assert callback_type in ("form callbacks", "tensor callbacks")
    if callback_type == "form callbacks":
        solver = EigenSolver(W, lhs, rhs, bc)
    elif callback_type == "tensor callbacks":
        LHS = assemble(lhs)
        RHS = assemble(rhs)
        solver = EigenSolver(W, LHS, RHS, bc)

    # Solve the eigenproblem
    solver.set_parameters({
        "linear_solver": "mumps",
        "problem_type": "gen_non_hermitian",
        "spectrum": "target real",
        "spectral_transform": "shift-and-invert",
        "spectral_shift": 1.e-5
    })
    solver.solve(1)
    r, c = solver.get_eigenvalue(0)
    assert abs(c) < 1.e-10
    assert r > 0., "r = " + str(r) + " is not positive"
    print("Sparse inf-sup constant: ", sqrt(r))
    return (sqrt(r), solver.condensed_A, solver.condensed_B)
def test_open_boundary(advection_scheme):
    xmin, xmax = 0.0, 1.0
    ymin, ymax = 0.0, 1.0
    pres = 3

    mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 10, 10)

    # Particle
    x = RandomRectangle(Point(0.955, 0.45), Point(1.0,
                                                  0.55)).generate([pres, pres])
    x = comm.bcast(x, root=0)

    # Given velocity field:
    vexpr = Constant((1.0, 1.0))
    # Given time do_step:
    dt = 0.05

    p = particles(x, [x, x], mesh)

    V = VectorFunctionSpace(mesh, "CG", 1)
    v = Function(V)
    v.assign(vexpr)

    # Different boundary parts
    bound_left = UnitSquareLeft()
    bound_right = UnitSquareRight()
    bound_top = UnitSquareTop()
    bound_bottom = UnitSquareBottom()

    # Mark all facets
    facet_marker = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    facet_marker.set_all(0)

    # Mark as open
    bound_right.mark(facet_marker, 2)

    # Mark other boundaries as closed
    bound_left.mark(facet_marker, 1)
    bound_top.mark(facet_marker, 1)
    bound_bottom.mark(facet_marker, 1)

    if advection_scheme == "euler":
        ap = advect_particles(p, V, v, facet_marker)
    elif advection_scheme == "rk2":
        ap = advect_rk2(p, V, v, facet_marker)
    elif advection_scheme == "rk3":
        ap = advect_rk3(p, V, v, facet_marker)
    else:
        assert False

    # Do one timestep, particle must bounce from wall of
    ap.do_step(dt)
    num_particles = p.number_of_particles()

    # Check if all particles left domain
    if comm.rank == 0:
        assert (num_particles == 0)
def refineMesh(m, l, u):
    cell_markers = MeshFunction('bool', m, 1)
    cell_markers.set_all(False)
    coords = m.coordinates()
    midpoints = 0.5 * (coords[:-1] + coords[1:])
    ref_idx = np.where((midpoints > l) & (midpoints < u))[0]
    cell_markers.array()[ref_idx] = True
    m = refine(m, cell_markers)
    return m
Exemple #8
0
 def mesh_generator(n):
     mesh = UnitSquareMesh(n, n, "left/right")
     dim = mesh.topology().dim()
     domains = MeshFunction("size_t", mesh, dim)
     domains.set_all(0)
     dx = Measure("dx", subdomain_data=domains)
     boundaries = MeshFunction("size_t", mesh, dim - 1)
     boundaries.set_all(0)
     ds = Measure("ds", subdomain_data=boundaries)
     return mesh, dx, ds
def test_advect_periodic_facet_marker(advection_scheme):
    xmin, xmax = 0.0, 1.0
    ymin, ymax = 0.0, 1.0

    mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), 10, 10)
    facet_marker = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    facet_marker.set_all(0)
    boundaries = Boundaries()
    boundaries.mark(facet_marker, 3)

    lims = np.array([
        [xmin, xmin, ymin, ymax],
        [xmax, xmax, ymin, ymax],
        [xmin, xmax, ymin, ymin],
        [xmin, xmax, ymax, ymax],
    ])

    vexpr = Constant((1.0, 1.0))
    V = VectorFunctionSpace(mesh, "CG", 1)

    x = RandomRectangle(Point(0.05, 0.05), Point(0.15, 0.15)).generate([3, 3])
    x = comm.bcast(x, root=0)
    dt = 0.05

    v = Function(V)
    v.assign(vexpr)

    p = particles(x, [x * 0, x**2], mesh)

    if advection_scheme == "euler":
        ap = advect_particles(p, V, v, facet_marker, lims.flatten())
    elif advection_scheme == "rk2":
        ap = advect_rk2(p, V, v, facet_marker, lims.flatten())
    elif advection_scheme == "rk3":
        ap = advect_rk3(p, V, v, facet_marker, lims.flatten())
    else:
        assert False

    xp0 = p.positions()
    t = 0.0
    while t < 1.0 - 1e-12:
        ap.do_step(dt)
        t += dt
    xpE = p.positions()

    # Check if position correct
    xp0_root = comm.gather(xp0, root=0)
    xpE_root = comm.gather(xpE, root=0)

    if comm.Get_rank() == 0:
        xp0_root = np.float32(np.vstack(xp0_root))
        xpE_root = np.float32(np.vstack(xpE_root))
        error = np.linalg.norm(xp0_root - xpE_root)
        assert error < 1e-10
Exemple #10
0
def navier_stokes_IPCS(mesh, dt, parameter):
    """
    fenics code: weak form of the problem.
    """
    mu, rho, nu = parameter
    V = VectorFunctionSpace(mesh, 'P', 2)
    Q = FunctionSpace(mesh, 'P', 1)

    bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall)
    bc1 = DirichletBC(V, Constant((0, 0)), topandbottom)
    bc2 = DirichletBC(V, U0, inlet)
    bc3 = DirichletBC(Q, Constant(1), outlet)
    bcs = [bc0, bc1, bc2, bc3]

    # ds is needed to compute drag and lift. Not used here.
    ASD1 = AutoSubDomain(topandbottom)
    ASD2 = AutoSubDomain(cylinderwall)
    mf = MeshFunction("size_t", mesh, 1)
    mf.set_all(0)
    ASD1.mark(mf, 1)
    ASD2.mark(mf, 2)
    ds_ = ds(subdomain_data=mf, domain=mesh)

    vu, vp = TestFunction(V), TestFunction(Q)  # for integration
    u_, p_ = Function(V), Function(Q)  # for the solution
    u_1, p_1 = Function(V), Function(Q)  # for the prev. solution
    u, p = TrialFunction(V), TrialFunction(Q)  # unknown!
    bcu = [bcs[0], bcs[1], bcs[2]]
    bcp = [bcs[3]]

    n = FacetNormal(mesh)
    u_mid = (u + u_1) / 2.0
    F1 = rho*dot((u - u_1) / dt, vu)*dx \
        + rho*dot(dot(u_1, nabla_grad(u_1)), vu)*dx \
        + inner(sigma(u_mid, p_1, mu), epsilon(vu))*dx \
        + dot(p_1*n, vu)*ds - dot(mu*nabla_grad(u_mid)*n, vu)*ds
    a1 = lhs(F1)
    L1 = rhs(F1)
    # Define variational problem for step 2
    a2 = dot(nabla_grad(p), nabla_grad(vp)) * dx
    L2 = dot(nabla_grad(p_1), nabla_grad(vp)) * dx - (
        rho / dt) * div(u_) * vp * dx  # rho missing in FEniCS tutorial
    # Define variational problem for step 3
    a3 = dot(u, vu) * dx
    L3 = dot(u_, vu) * dx - dt * dot(nabla_grad(p_ - p_1), vu) * dx
    # Assemble matrices
    A1 = assemble(a1)
    A2 = assemble(a2)
    A3 = assemble(a3)
    # Apply boundary conditions to matrices
    [bc.apply(A1) for bc in bcu]
    [bc.apply(A2) for bc in bcp]
    return u_, p_, u_1, p_1, L1, A1, L2, A2, L3, A3, bcu, bcp
Exemple #11
0
def generate_footing_square(Nelements, length, refinements=0):
    from dolfin import UnitSquareMesh, SubDomain, MeshFunction, Measure, near, refine, cells
    import numpy as np
    # Start from square
    mesh = generate_square(Nelements, length, 0)[0]

    def refine_mesh(mesh):
        # Refine on top
        cell_markers = MeshFunction('bool', mesh, mesh.topology().dim())
        cell_markers.set_all(False)
        for c in cells(mesh):
            verts = np.reshape(c.get_vertex_coordinates(), (3, 2))
            verts_x = verts[:, 0]
            verts_y = verts[:, 1]
            newval = verts_y.min() > 2 * length / 3 and verts_x.min() > length / \
                8 and verts_x.max() < 7 / 8 * length
            cell_markers[c] = newval

        # Redefine markers on new mesh
        return refine(mesh, cell_markers)

    mesh = refine_mesh(refine_mesh(mesh))

    for i in range(refinements):
        mesh = refine(mesh)

    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0) and on_boundary

    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], length) and on_boundary

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], length) and on_boundary

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0) and on_boundary

    left, right, top, bottom = Left(), Right(), Top(), Bottom()
    LEFT, RIGHT, TOP, BOTTOM = 1, 2, 3, 4  # Set numbering
    markers = MeshFunction("size_t", mesh, 1)
    markers.set_all(0)

    boundaries = (left, right, top, bottom)
    def_names = (LEFT, RIGHT, TOP, BOTTOM)
    for side, num in zip(boundaries, def_names):
        side.mark(markers, num)
    return mesh, markers, LEFT, RIGHT, TOP, BOTTOM, NONE
Exemple #12
0
 def __init__(self, n=16, divide=1, threshold=12.3,
              left_side_num=3, left_side_denom=4):
     """ Store parameters, initialize data exports (latex, txt). """
     # left_side_num/denom are either height, assuming base is 1,
     #   or left and bottom side lengths
     self.n = n
     self.threshold = threshold / left_side_denom ** 2
     self.left_side = [0] * (n + 1)
     self.bottom_side = [0] * (n + 1)
     self.left_side_len = left_side_num * 1.0 / left_side_denom
     self.left_side_num = left_side_num
     self.left_side_denom = left_side_denom
     self.folder = "results"
     self.name = "domains_{}_{}_{}".format(n, divide, threshold)
     self.filename = self.folder + "/" + self.name + ".tex"
     self.matrixZname = self.folder + "/matrices_Z/" + self.name
     self.matrixQname = self.folder + "/matrices_Q/" + self.name
     self.genericname = self.folder + "/" + self.name
     self.textname = self.folder + "/" + self.name + ".txt"
     f = open(self.textname, 'w')
     f.close()
     self.latex = "cd " + self.folder + "; pdflatex --interaction=batchmode" \
         + " {0}.tex; rm {0}.aux {0}.log".format(self.name)
     self.shift = 0
     # common mesh, ready to cut/apply Dirichlet BC
     self.mesh = Triangle(self.left_side_num, left_side_denom)
     while self.mesh.size(2) < self.n * self.n:
         self.mesh = refine(self.mesh)
     for i in range(divide):
         self.mesh = refine(self.mesh)
     boundary = MeshFunction("size_t", self.mesh, 1)
     boundary.set_all(0)
     self.plotted = plot(
         boundary,
         prefix='animation/animation',
         scalarbar=False,
         window_width=1024,
         window_height=1024)
     print 'Grid size: ', self.n ** 2
     print 'Mesh size: ', self.mesh.size(2)
     # setup solver
     self.solver = Solver(self.mesh, left_side_num, left_side_denom)
     self.mass = self.solver.B
     self.stiff = self.solver.A
     print np.unique(self.stiff.data)
     self.save_matrices(0)
     # save dofs
     f = open(self.genericname+'_dofmap.txt', 'w')
     for vec in self.solver.dofs:
         print >>f, vec
     f.close()
def test_advect_open(advection_scheme):
    pres = 3

    mesh = UnitCubeMesh(10, 10, 10)

    # Particle
    x = RandomBox(Point(0.955, 0.45, 0.5),
                  Point(0.99, 0.55, 0.6)).generate([pres, pres, pres])
    x = comm.bcast(x, root=0)

    # Given velocity field:
    vexpr = Constant((1.0, 1.0, 1.0))
    # Given time do_step:
    dt = 0.05

    p = particles(x, [x, x], mesh)

    V = VectorFunctionSpace(mesh, "CG", 1)
    v = Function(V)
    v.assign(vexpr)

    # Different boundary parts
    bounds = Boundaries()
    bound_right = UnitCubeRight()

    # Mark all facets
    facet_marker = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    facet_marker.set_all(0)
    bounds.mark(facet_marker, 1)
    bound_right.mark(facet_marker, 2)

    # Mark as open
    bound_right.mark(facet_marker, 2)

    if advection_scheme == "euler":
        ap = advect_particles(p, V, v, facet_marker)
    elif advection_scheme == "rk2":
        ap = advect_rk2(p, V, v, facet_marker)
    elif advection_scheme == "rk3":
        ap = advect_rk3(p, V, v, facet_marker)
    else:
        assert False

    # Do one timestep, particle must bounce from wall of
    ap.do_step(dt)
    num_particles = p.number_of_particles()

    # Check if all particles left domain
    if comm.rank == 0:
        assert num_particles == 0
Exemple #14
0
    def refine_mesh(mesh):
        # Refine on top
        cell_markers = MeshFunction('bool', mesh, mesh.topology().dim())
        cell_markers.set_all(False)
        for c in cells(mesh):
            verts = np.reshape(c.get_vertex_coordinates(), (3, 2))
            verts_x = verts[:, 0]
            verts_y = verts[:, 1]
            newval = verts_y.min() > 2 * length / 3 and verts_x.min() > length / \
                8 and verts_x.max() < 7 / 8 * length
            cell_markers[c] = newval

        # Redefine markers on new mesh
        return refine(mesh, cell_markers)
Exemple #15
0
def square_with_obstacle():
    # Create classes for defining parts of the boundaries and the interior
    # of the domain
    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0)

    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 1.0)

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0)

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 1.0)

    class Obstacle(SubDomain):
        def inside(self, x, on_boundary):
            return between(x[1], (0.5, 0.7)) and between(x[0], (0.2, 1.0))

    # Initialize sub-domain instances
    left = Left()
    top = Top()
    right = Right()
    bottom = Bottom()
    obstacle = Obstacle()

    # Define mesh
    mesh = UnitSquareMesh(100, 100, "crossed")

    # Initialize mesh function for interior domains
    domains = CellFunction("size_t", mesh)
    domains.set_all(0)
    obstacle.mark(domains, 1)

    # Initialize mesh function for boundary domains
    boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    left.mark(boundaries, 1)
    top.mark(boundaries, 2)
    right.mark(boundaries, 3)
    bottom.mark(boundaries, 4)

    boundary_indices = {"left": 1, "top": 2, "right": 3, "bottom": 4}
    f = Constant(0.0)
    theta0 = Constant(293.0)
    return mesh, f, boundaries, boundary_indices, theta0
Exemple #16
0
def generate_cube(Nelements, length, refinements=0):
    """
    Creates a square mesh of given elements and length with markers on
    the sides: left, bottom, right and top
    """
    from dolfin import UnitCubeMesh, SubDomain, MeshFunction, Measure, near, refine
    mesh = UnitCubeMesh(Nelements, Nelements, Nelements)
    for i in range(refinements):
        mesh = refine(mesh)
    mesh.coordinates()[:] *= length

    # Subdomains: Solid
    class Xp(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], length) and on_boundary

    class Xm(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0) and on_boundary

    class Yp(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], length) and on_boundary

    class Ym(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0) and on_boundary

    class Zp(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[2], length) and on_boundary

    class Zm(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[2], 0.0) and on_boundary
    xp, xm, yp, ym, zp, zm = Xp(), Xm(), Yp(), Ym(), Zp(), Zm()
    XP, XM, YP, YM, ZP, ZM = 1, 2, 3, 4, 5, 6  # Set numbering

    markers = MeshFunction("size_t", mesh, 2)
    markers.set_all(0)

    boundaries = (xp, xm, yp, ym, zp, zm)
    def_names = (XP, XM, YP, YM, ZP, ZM)
    for side, num in zip(boundaries, def_names):
        side.mark(markers, num)

    return mesh, markers, XP, XM, YP, YM, ZP, ZM
Exemple #17
0
class BoxGrid(object):
	def __init__(self, x0, x1, y0, y1, z0, z1, n, unstructured=False):
		class Left(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x0)
		class Right(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[0], x1)
		class Back(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y0)
		class Front(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[1], y1)
		class Bottom(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z0)
		class Top(SubDomain):
			def inside(self, x, on_boundary):
				return near(x[2], z1)
		if unstructured:
			self.geometry = Box(Point(x0, y0, z0), Point(x1, y1, z1))
			self.mesh = generate_mesh(self.geometry, n)
		else:
			nx = int(round(n**(1./3.)*(x1 - x0)))
			ny = int(round(n**(1./3.)*(y1 - y0)))
			nz = int(round(n**(1./3.)*(z1 - z0)))
			self.mesh = BoxMesh(Point(x0, y0, z0), Point(x1, y1, z1), nx, ny, nz)
		self.domains = MeshFunction("size_t", self.mesh, self.mesh.topology().dim())
		self.domains.set_all(0)
		self.dx = Measure('dx', domain=self.mesh, subdomain_data=self.domains)
		self.boundaries = MeshFunction("size_t", self.mesh, self.mesh.topology().dim()-1)
		self.boundaries.set_all(0)
		self.left = Left()
		self.left.mark(self.boundaries, 1)
		self.right = Right()
		self.right.mark(self.boundaries, 2)
		self.front = Front()
		self.front.mark(self.boundaries, 3)
		self.back = Back()
		self.back.mark(self.boundaries, 4)
		self.bottom = Bottom()
		self.bottom.mark(self.boundaries, 5)
		self.top = Top()
		self.top.mark(self.boundaries, 6)
		self.ds = Measure('ds', domain=self.mesh, subdomain_data=self.boundaries)
		self.dS = Measure('dS', domain=self.mesh, subdomain_data=self.boundaries)
Exemple #18
0
 def _init_for_append_if_needed(self):
     # Initialize dof to cells map only the first time
     if len(self.dof_to_cells) == 0:
         self.dof_to_cells = list() # of size len(V)
         for (component, V_component) in enumerate(self.V):
             dof_to_cells = self._compute_dof_to_cells(V_component)
             # Debugging
             log(DEBUG, "DOFs to cells map (component " + str(component) + ") on processor " + str(self.mpi_comm.rank) + ":")
             for (global_dof, cells_) in dof_to_cells.items():
                 log(DEBUG, "\t" + str(global_dof) + ": " + str([cell.global_index() for cell in cells_]))
             # Add to storage
             self.dof_to_cells.append(dof_to_cells)
         self.dof_to_cells = tuple(self.dof_to_cells)
     # Initialize cells marker
     N = self._get_next_index()
     reduced_mesh_markers = MeshFunction("bool", self.mesh, self.mesh.topology().dim())
     reduced_mesh_markers.set_all(False)
     if N > 0:
         reduced_mesh_markers.array()[:] = self.reduced_mesh_markers[N - 1].array()
     assert N not in self.reduced_mesh_markers
     self.reduced_mesh_markers[N] = reduced_mesh_markers
Exemple #19
0
def test_meshfunction_where_equal():
    mesh = UnitSquareMesh(MPI.comm_self, 2, 2)

    cf = MeshFunction("size_t", mesh, mesh.topology.dim, 0)
    cf.set_all(1)
    cf[0] = 3
    cf[3] = 3
    assert list(cf.where_equal(3)) == [0, 3]
    assert list(cf.where_equal(1)) == [1, 2, 4, 5, 6, 7]

    ff = MeshFunction("size_t", mesh, mesh.topology.dim - 1, 100)
    ff.set_all(0)
    ff[0] = 1
    ff[2] = 3
    ff[3] = 3
    assert list(ff.where_equal(1)) == [0]
    assert list(ff.where_equal(3)) == [2, 3]
    assert list(ff.where_equal(0)) == [1] + list(range(4, ff.size()))

    vf = MeshFunction("size_t", mesh, 0, 0)
    vf.set_all(3)
    vf[1] = 1
    vf[2] = 1
    assert list(vf.where_equal(1)) == [1, 2]
    assert list(vf.where_equal(3)) == [0] + list(range(3, vf.size()))
Exemple #20
0
def generate_square(Nelements, length, refinements=0):
    """
    Creates a square mesh of given elements and length with markers on
    the sides: left, bottom, right and top
    """
    from dolfin import UnitSquareMesh, SubDomain, MeshFunction, Measure, near, refine
    mesh = UnitSquareMesh(Nelements, Nelements)
    for i in range(refinements):
        mesh = refine(mesh)
    mesh.coordinates()[:] *= length

    # Subdomains: Solid
    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], 0.0) and on_boundary

    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], length) and on_boundary

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], length) and on_boundary

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], 0.0) and on_boundary
    left, right, top, bottom = Left(), Right(), Top(), Bottom()
    LEFT, RIGHT, TOP, BOTTOM = 1, 2, 3, 4  # Set numbering
    NONE = 99  # Marker for empty boundary

    markers = MeshFunction("size_t", mesh, 1)
    markers.set_all(0)

    boundaries = (left, right, top, bottom)
    def_names = (LEFT, RIGHT, TOP, BOTTOM)
    for side, num in zip(boundaries, def_names):
        side.mark(markers, num)

    return mesh, markers, LEFT, RIGHT, TOP, BOTTOM, NONE
Exemple #21
0
        def get_norm(u, uh):
            assert len(subdomains) == len(u)

            V = uh.function_space()
            mesh = V.mesh()
            cell_f = MeshFunction('size_t', mesh, mesh.topology().dim(), 0)

            error = 0
            for subd_i, u_i in zip(subdomains, u):
                cell_f.set_all(0)  # Reset!
                # Pick an edge
                subd_i.mark(cell_f, 1)
                mesh_i = SubMesh(mesh, cell_f, 1)
                # Edge local function space
                Vi = FunctionSpace(mesh_i, V.ufl_element())
                # The solution on it
                uh_i = interpolate(uh, Vi)
                # And the error there
                error_i = norm(u_i, uh_i)
                error += error_i**2
            error = sqrt(error)
            return error
 def __init__(self, mesh, arg):
     # Initialize empty list
     list.__init__(self)
     # Process depending on the second argument
     assert isinstance(mesh, Mesh)
     assert isinstance(arg, (list, str, SubDomain)) or arg is None
     if isinstance(arg, list):
         assert all([isinstance(arg_i, SubDomain) for arg_i in arg])
     if arg is None:
         pass  # leave the list empty
     elif isinstance(arg, (list, SubDomain)):
         D = mesh.topology().dim()
         for d in range(D + 1):
             mesh_function_d = MeshFunction("bool", mesh, d)
             mesh_function_d.set_all(False)
             if isinstance(arg, SubDomain):
                 arg.mark(mesh_function_d, True)
             else:
                 for arg_i in arg:
                     arg_i.mark(mesh_function_d, True)
             self.append(mesh_function_d)
     elif isinstance(arg, str):
         self._read(mesh, arg)
Exemple #23
0
def setup_problem(mesh, U0, coupled=True):
    # Build function space
    V = VectorFunctionSpace(mesh, 'P', 2)
    Q = FunctionSpace(mesh, 'P', 1)
    L = FunctionSpace(mesh, 'P', 1)
    VQL = (V, Q, L)

    # bc0 = DirichletBC(V, Constant((0, 0)), cylinderwall)
    bc1 = DirichletBC(V, Constant((0, 0)), topandbottom)
    bc2 = DirichletBC(V, U0, inlet)
    bc3 = DirichletBC(Q, Constant(1), outlet)
    # bcs = [bc0, bc1, bc2, bc3]
    bcs = [bc1, bc2, bc3]
    warnings.warn("no no-slip for cyl-wall!")

    ASD1 = AutoSubDomain(topandbottom)
    ASD2 = AutoSubDomain(cylinderwall)
    mf = MeshFunction("size_t", mesh, 1)
    mf.set_all(0)
    ASD1.mark(mf, 1)
    ASD2.mark(mf, 2)
    ds_ = ds(subdomain_data=mf, domain=mesh)
    return VQL, bcs, ds_
Exemple #24
0
def generate_rectangle(x0, y0, x1, y1, nx, ny):
    """
    Creates a square mesh of given elements and length with markers on
    the sides: left, bottom, right and top
    """
    from dolfin import RectangleMesh, Point, SubDomain, MeshFunction, Measure, near
    mesh = RectangleMesh(Point(x0, y0), Point(x1, y1), nx, ny)

    # Subdomains: Solid
    class Left(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], x0) and on_boundary

    class Right(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[0], x1) and on_boundary

    class Top(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], y1) and on_boundary

    class Bottom(SubDomain):
        def inside(self, x, on_boundary):
            return near(x[1], y0) and on_boundary
    left, right, top, bottom = Left(), Right(), Top(), Bottom()
    LEFT, RIGHT, TOP, BOTTOM = 1, 2, 3, 4  # Set numbering
    NONE = 99  # Marker for empty boundary

    markers = MeshFunction("size_t", mesh, 1)
    markers.set_all(0)

    boundaries = (left, right, top, bottom)
    def_names = (LEFT, RIGHT, TOP, BOTTOM)
    for side, num in zip(boundaries, def_names):
        side.mark(markers, num)

    return mesh, markers, LEFT, RIGHT, TOP, BOTTOM, NONE
Exemple #25
0
    def create_boundary(self, domains, interior, exterior):
        """ mark commmon facets between two domains with 1 and a return FacetFunction"""

        edges = MeshFunction("size_t", domains.mesh(),
                             domains.mesh().topology().dim() - 1)
        edges.set_all(0)

        # count number of boundary facets
        Nfacets = 0
        for facet in facets(domains.mesh()):
            cells = facet.entities(2)
            if facet.exterior() == False:

                cell1 = cells[0]
                cell2 = cells[1]
                domain1 = domains.array()[cells[0]]
                domain2 = domains.array()[cells[1]]
                if (sorted([domain1, domain2]) == sorted([interior,
                                                          exterior])):
                    idx = facet.index()
                    edges.array()[idx] = True
                    Nfacets += 1

        return (edges, Nfacets)
Exemple #26
0
class EmbeddedWaveguide():
    """ a rectangular waveguide with cladding class 
        builds the mesh and marks domains """
    def __init__(self, w_sim, h_sim, w_wg, h_wg, res):
        # Create mesh with two domains, waveguide + cladding
        self.res = res
        domain = Rectangle(Point(-w_sim / 2, -h_sim / 2),
                           Point(w_sim / 2, h_sim / 2))
        domain.set_subdomain(
            1,
            Rectangle(Point(-w_sim / 2, -h_sim / 2),
                      Point(w_sim / 2, h_sim / 2)))
        domain.set_subdomain(
            2, Rectangle(Point(-w_wg / 2, -h_wg / 2),
                         Point(w_wg / 2, h_wg / 2)))
        self.mesh = generate_mesh(domain, self.res)
        self.mesh.init()
        # Initialize mesh function for interior domains
        self.waveguide = Waveguide(w_wg, h_wg)
        self.domains = MeshFunction("size_t", self.mesh, 2)
        self.domains.set_all(0)
        self.waveguide.mark(self.domains, 1)
        # Define new measures associated with the interior domains
        self.dx = Measure("dx")(subdomain_data=self.domains)
Exemple #27
0
def peter():
    base = "../meshes/2d/peter"
    # base = '../meshes/2d/peter-fine'
    mesh = Mesh(base + ".xml")

    subdomains = MeshFunction("size_t", mesh, base + "_physical_region.xml")

    workpiece_index = 3
    subdomain_materials = {1: "SiC", 2: "carbon steel", 3: "GaAs (liquid)"}

    submesh_workpiece = SubMesh(mesh, subdomains, workpiece_index)
    W = VectorFunctionSpace(submesh_workpiece, "CG", 2)
    Q = FunctionSpace(submesh_workpiece, "CG", 2)

    # Define melt boundaries.
    class LeftBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Be especially careful in the corners when defining the r=0 axis:
            # For the PPE to be consistent, we need to have n.u=0 *everywhere*
            # on the non-(r=0) boundaries.
            return (
                on_boundary
                and x[0] < GMSH_EPS
                and 0.005 + GMSH_EPS < x[1]
                and x[1] < 0.050 - GMSH_EPS
            )

    class SurfaceBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return (
                on_boundary
                and 0.055 - GMSH_EPS < x[1]
                and 0.030 - GMSH_EPS < x[0]
                and x[0] < 0.075 + GMSH_EPS
            )

    class StampBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Well well. If we don't include the endpoints here, the PPE turns
            # out inconsistent. This is weird since the endpoints should be
            # picked up by RightBoundary and StampBoundary.
            return (
                on_boundary
                and 0.050 - GMSH_EPS < x[1]
                and x[1] < 0.055 + GMSH_EPS
                and x[0] < 0.030 + GMSH_EPS
            )

    class LowerBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Danger, danger.
            # If the rightmost point (0.075, 0.010) is excluded, the PPE will
            # end up inconsistent.
            # This is actually weird since it should be picked up by
            # RightBoundary.
            return on_boundary and (
                x[1] < 0.005 + GMSH_EPS
                or (x[0] > 0.070 - GMSH_EPS and x[1] < 0.010 + GMSH_EPS)
            )

    class RightBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and x[0] > 0.075 - GMSH_EPS

    left_boundary = LeftBoundary()
    lower_boundary = LowerBoundary()
    right_boundary = RightBoundary()
    surface_boundary = SurfaceBoundary()
    stamp_boundary = StampBoundary()

    # Define workpiece boundaries.
    wp_boundaries = MeshFunction(
        "size_t", submesh_workpiece, self.submesh_workpiece.topology().dim() - 1
    )
    wp_boundaries.set_all(0)
    left_boundary.mark(wp_boundaries, 1)
    lower_boundary.mark(wp_boundaries, 2)
    right_boundary.mark(wp_boundaries, 3)
    surface_boundary.mark(wp_boundaries, 4)
    stamp_boundary.mark(wp_boundaries, 5)

    # For local use only:
    wp_boundary_indices = {"left": 1, "lower": 2, "right": 3, "surface": 4, "stamp": 5}

    # Boundary conditions for the velocity.
    u_bcs = [
        DirichletBC(W, (0.0, 0.0), stamp_boundary),
        DirichletBC(W, (0.0, 0.0), right_boundary),
        DirichletBC(W, (0.0, 0.0), lower_boundary),
        DirichletBC(W.sub(0), 0.0, left_boundary),
        DirichletBC(W.sub(1), 0.0, surface_boundary),
    ]
    p_bcs = []

    # Boundary conditions for the heat equation.
    # Dirichlet
    theta_bcs_d = []
    # Neumann
    theta_bcs_n = {}
    # Robin, i.e.,
    #
    #    -dtheta/dn = alpha (theta - theta0)
    #
    # (with alpha>0 to preserve coercivity of the scheme).
    #
    theta_bcs_r = {
        wp_boundary_indices["stamp"]: (100.0, 1500.0),
        wp_boundary_indices["surface"]: (100.0, 1550.0),
        wp_boundary_indices["right"]: (300.0, Expression("200*x[0] + 1600", degree=1)),
        wp_boundary_indices["lower"]: (
            300.0,
            Expression("-1200*x[1] + 1614", degree=1),
        ),
    }
    return (
        mesh,
        subdomains,
        subdomain_materials,
        workpiece_index,
        wp_boundaries,
        W,
        u_bcs,
        p_bcs,
        Q,
        theta_bcs_d,
        theta_bcs_n,
        theta_bcs_r,
    )
Exemple #28
0
def coil_in_box():
    mesh = Mesh("../meshes/2d/coil-in-box.xml")

    f = Constant(0.0)

    # Define mesh and boundaries.
    class LeftBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and x[0] < GMSH_EPS

    left_boundary = LeftBoundary()

    class RightBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and x[0] > 2.5 - GMSH_EPS

    right_boundary = RightBoundary()

    class LowerBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and x[1] < GMSH_EPS

    lower_boundary = LowerBoundary()

    class UpperBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and x[1] > 0.4 - GMSH_EPS

    upper_boundary = UpperBoundary()

    class CoilBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return (
                on_boundary
                and x[0] > GMSH_EPS
                and x[0] < 2.5 - GMSH_EPS
                and x[1] > GMSH_EPS
                and x[1] < 0.4 - GMSH_EPS
            )

    coil_boundary = CoilBoundary()

    # heater_temp = 380.0
    # room_temp = 293.0
    # bcs = [(coil_boundary, heater_temp),
    #        (left_boundary, room_temp),
    #        (right_boundary, room_temp),
    #        (upper_boundary, room_temp),
    #        (lower_boundary, room_temp)
    #        ]

    boundaries = {}
    boundaries["left"] = left_boundary
    boundaries["right"] = right_boundary
    boundaries["upper"] = upper_boundary
    boundaries["lower"] = lower_boundary
    boundaries["coil"] = coil_boundary

    boundaries = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    boundaries.set_all(0)
    left_boundary.mark(boundaries, 1)
    right_boundary.mark(boundaries, 2)
    upper_boundary.mark(boundaries, 3)
    lower_boundary.mark(boundaries, 4)
    coil_boundary.mark(boundaries, 5)

    boundary_indices = {"left": 1, "right": 2, "top": 3, "bottom": 4, "coil": 5}
    theta0 = Constant(293.0)
    return mesh, f, boundaries, boundary_indices, theta0
Exemple #29
0
        def inside(self, x, on_boundary):
            return (between(x[0], (-w_wg / 2, w_wg / 2))
                    and between(x[1], (-h_wg / 2, h_wg / 2)))

    domain = Rectangle(Point(-w_sim / 2, -h_sim / 2),
                       Point(w_sim / 2, h_sim / 2))
    domain.set_subdomain(
        1, Rectangle(Point(-w_sim / 2, -h_sim / 2),
                     Point(w_sim / 2, h_sim / 2)))
    domain.set_subdomain(
        2, Rectangle(Point(-w_wg / 2, -h_wg / 2), Point(w_wg / 2, h_wg / 2)))
    mesh = generate_mesh(domain, res)
    mesh.init()

    # Initialize mesh function for interior domains
    waveguide = Waveguide()
    domains = MeshFunction("size_t", mesh, 2)
    domains.set_all(0)
    waveguide.mark(domains, 1)

    boundary = InternalBoundary(domains, 1, 0)
    normal = boundary.normal
    midpoints = boundary.midpoints

    plt.quiver(midpoints[:, 0],
               midpoints[:, 1],
               normal[:, 0],
               normal[:, 1],
               color='r')
    plt.show()
Exemple #30
0
class Crucible:
    def __init__(self):

        GMSH_EPS = 1.0e-15

        # https://fenicsproject.org/qa/12891/initialize-mesh-from-vertices-connectivities-at-once
        points, cells, point_data, cell_data, _ = meshes.crucible_with_coils.generate(
        )

        # Convert the cell data to 'uint' so we can pick a size_t MeshFunction
        # below as usual.
        for k0 in cell_data:
            for k1 in cell_data[k0]:
                cell_data[k0][k1] = numpy.array(cell_data[k0][k1],
                                                dtype=numpy.dtype("uint"))

        with TemporaryDirectory() as temp_dir:
            tmp_filename = os.path.join(temp_dir, "test.xml")
            meshio.write_points_cells(
                tmp_filename,
                points,
                cells,
                cell_data=cell_data,
                file_format="dolfin-xml",
            )
            self.mesh = Mesh(tmp_filename)
            self.subdomains = MeshFunction(
                "size_t", self.mesh,
                os.path.join(temp_dir, "test_gmsh:physical.xml"))

        self.subdomain_materials = {
            1: my_materials.porcelain,
            2: materials.argon,
            3: materials.gallium_arsenide_solid,
            4: materials.gallium_arsenide_liquid,
            27: materials.air,
        }

        # coils
        for k in range(5, 27):
            self.subdomain_materials[k] = my_materials.ek90

        # Define the subdomains which together form a single coil.
        self.coil_domains = [
            [5, 6, 7, 8, 9],
            [10, 11, 12, 13, 14],
            [15, 16, 17, 18, 19],
            [20, 21, 22, 23],
            [24, 25, 26],
        ]

        self.wpi = 4

        self.submesh_workpiece = SubMesh(self.mesh, self.subdomains, self.wpi)

        # http://fenicsproject.org/qa/2026/submesh-workaround-for-parallel-computation
        # submesh_parallel_bug_fixed = False
        # if submesh_parallel_bug_fixed:
        #     submesh_workpiece = SubMesh(self.mesh, self.subdomains, self.wpi)
        # else:
        #     # To get the mesh in parallel, we need to read it in from a file.
        #     # Writing out can only happen in serial mode, though. :/
        #     base = os.path.join(current_path,
        #                         '../../meshes/2d/crucible-with-coils-submesh'
        #                         )
        #     filename = base + '.xml'
        #     if not os.path.isfile(filename):
        #         warnings.warn(
        #             'Submesh file \'{}\' does not exist. Creating... '.format(
        #             filename
        #             ))
        #         if MPI.size(mpi_comm_world()) > 1:
        #             raise RuntimeError(
        #                 'Can only write submesh in serial mode.'
        #                 )
        #         submesh_workpiece = \
        #             SubMesh(self.mesh, self.subdomains, self.wpi)
        #         output_stream = File(filename)
        #         output_stream << submesh_workpiece
        #     # Read the mesh
        #     submesh_workpiece = Mesh(filename)

        coords = self.submesh_workpiece.coordinates()
        ymin = min(coords[:, 1])
        ymax = max(coords[:, 1])

        # Find the top right point.
        k = numpy.argmax(numpy.sum(coords, 1))
        topright = coords[k, :]

        # Initialize mesh function for boundary domains
        class Left(SubDomain):
            def inside(self, x, on_boundary):
                # Explicitly exclude the lowest and the highest point of the
                # symmetry axis.
                # It is necessary for the consistency of the pressure-Poisson
                # system in the Navier-Stokes solver that the velocity is
                # exactly 0 at the boundary r>0. Hence, at the corner points
                # (r=0, melt-crucible, melt-crystal) we must enforce u=0
                # already and cannot have a component in z-direction.
                return (on_boundary and x[0] < GMSH_EPS
                        and x[1] < ymax - GMSH_EPS and x[1] > ymin + GMSH_EPS)

        class Crucible(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and (
                    (x[0] > GMSH_EPS and x[1] < ymax - GMSH_EPS) or
                    (x[0] > topright[0] - GMSH_EPS
                     and x[1] > topright[1] - GMSH_EPS) or
                    (x[0] < GMSH_EPS and x[1] < ymin + GMSH_EPS))

        # At the top right part (boundary melt--gas), slip is allowed, so only
        # n.u=0 is enforced. Very weirdly, the PPE is consistent if and only if
        # the end points of UpperRight are in UpperRight. This contrasts
        # Left(), where the end points must NOT belong to Left().  Judging from
        # the experiments, these settings do the right thing.
        # TODO try to better understand the PPE system/dolfin's boundary
        # settings
        class Upper(SubDomain):
            def inside(self, x, on_boundary):
                return on_boundary and x[1] > ymax - GMSH_EPS

        class UpperRight(SubDomain):
            def inside(self, x, on_boundary):
                return (on_boundary and x[1] > ymax - GMSH_EPS
                        and x[0] > 0.038 - GMSH_EPS)

        # The crystal boundary is taken to reach up to 0.038 where the
        # Dirichlet boundary data is about the melting point of the crystal,
        # 1511K. This setting gives pretty acceptable results when there is no
        # convection except the one induced by buoyancy. Is there is any more
        # stirring going on, though, the end point of the crystal with its
        # fixed temperature of 1511K might be the hottest point globally. This
        # looks rather unphysical.
        # TODO check out alternatives
        class UpperLeft(SubDomain):
            def inside(self, x, on_boundary):
                return (on_boundary and x[1] > ymax - GMSH_EPS
                        and x[0] < 0.038 + GMSH_EPS)

        left = Left()
        crucible = Crucible()
        upper_left = UpperLeft()
        upper_right = UpperRight()

        self.wp_boundaries = MeshFunction(
            "size_t",
            self.submesh_workpiece,
            self.submesh_workpiece.topology().dim() - 1,
        )
        self.wp_boundaries.set_all(0)
        left.mark(self.wp_boundaries, 1)
        crucible.mark(self.wp_boundaries, 2)
        upper_right.mark(self.wp_boundaries, 3)
        upper_left.mark(self.wp_boundaries, 4)

        if DEBUG:
            from dolfin import plot, interactive

            plot(self.wp_boundaries, title="Boundaries")
            interactive()

        submesh_boundary_indices = {
            "left": 1,
            "crucible": 2,
            "upper right": 3,
            "upper left": 4,
        }

        # Boundary conditions for the velocity.
        #
        # [1] Incompressible flow and the finite element method; volume two;
        #     Isothermal Laminar Flow;
        #     P.M. Gresho, R.L. Sani;
        #
        # For the choice of function space, [1] says:
        #     "In 2D, the triangular elements P_2^+P_1 and P_2^+P_{-1} are very
        #      good [...]. [...] If you wish to avoid bubble functions on
        #      triangular elements, P_2P_1 is not bad, and P_2(P_1+P_0) is even
        #      better [...]."
        #
        # It turns out that adding the bubble space significantly hampers the
        # convergence of the Stokes solver and also considerably increases the
        # time it takes to construct the Jacobian matrix of the Navier--Stokes
        # problem if no optimization is applied.
        V_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(), 2)
        with_bubbles = False
        if with_bubbles:
            V_element += FiniteElement("B", self.submesh_workpiece.ufl_cell(),
                                       2)
        self.W_element = MixedElement(3 * [V_element])
        self.W = FunctionSpace(self.submesh_workpiece, self.W_element)

        rot0 = Expression(("0.0", "0.0", "-2*pi*x[0] * 5.0/60.0"), degree=1)
        # rot0 = (0.0, 0.0, 0.0)
        rot1 = Expression(("0.0", "0.0", "2*pi*x[0] * 5.0/60.0"), degree=1)
        self.u_bcs = [
            DirichletBC(self.W, rot0, crucible),
            DirichletBC(self.W.sub(0), 0.0, left),
            DirichletBC(self.W.sub(2), 0.0, left),
            # Make sure that u[2] is 0 at r=0.
            DirichletBC(self.W, rot1, upper_left),
            DirichletBC(self.W.sub(1), 0.0, upper_right),
        ]
        self.p_bcs = []

        self.P_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(),
                                       1)
        self.P = FunctionSpace(self.submesh_workpiece, self.P_element)

        self.Q_element = FiniteElement("CG", self.submesh_workpiece.ufl_cell(),
                                       2)
        self.Q = FunctionSpace(self.submesh_workpiece, self.Q_element)

        # Dirichlet.
        # This is a bit of a tough call since the boundary conditions need to
        # be read from a Tecplot file here.
        filename = os.path.join(os.path.dirname(os.path.realpath(__file__)),
                                "data/crucible-boundary.dat")
        data = tecplot_reader.read(filename)
        RZ = numpy.c_[data["ZONE T"]["node data"]["r"],
                      data["ZONE T"]["node data"]["z"]]
        T_vals = data["ZONE T"]["node data"]["temp. [K]"]

        class TecplotDirichletBC(Expression):
            def eval(self, value, x):
                # Find on which edge x sits, and raise exception if it doesn't.
                edge_found = False
                for edge in data["ZONE T"]["element data"]:
                    # Given a point X and an edge X0--X1,
                    #
                    #     (1 - theta) X0 + theta X1,
                    #
                    # the minimum distance is assumed for
                    #
                    #    argmin_theta ||(1-theta) X0  + theta X1 - X||^2
                    #    = <X1 - X0, X - X0> / ||X1 - X0||^2.
                    #
                    # If the distance is 0 and 0<=theta<=1, we found the edge.
                    #
                    # Note that edges are 1-based in Tecplot.
                    X0 = RZ[edge[0] - 1]
                    X1 = RZ[edge[1] - 1]
                    theta = numpy.dot(X1 - X0, x - X0) / numpy.dot(
                        X1 - X0, X1 - X0)
                    diff = (1.0 - theta) * X0 + theta * X1 - x
                    if (numpy.dot(diff, diff) < 1.0e-10 and 0.0 <= theta
                            and theta <= 1.0):
                        # Linear interpolation of the temperature value.
                        value[0] = (1.0 - theta) * T_vals[
                            edge[0] - 1] + theta * T_vals[edge[1] - 1]
                        edge_found = True
                        break
                # This class is supposed to be used for Dirichlet boundary
                # conditions. For some reason, FEniCS also evaluates
                # DirichletBC objects at coordinates which do not sit on the
                # boundary, see
                # <http://fenicsproject.org/qa/1033/dirichletbc-expressions-evaluated-away-from-the-boundary>.
                # The assigned values have no meaning though, so not assigning
                # values[0] here is okay.
                #
                # from matplotlib import pyplot as pp
                # pp.plot(x[0], x[1], 'xg')
                if not edge_found:
                    value[0] = 0.0
                    if False:
                        warnings.warn(
                            "Coordinate ({:e}, {:e}) doesn't sit on edge.".
                            format(x[0], x[1]))
                    # pp.plot(RZ[:, 0], RZ[:, 1], '.k')
                    # pp.plot(x[0], x[1], 'xr')
                    # pp.show()
                    # raise RuntimeError('Input coordinate '
                    #                    '{} is not on boundary.'.format(x))
                return

        tecplot_dbc = TecplotDirichletBC(degree=5)
        self.theta_bcs_d = [DirichletBC(self.Q, tecplot_dbc, upper_left)]
        self.theta_bcs_d_strict = [
            DirichletBC(self.Q, tecplot_dbc, upper_right),
            DirichletBC(self.Q, tecplot_dbc, crucible),
            DirichletBC(self.Q, tecplot_dbc, upper_left),
        ]

        # Neumann
        dTdr_vals = data["ZONE T"]["node data"]["dTempdx [K/m]"]
        dTdz_vals = data["ZONE T"]["node data"]["dTempdz [K/m]"]

        class TecplotNeumannBC(Expression):
            def eval(self, value, x):
                # Same problem as above: This expression is not only evaluated
                # at boundaries.
                for edge in data["ZONE T"]["element data"]:
                    X0 = RZ[edge[0] - 1]
                    X1 = RZ[edge[1] - 1]
                    theta = numpy.dot(X1 - X0, x - X0) / numpy.dot(
                        X1 - X0, X1 - X0)
                    dist = numpy.linalg.norm((1 - theta) * X0 + theta * X1 - x)
                    if dist < 1.0e-5 and 0.0 <= theta and theta <= 1.0:
                        value[0] = (1 - theta) * dTdr_vals[
                            edge[0] - 1] + theta * dTdr_vals[edge[1] - 1]
                        value[1] = (1 - theta) * dTdz_vals[
                            edge[0] - 1] + theta * dTdz_vals[edge[1] - 1]
                        break
                return

            def value_shape(self):
                return (2, )

        tecplot_nbc = TecplotNeumannBC(degree=5)
        n = FacetNormal(self.Q.mesh())
        self.theta_bcs_n = {
            submesh_boundary_indices["upper right"]: dot(n, tecplot_nbc),
            submesh_boundary_indices["crucible"]: dot(n, tecplot_nbc),
        }
        self.theta_bcs_r = {}

        # It seems that the boundary conditions from above are inconsistent in
        # that solving with Dirichlet overall and mixed Dirichlet-Neumann give
        # different results; the value *cannot* correspond to one solution.
        # From looking at the solutions, the pure Dirichlet setting appears
        # correct, so extract the Neumann values directly from that solution.

        # Pick fixed coefficients roughly at the temperature that we expect.
        # This could be made less magic by having the coefficients depend on
        # theta and solving the quasilinear equation.
        temp_estimate = 1550.0

        # Get material parameters
        wp_material = self.subdomain_materials[self.wpi]
        if isinstance(wp_material.specific_heat_capacity, float):
            cp = wp_material.specific_heat_capacity
        else:
            cp = wp_material.specific_heat_capacity(temp_estimate)
        if isinstance(wp_material.density, float):
            rho = wp_material.density
        else:
            rho = wp_material.density(temp_estimate)
        if isinstance(wp_material.thermal_conductivity, float):
            k = wp_material.thermal_conductivity
        else:
            k = wp_material.thermal_conductivity(temp_estimate)

        reference_problem = cyl_heat.Heat(
            self.Q,
            convection=None,
            kappa=k,
            rho=rho,
            cp=cp,
            source=Constant(0.0),
            dirichlet_bcs=self.theta_bcs_d_strict,
        )
        theta_reference = reference_problem.solve_stationary()
        theta_reference.rename("theta", "temperature (Dirichlet)")

        # Create equivalent boundary conditions from theta_ref. This
        # makes sure that the potentially expensive Expression evaluation in
        # theta_bcs_* is replaced by something reasonably cheap.
        self.theta_bcs_d = [
            DirichletBC(bc.function_space(), theta_reference,
                        bc.domain_args[0]) for bc in self.theta_bcs_d
        ]
        # Adapt Neumann conditions.
        n = FacetNormal(self.Q.mesh())
        self.theta_bcs_n = {
            k: dot(n, grad(theta_reference))
            # k: Constant(1000.0)
            for k in self.theta_bcs_n
        }

        if DEBUG:
            # Solve the heat equation with the mixed Dirichlet-Neumann
            # boundary conditions and compare it to the Dirichlet-only
            # solution.
            theta_new = Function(self.Q,
                                 name="temperature (Neumann + Dirichlet)")
            from dolfin import Measure

            ds_workpiece = Measure("ds", subdomain_data=self.wp_boundaries)

            heat = cyl_heat.Heat(
                self.Q,
                convection=None,
                kappa=k,
                rho=rho,
                cp=cp,
                source=Constant(0.0),
                dirichlet_bcs=self.theta_bcs_d,
                neumann_bcs=self.theta_bcs_n,
                robin_bcs=self.theta_bcs_r,
                my_ds=ds_workpiece,
            )
            theta_new = heat.solve_stationary()
            theta_new.rename("theta", "temperature (Neumann + Dirichlet)")

            from dolfin import plot, interactive, errornorm

            print("||theta_new - theta_ref|| = {:e}".format(
                errornorm(theta_new, theta_reference)))
            plot(theta_reference)
            plot(theta_new)
            plot(theta_reference - theta_new, title="theta_ref - theta_new")
            interactive()

        self.background_temp = 1400.0

        # self.omega = 2 * pi * 10.0e3
        self.omega = 2 * pi * 300.0

        return
Exemple #31
0
    def __init__(self,
                 mesh: df.Mesh,
                 time: df.Constant,
                 M_i: tp.Union[df.Expression, tp.Dict[int, df.Expression]],
                 M_e: tp.Union[df.Expression, tp.Dict[int, df.Expression]],
                 I_s: tp.Union[df.Expression, tp.Dict[int,
                                                      df.Expression]] = None,
                 I_a: tp.Union[df.Expression, tp.Dict[int,
                                                      df.Expression]] = None,
                 ect_current: tp.Dict[int, df.Expression] = None,
                 v_: df.Function = None,
                 cell_domains: df.MeshFunction = None,
                 facet_domains: df.MeshFunction = None,
                 dirichlet_bc: tp.List[tp.Tuple[df.Expression, int]] = None,
                 dirichlet_bc_v: tp.List[tp.Tuple[df.Expression, int]] = None,
                 periodic_domain: df.SubDomain = None,
                 parameters: df.Parameters = None) -> None:
        """Initialise solverand check all parametersare correct.

        NB! The periodic domain has to be set in the cellsolver too.
        """
        self._timestep = None

        comm = df.MPI.comm_world
        rank = df.MPI.rank(comm)

        msg = "Expecting mesh to be a Mesh instance, not {}".format(mesh)
        assert isinstance(mesh, df.Mesh), msg

        msg = "Expecting time to be a Constant instance (or None)."
        assert isinstance(time, df.Constant) or time is None, msg

        msg = "Expecting parameters to be a Parameters instance (or None)"
        assert isinstance(parameters, df.Parameters) or parameters is None, msg

        self._nullspace_basis = None

        # Store input
        self._mesh = mesh
        self._time = time

        # Initialize and update parameters if given
        self._parameters = self.default_parameters()
        if parameters is not None:
            self._parameters.update(parameters)

        if self._parameters["Chi"] == -1 or self._parameters["Cm"] == -1:
            raise ValueError(
                "Need Chi and Cm to be specified explicitly throug the parameters."
            )

        # Set-up function spaces
        k = self._parameters["polynomial_degree"]
        Ve = df.FiniteElement("CG", self._mesh.ufl_cell(), k)
        V = df.FunctionSpace(self._mesh,
                             "CG",
                             k,
                             constrained_domain=periodic_domain)
        Ue = df.FiniteElement("CG", self._mesh.ufl_cell(), k)

        if self._parameters["linear_solver_type"] == "direct":
            Re = df.FiniteElement("R", self._mesh.ufl_cell(), 0)
            _element = df.MixedElement((Ve, Ue, Re))
            self.VUR = df.FunctionSpace(mesh,
                                        _element,
                                        constrained_domain=periodic_domain)
        else:
            _element = df.MixedElement((Ve, Ue))
            self.VUR = df.FunctionSpace(mesh,
                                        _element,
                                        constrained_domain=periodic_domain)

        self.V = V

        if cell_domains is None:
            cell_domains = df.MeshFunction("size_t", mesh,
                                           self._mesh.geometry().dim())
            cell_domains.set_all(0)

        # Chech that it is indeed a cell function.
        cell_dim = cell_domains.dim()
        mesh_dim = self._mesh.geometry().dim()
        msg = "Got {cell_dim}, expected {mesh_dim}.".format(cell_dim=cell_dim,
                                                            mesh_dim=mesh_dim)
        assert cell_dim == mesh_dim, msg
        self._cell_domains = cell_domains

        if facet_domains is None:
            facet_domains = df.MeshFunction("size_t", mesh,
                                            self._mesh.geometry().dim() - 1)
            facet_domains.set_all(0)

        # Check that it is indeed a facet function.
        facet_dim = facet_domains.dim()
        msg = "Got {facet_dim}, expected {mesh_dim}.".format(
            facet_dim=facet_dim, mesh_dim=mesh_dim - 1)
        assert facet_dim == mesh_dim - 1, msg
        self._facet_domains = facet_domains

        # Gather all cell keys on all processes. Greatly simplifies things
        cell_keys = set(self._cell_domains.array())
        all_cell_keys = comm.allgather(cell_keys)
        all_cell_keys = reduce(or_, all_cell_keys)

        # If Mi is not dict, make dict
        if not isinstance(M_i, dict):
            M_i = {int(i): M_i for i in all_cell_keys}
        else:  # Check that the keys match the cell function
            M_i_keys = set(M_i.keys())
            msg = "Got {M_i_keys}, expected {cell_keys}.".format(
                M_i_keys=M_i_keys, cell_keys=all_cell_keys)
            assert M_i_keys == all_cell_keys, msg

        # If Me is not dict, make dict
        if not isinstance(M_e, dict):
            M_e = {int(i): M_e for i in all_cell_keys}
        else:  # Check that the keys match the cell function
            M_e_keys = set(M_e.keys())
            msg = "Got {M_e_keys}, expected {cell_keys}.".format(
                M_e_keys=M_e_keys, cell_keys=all_cell_keys)
            assert M_e_keys == all_cell_keys, msg
        self._M_i = M_i
        self._M_e = M_e

        # Store source terms
        if I_s is not None and not isinstance(I_s, dict):
            I_s = {key: I_s for key in all_cell_keys}
        self._I_s = I_s

        if I_a is not None and not isinstance(I_a, dict):
            I_a = {key: I_a for key in all_cell_keys}
        self._I_a = I_a

        # Set the ECT current, Note, it myst depend on `time` to be updated
        if ect_current is not None:
            ect_tags = set(ect_current.keys())
            facet_tags = set(self._facet_domains.array())
            msg = "{} not in facet domains ({}).".format(ect_tags, facet_tags)
            assert ect_tags <= facet_tags, msg
        self._ect_current = ect_current

        # Set-up solution fields:
        if v_ is None:
            self.merger = df.FunctionAssigner(V, self.VUR.sub(0))
            self.v_ = df.Function(V, name="v_")
        else:
            # df.debug("Experimental: v_ shipped from elsewhere.")
            self.merger = None
            self.v_ = v_
        self.vur = df.Function(self.VUR, name="vur")

        # Set Dirichlet bcs for the transmembrane potential
        self._bcs = []
        if dirichlet_bc_v is not None:
            for function, marker in dirichlet_bc_v:
                self._bcs.append(
                    df.DirichletBC(self.VUR.sub(0), function,
                                   self._facet_domains, marker))

        # Set Dirichlet bcs for the extra cellular potential
        if dirichlet_bc is not None:
            for function, marker in dirichlet_bc:
                self._bcs.append(
                    df.DirichletBC(self.VUR.sub(1), function,
                                   self._facet_domains, marker))
pres = 400
k = 1

# Directory for output
outdir_base = './../../results/MovingMesh/'

mesh = RectangleMesh(Point(xmin, ymin), Point(xmax, ymax), nx, ny)
n = FacetNormal(mesh)

outfile = File(mesh.mpi_comm(), outdir_base+"psi_h.pvd")

V = VectorFunctionSpace(mesh, 'DG', 2)
Vcg = VectorFunctionSpace(mesh, 'CG', 1)

boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1)
boundaries.set_all(0)
ds = Measure('ds', domain=mesh, subdomain_data=boundaries)

# Create function spaces
Q_E_Rho = FiniteElement("DG", mesh.ufl_cell(), k)
T_1 = FunctionSpace(mesh, 'DG', 0)
Qbar_E = FiniteElement("DGT", mesh.ufl_cell(), k)

Q_Rho = FunctionSpace(mesh, Q_E_Rho)
Qbar = FunctionSpace(mesh, Qbar_E)

phih, phih0 = Function(Q_Rho), Function(Q_Rho)
phibar = Function(Qbar)

# Advective velocity
# Swirling deformation advection (see LeVeque)
Exemple #33
0
def setup_geometry(interior_circle=True, num_mesh_refinements=0):
    # Generate mesh
    xmin, xmax = 0.0, 4.0
    ymin, ymax = 0.0, 1.0
    mesh_resolution = 30
    geometry1 = Rectangle(Point(xmin, ymin), Point(xmax, ymax))
    center = Point(0.5, 0.5)
    r = 0.1
    side_length = 0.1
    if interior_circle:
        geometry2 = Circle(center, r)
    else:
        l2 = side_length / 2
        geometry2 = Rectangle(Point(center[0] - l2, center[1] - l2),
                              Point(center[0] + l2, center[1] + l2))
    mesh = generate_mesh(geometry1 - geometry2, mesh_resolution)

    # Refine mesh around the interior boundary
    for i in range(0, num_mesh_refinements):
        cell_markers = MeshFunction("bool", mesh, mesh.topology().dim())
        for c in cells(mesh):
            p = c.midpoint()
            cell_markers[c] = (abs(p[0] - .5) < .5 and abs(p[1] - .5) < .3
                               and c.diameter() > .1) or c.diameter() > .2
        mesh = refine(mesh, cell_markers)

    # Mark regions for boundary conditions
    eps = 1e-5
    # Part of the boundary with zero pressure
    om = Expression("x[0] > XMAX - eps ? 1. : 0.",
                    XMAX=xmax,
                    eps=eps,
                    degree=1)
    # Part of the boundary with prescribed velocity
    im = Expression("x[0] < XMIN + eps ? 1. : 0.",
                    XMIN=xmin,
                    eps=eps,
                    degree=1)
    # Part of the boundary with zero velocity
    nm = Expression("x[0] > XMIN + eps && x[0] < XMAX - eps ? 1. : 0.",
                    XMIN=xmin,
                    XMAX=xmax,
                    eps=eps,
                    degree=1)

    # Define interior boundary
    class InteriorBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Compute squared distance to interior object midpoint
            d2 = (x[0] - center[0])**2 + (x[1] - center[1])**2
            return on_boundary and d2 < (2 * r)**2

    # Create mesh function over the cell facets
    sub_domains = MeshFunction("size_t", mesh, mesh.topology().dim() - 1)
    # Mark all facets as sub domain 0
    sub_domains.set_all(0)
    # Mark interior boundary facets as sub domain 1
    interior_boundary = InteriorBoundary()
    interior_boundary.mark(sub_domains, 1)

    return mesh, om, im, nm, ymax, sub_domains
Exemple #34
0
def femsolve():
    
    ''' Bilineaarinen muoto:

        a(u,v) = L(v)
        a(u,v) = (inner(grad(u), grad(v)) + u*v)*dx
        L(v) = f*v*dx - g*v*ds
        g(x) = -du/dx = -u1, x = x1
        u(x0) = u0
        Omega = {xeR|x0<=x<=x1}

    '''

    from dolfin import UnitInterval, FunctionSpace, DirichletBC, TrialFunction
    from dolfin import TestFunction, grad, Constant, Function, solve, inner, dx, ds
    from dolfin import MeshFunction, assemble
    import dolfin
#    from dolfin import set_log_level, PROCESS

    # Create mesh and define function space
    mesh = UnitInterval(30)
    V = FunctionSpace(mesh, 'Lagrange', 2)

    boundaries  = MeshFunction('uint', mesh, mesh.topology().dim()-1)

    boundaries.set_all(0)

    class Left(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            tol = 1E-14   # tolerance for coordinate comparisons
            return on_boundary and abs(x[0]) < tol

    class Right(dolfin.SubDomain):
        def inside(self, x, on_boundary):
            return dolfin.near(x[0], 1.0)
    
    left = Left()
    right = Right()
    
    left.mark(boundaries, 1)
    right.mark(boundaries, 2)

#    def u0_boundary(x):
#        return abs(x[0]) < tol
#    
#    bc = DirichletBC(V, Constant(u0), lambda x: abs(x[0]) < tol)
    
    bcs = [DirichletBC(V, Constant(u0), boundaries, 1)]
    
    # Define variational problem
    u = TrialFunction(V)
    v = TestFunction(V)
    a = (inner(grad(u), grad(v)) + u*v)*dx
    g = Constant(-u1)
    L = Constant(f)*v*dx - g*v*ds(2)
    
 #   set_log_level(PROCESS)
    # Compute solution
    
    A = assemble(a, exterior_facet_domains=boundaries)
    b = assemble(L, exterior_facet_domains=boundaries)
    for bc in bcs: 
        bc.apply(A, b)
    
    u = Function(V)
    solve(A, u.vector(), b, 'lu')
    
    coor = mesh.coordinates()
    u_array = u.vector().array()
    a = []
    b = []
    for i in range(mesh.num_vertices()):
        a.append(coor[i])
        b.append(u_array[i])
        print('u(%3.2f) = %0.14E'%(coor[i],u_array[i]))
    
    import numpy as np
    np.savez('fem',a,b)
class Solver(object):

    """
    First order FEM with CR elements.

    Nonconforming CR elements give lower bounds for eigenvalues
    after apropriate postprocessing is applied.
    """

    def __init__(self, mesh, num, denom, method="CR"):
        """ Assemble matrices and cache matrices. """
        self.V = FunctionSpace(mesh, method, 1)
        # save coordinates of DOFs
        self.dofs = np.reshape(self.V.dofmap().tabulate_all_coordinates(mesh),
                               (-1, 2))
        u = TrialFunction(self.V)
        v = TestFunction(self.V)
        self.boundary = MeshFunction("size_t", mesh, 1)
        # assemble matrices
        a = inner(grad(u), grad(v)) * dx
        b = u * v * dx
        self.A = uBLASSparseMatrix()
        self.A = assemble(a, tensor=self.A)
        self.A.compress()
        self.B = uBLASSparseMatrix()
        self.B = assemble(b, tensor=self.B)
        self.B.compress()
        size = mesh.size(2)
        # cell diameter calculation
        self.H2 = (num ** 2 + denom ** 2) * 1.0 / size
        # print "Theoretical cell diameter: ", sqrt(self.H2)
        # print "FEniCS calculated: ", mesh.hmax()

        # Matrices have rational entries. We can rescale to get integers
        # and save as scipy matrices
        scaleB = 6.0*size/num/denom
        self.scaleB = scaleB
        self.B *= scaleB
        r, c, val = self.B.data()
        val = np.round(val)
        self.B = sps.csr_matrix((val, c, r))
        # check if B is diagonal
        assert len(self.B.diagonal()) == self.B.nnz
        # find B inverse
        self.Binv = sps.csr_matrix((1.0/val, c, r))
        scaleA = 1.0*num*denom/2
        self.scaleA = scaleA
        self.A *= scaleA
        r, c, val = self.A.data()
        self.A = sps.csr_matrix((np.round(val), c, r))

        self.scale = scaleA/scaleB
        print 'scaling A by: ', scaleA
        print 'scaling B by: ', scaleB
        print 'eigenvalues scale by:', self.scale

    def solve(self, dirichlet=lambda x: False, plotted=None):
        """
        Find eigenvalues given a boundary condition function.

        dirichlet is a function returning True if x is on Dirichlet BC.
        """
        self.boundary.set_all(0)
        d = Dirichlet()
        d.init(dirichlet)
        d.mark(self.boundary, 1)
        if plotted is not None:
            plotted.plot(self.boundary)
        #    plotted.write_png()

        # indices for non-Dirichlet rows/columns
        indices = np.nonzero(np.apply_along_axis(
            lambda x: not dirichlet(x), 1, self.dofs))[0]
        # remove Dirichlet rows and columns from A
        self.AA = (self.A[indices, :]).tocsc()[:, indices]
        # remove Dirichlet rows and columns from B
        self.BB = (self.B[indices, :]).tocsc()[:, indices]
        self.BBinv = (self.Binv[indices, :]).tocsc()[:, indices]
        # solve using scipy
        eigs, eigfs = ssl.eigsh(self.AA, k=2, M=self.BB, sigma=0, which='LM')
        self.raweigs = [eigs[0], eigs[1]]
        eig = eigs[0]
        # turn eigf into a function
        eigf = np.array(eigfs[:, 0]).flatten()
        # we were solving only for some dofs, rest is 0
        # u = Function(self.V)
        # u.vector()[:] = 0
        # u.vector()[indices] = eigf
        # find algebraic residual
        # both L2 norm of u and B norm of eigf should equal 1
        # print assemble(u*u*dx), self.BB.dot(eigf).dot(eigf)
        res = self.AA.dot(eigf) - eig * self.BB.dot(eigf)
        resnorm = np.sqrt(self.BBinv.dot(res).dot(res))
        self.residual = [resnorm, 0]
        # apply Carstensen-Gedicke transformations to eig
        #
        # kappa^2 less than 0.1932
        eig = (eig - resnorm) / (1 + 0.1932 * (eig - resnorm) *
                                 self.H2 / self.scale)
        # scale back the eigenvalue
        eig = eig/self.scale
        # find residual for the second eigenvalue (for gap calculations)
        eigf = np.array(eigfs[:, 1]).flatten()
        res = self.AA.dot(eigf) - eigs[1] * self.BB.dot(eigf)
        resnorm = np.sqrt(self.BBinv.dot(res).dot(res))
        self.residual[1] = resnorm
        # return (eig, u)  # pair (eigenvalue,eigenfunctions)
        return (eig, None)  # pair (eigenvalue,eigenfunctions)