def amg_solve(N, method):
        # Elasticity parameters
        E = 1.0e9
        nu = 0.3
        mu = E / (2.0 * (1.0 + nu))
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))

        # Stress computation
        def sigma(v):
            return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(
                grad(v))) * Identity(2)

        # Define problem
        mesh = UnitSquareMesh(MPI.comm_world, N, N)
        V = VectorFunctionSpace(mesh, 'Lagrange', 1)
        bc0 = Function(V)
        with bc0.vector().localForm() as bc_local:
            bc_local.set(0.0)

        def boundary(x, only_boundary):
            return [only_boundary] * x.shape(0)

        bc = DirichletBC(V.sub(0), bc0, boundary)
        u = TrialFunction(V)
        v = TestFunction(V)

        # Forms
        a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector(
            (1.0, 1.0)), v) * dx

        # Assemble linear algebra objects
        A = assemble_matrix(a, [bc])
        A.assemble()
        b = assemble_vector(L)
        apply_lifting(b, [a], [[bc]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        set_bc(b, [bc])

        # Create solution function
        u = Function(V)

        # Create near null space basis and orthonormalize
        null_space = build_nullspace(V, u.vector())

        # Attached near-null space to matrix
        A.set_near_nullspace(null_space)

        # Test that basis is orthonormal
        assert null_space.is_orthonormal()

        # Create PETSC smoothed aggregation AMG preconditioner, and
        # create CG solver
        solver = PETScKrylovSolver("cg", method)

        # Set matrix operator
        solver.set_operator(A)

        # Compute solution and return number of iterations
        return solver.solve(u.vector(), b)
Beispiel #2
0
def pot():
    # Define mesh and boundaries.
    mesh = RectangleMesh(0.0, 0.0, 0.4, 0.1, 120, 30, "left/right")

    V = VectorFunctionSpace(mesh, "CG", 2)
    Q = FunctionSpace(mesh, "CG", 1)

    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] > 0.4 - 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.1 - GMSH_EPS

    upper_boundary = UpperBoundary()

    # Boundary conditions for the velocity.
    u_bcs = [
        DirichletBC(V, (0.0, 0.0), lower_boundary),
        DirichletBC(V.sub(1), 0.0, upper_boundary),
        DirichletBC(V.sub(0), 0.0, right_boundary),
        DirichletBC(V.sub(0), 0.0, left_boundary),
    ]
    p_bcs = []
    return mesh, V, Q, u_bcs, p_bcs, [lower_boundary], [right_boundary, left_boundary]
Beispiel #3
0
 def __init__(self, u, name="Assigned Vector Function"):
     
     self.u = u
     assert isinstance(u, ListTensor)
     V = u[0].function_space()
     mesh = V.mesh()
     family = V.ufl_element().family()
     degree = V.ufl_element().degree()
     constrained_domain = V.dofmap().constrained_domain            
     Vv = VectorFunctionSpace(mesh, family, degree, constrained_domain=constrained_domain)
     
     Function.__init__(self, Vv, name=name)
     self.fa = [FunctionAssigner(Vv.sub(i), V) for i, _u in enumerate(u)]
Beispiel #4
0
    def amg_solve(N, method):
        # Elasticity parameters
        E = 1.0e9
        nu = 0.3
        mu = E / (2.0 * (1.0 + nu))
        lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu))

        # Stress computation
        def sigma(v):
            return 2.0 * mu * sym(grad(v)) + lmbda * tr(sym(
                grad(v))) * Identity(2)

        # Define problem
        mesh = UnitSquareMesh(MPI.comm_world, N, N)
        V = VectorFunctionSpace(mesh, 'Lagrange', 1)
        bc0 = Function(V)
        bc = DirichletBC(V.sub(0), bc0, lambda x, on_boundary: on_boundary)
        u = TrialFunction(V)
        v = TestFunction(V)

        # Forms
        a, L = inner(sigma(u), grad(v)) * dx, dot(ufl.as_vector(
            (1.0, 1.0)), v) * dx

        # Assemble linear algebra objects
        A, b = assemble_system(a, L, bc)

        # Create solution function
        u = Function(V)

        # Create near null space basis and orthonormalize
        null_space = build_nullspace(V, u.vector())

        # Attached near-null space to matrix
        A.set_near_nullspace(null_space)

        # Test that basis is orthonormal
        assert null_space.is_orthonormal()

        # Create PETSC smoothed aggregation AMG preconditioner, and
        # create CG solver
        solver = PETScKrylovSolver("cg", method)

        # Set matrix operator
        solver.set_operator(A)

        # Compute solution and return number of iterations
        return solver.solve(u.vector(), b)
Beispiel #5
0
    def __init__(self, u, name="Assigned Vector Function"):

        self.u = u
        assert isinstance(u, ListTensor)
        V = u[0].function_space()
        mesh = V.mesh()
        family = V.ufl_element().family()
        degree = V.ufl_element().degree()
        constrained_domain = V.dofmap().constrained_domain
        Vv = VectorFunctionSpace(mesh,
                                 family,
                                 degree,
                                 constrained_domain=constrained_domain)

        Function.__init__(self, Vv, name=name)
        self.fa = [FunctionAssigner(Vv.sub(i), V) for i, _u in enumerate(u)]
Beispiel #6
0
class SNDiscretization(Discretization):
  def __init__(self, problem, SN_order, verbosity=0):
    super(SNDiscretization, self).__init__(problem, verbosity)

    if self.verb > 1: print0("Obtaining angular discretization data")
    t_ordinates = Timer("Angular discretization data")

    from transport_data import ordinates_ext_module, quadrature_file
    from common import check_sn_order

    self.angular_quad = ordinates_ext_module.OrdinatesData(SN_order, self.mesh.topology().dim(), quadrature_file)
    self.M = self.angular_quad.get_M()
    self.N = check_sn_order(SN_order)

    ord_mat = [self.angular_quad.get_xi().tolist(), self.angular_quad.get_eta().tolist()]
    if self.angular_quad.get_D() == 3: ord_mat.append(self.angular_quad.get_mu().tolist())
    self.ordinates_matrix = as_matrix(ord_mat)

    if self.verb > 2:
      self.angular_quad.print_info()

  def init_solution_spaces(self, group_GS=False):
    if self.verb > 1: print0("Defining function spaces" )

    self.t_spaces.start()

    self.Vpsi1 = VectorFunctionSpace(self.mesh, "CG", self.parameters["p"], self.M)

    if not group_GS:
      self.V = MixedFunctionSpace([self.Vpsi1]*self.G)
    else:
      # Alias the solution space as Vpsi1
      self.V = self.Vpsi1

    self.Vphi1 = FunctionSpace(self.mesh, "CG", self.parameters["p"])

    self.ndof1 = self.Vpsi1.dim()
    self.ndof = self.V.dim()

    if self.verb > 1:
      print0("  {0} direction(s), {1} group(s), {2}".format(self.M, self.G, "group GS" if group_GS else "full system"))
      print0("    NDOF (solution): {0}".format(self.ndof) )
      print0("    NDOF (1gr): {0}".format(self.ndof1) )
      print0("    NDOF (1dir, 1gr): {0}".format(self.Vpsi1.sub(0).dim()) )
      print0("    NDOF (XS): {0}".format(self.ndof0) )
Beispiel #7
0
def save_tstep_solution_h5(tstep, q_, u_, newfolder, tstepfiles, constrained_domain,
                           output_timeseries_as_vector, u_components, 
                           scalar_components, NS_parameters):
    """Store solution on current timestep to XDMF file."""
    timefolder = path.join(newfolder, 'Timeseries')
    if output_timeseries_as_vector:
        # project or store velocity to vector function space
        for comp, tstepfile in tstepfiles.iteritems():
            if comp == "u":
                if not hasattr(tstepfile, 'uv'): # First time around only
                    V = q_['u0'].function_space()
                    Vv = VectorFunctionSpace(V.mesh(), V.ufl_element().family(), V.ufl_element().degree(),
                                            constrained_domain=constrained_domain)
                    tstepfile.uv = Function(Vv)
                    tstepfile.d = dict((ui, Vv.sub(i).dofmap().collapse(Vv.mesh())[1]) 
                                       for i, ui in enumerate(u_components))

                # The short but timeconsuming way:
                #tstepfile.uv.assign(project(u_, Vv))
                
                # Or the faster, but more comprehensive way:
                for ui in u_components:
                    q_[ui].update()    
                    vals = tstepfile.d[ui].values()
                    keys = tstepfile.d[ui].keys()
                    tstepfile.uv.vector()[vals] = q_[ui].vector()[keys]
                tstepfile << (tstepfile.uv, float(tstep))
            
            elif comp in q_:                
                tstepfile << (q_[comp], float(tstep))
            
            else:
                tstepfile << (tstepfile.function, float(tstep))
            
    else:
        for comp, tstepfile in tstepfiles.iteritems():
            tstepfile << (q_[comp], float(tstep))
        
    if MPI.rank(mpi_comm_world()) == 0:
        if not path.exists(path.join(timefolder, "params.dat")):
            f = open(path.join(timefolder, 'params.dat'), 'w')
            cPickle.dump(NS_parameters,  f)
Beispiel #8
0
def save_tstep_solution_h5(tstep, q_, u_, newfolder, tstepfiles, constrained_domain,
                           output_timeseries_as_vector, u_components,
                           scalar_components, NS_parameters):
    """Store solution on current timestep to XDMF file."""
    timefolder = path.join(newfolder, 'Timeseries')
    if output_timeseries_as_vector:
        # project or store velocity to vector function space
        for comp, tstepfile in tstepfiles.iteritems():
            if comp == "u":
                V = q_['u0'].function_space()
                # First time around create vector function and assigners
                if not hasattr(tstepfile, 'uv'):
                    Vv = VectorFunctionSpace(V.mesh(), V.ufl_element().family(), V.ufl_element().degree(),
                                            constrained_domain=constrained_domain)
                    tstepfile.uv = Function(Vv)
                    tstepfile.fa = [FunctionAssigner(Vv.sub(i), V) for i, ui in enumerate(u_components)]

                # Assign solution to vector
                for i, ui in enumerate(u_components):
                    tstepfile.fa[i].assign(tstepfile.uv.sub(i), q_[ui])
                    
                # Store solution vector
                tstepfile << (tstepfile.uv, float(tstep))
            
            elif comp in q_:                
                tstepfile << (q_[comp], float(tstep))
            
            else:
                tstepfile << (tstepfile.function, float(tstep))
            
    else:
        for comp, tstepfile in tstepfiles.iteritems():
            tstepfile << (q_[comp], float(tstep))
        
    if MPI.rank(mpi_comm_world()) == 0:
        if not path.exists(path.join(timefolder, "params.dat")):
            f = open(path.join(timefolder, 'params.dat'), 'w')
            cPickle.dump(NS_parameters,  f)
def m_linear(integrator_type, mesh, subdomains, boundaries, t_start, dt, T, solution0, \
                 alpha_0, K_0, mu_l_0, lmbda_l_0, Ks_0, \
                 alpha_1, K_1, mu_l_1, lmbda_l_1, Ks_1, \
                 alpha, K, mu_l, lmbda_l, Ks, \
                 cf_0, phi_0, rho_0, mu_0, k_0,\
                 cf_1, phi_1, rho_1, mu_1, k_1,\
                 cf, phi, rho, mu, k, \
                 pressure_freeze):
    # Create mesh and define function space
    parameters["ghost_mode"] = "shared_facet" # required by dS

    dx = Measure('dx', domain=mesh, subdomain_data=subdomains)
    ds = Measure('ds', domain=mesh, subdomain_data=boundaries)
    dS = Measure('dS', domain=mesh, subdomain_data=boundaries)

    C = VectorFunctionSpace(mesh, "CG", 2)
    C = BlockFunctionSpace([C])
    TM = TensorFunctionSpace(mesh, 'DG', 0)
    PM = FunctionSpace(mesh, 'DG', 0)
    n = FacetNormal(mesh)
    vc = CellVolume(mesh)
    fc = FacetArea(mesh)

    h = vc/fc
    h_avg = (vc('+') + vc('-'))/(2*avg(fc))

    monitor_dt = dt

    f_stress_x = Constant(-1.e3)
    f_stress_y = Constant(-20.0e6)

    f = Constant((0.0, 0.0)) #sink/source for displacement

    I = Identity(mesh.topology().dim())

    # Define variational problem
    psiu, = BlockTestFunction(C)
    block_u = BlockTrialFunction(C)
    u, = block_split(block_u)
    w = BlockFunction(C)

    theta = -1.0

    a_time = inner(-alpha*pressure_freeze*I,sym(grad(psiu)))*dx #quasi static

    a = inner(2*mu_l*strain(u)+lmbda_l*div(u)*I, sym(grad(psiu)))*dx

    rhs_a = inner(f,psiu)*dx \
        + dot(f_stress_y*n,psiu)*ds(2)


    r_u = [a]

    #DirichletBC
    bcd1 = DirichletBC(C.sub(0).sub(0), 0.0, boundaries, 1) # No normal displacement for solid on left side
    bcd3 = DirichletBC(C.sub(0).sub(0), 0.0, boundaries, 3) # No normal displacement for solid on right side
    bcd4 = DirichletBC(C.sub(0).sub(1), 0.0, boundaries, 4) # No normal displacement for solid on bottom side
    bcs = BlockDirichletBC([bcd1,bcd3,bcd4])

    AA = block_assemble([r_u])
    FF = block_assemble([rhs_a - a_time])
    bcs.apply(AA)
    bcs.apply(FF)

    block_solve(AA, w.block_vector(), FF, "mumps")

    export_solution = w

    return export_solution, T
Beispiel #10
0
def karman():
    #mesh = Mesh('../meshes/2d/karman.xml')
    mesh = Mesh('../meshes/2d/karman-coarse2.xml')

    V = VectorFunctionSpace(mesh, 'CG', 2)
    Q = FunctionSpace(mesh, 'CG', 1)

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

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

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

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

    class ObstacleBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary \
                and x[0] > DOLFIN_EPS and x[0] < 2.5-DOLFIN_EPS \
                and x[1] > DOLFIN_EPS and x[1] < 0.4-DOLFIN_EPS
    obstacle_boundary = ObstacleBoundary()

    # Boundary conditions for the velocity.
    # Proper inflow and outflow conditions are a matter of voodoo. See for
    # example Gresho/Sani, or
    #
    #     Boundary conditions for open boundaries
    #     for the incompressible Navier-Stokes equation;
    #     B.C.V. Johansson;
    #     J. Comp. Phys. 105, 233-251 (1993).
    #
    # The latter in particularly suggest for the inflow:
    #
    #     u = u0,
    #     d^r v / dx^r = v_r,
    #     div(u) = 0,
    #
    # where u and v are the velocities in normal and tangential directions,
    # respectively, and r\in{0,1,2}. The setting r=0 essentially means to set
    # (u,v) statically at the left boundary, r=1 means to set u and control
    # dv/dn, which is what we do here (namely implicitly by dv/dn=0).
    # At the outflow,
    #
    #     d^j u / dx^j = 0,
    #     d^q v / dx^q = 0,
    #     p = p0,
    #
    # is suggested with j=q+1. Choosing q=0, j=1 means setting the tangential
    # component of the outflow to 0, and letting the normal component du/dn=0
    # (again, this is achieved implicitly by the weak formulation).
    #
    inflow = Expression('100*x[1]*(0.4-x[1])', degree=2)
    u_bcs = [DirichletBC(V, (0.0, 0.0), upper_boundary),
             DirichletBC(V, (0.0, 0.0), lower_boundary),
             DirichletBC(V, (0.0, 0.0), obstacle_boundary),
             DirichletBC(V.sub(0), inflow, left_boundary),
             #DirichletBC(V.sub(1), 0.0, right_boundary),
             ]
    dudt_bcs = [DirichletBC(V, (0.0, 0.0), upper_boundary),
                DirichletBC(V, (0.0, 0.0), lower_boundary),
                DirichletBC(V, (0.0, 0.0), obstacle_boundary),
                DirichletBC(V.sub(0), 0.0, left_boundary),
                #DirichletBC(V.sub(1), 0.0, right_boundary),
                ]
    # If there is a penetration boundary (i.e., n.u!=0), then the pressure must
    # be set at the boundary to make sure that the Navier-Stokes problem
    # remains consistent.
    # It is not quite clear now where exactly to set the pressure to 0. Inlet,
    # outlet, some other place? The PPE system is consistent in all cases.
    # TODO find out more about it
    #p_bcs = [DirichletBC(Q, 0.0, right_boundary)]
    p_bcs = []
    return mesh, V, Q, u_bcs, dudt_bcs, p_bcs
Beispiel #11
0
def crucible_without_coils():
    base = '../meshes/2d/crucible'
    mesh = Mesh(base + '.xml')
    subdomains = MeshFunction('size_t', mesh, base+'_physical_region.xml')
    workpiece_index = 4
    subdomain_materials = {1: 'SiC',
                           2: 'boron trioxide',
                           3: 'GaAs (solid)',
                           4: 'GaAs (liquid)'}

    submesh_workpiece = SubMesh(mesh, subdomains, workpiece_index)
    V = VectorFunctionSpace(submesh_workpiece, 'CG', 2)
    P = FunctionSpace(submesh_workpiece, 'CG', 1)

    Q = FunctionSpace(mesh, 'CG', 2)

    # Define mesh and 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.366 + GMSH_EPS < x[1] \
                and x[1] < 0.411 - GMSH_EPS
    left_boundary = LeftBoundary()

    class SurfaceBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Make sure to catch the entire surface, so don't be too
            # restrictive about x[0].
            return on_boundary \
                and x[1] > 0.38-GMSH_EPS \
                and x[0] > 0.04-GMSH_EPS and x[0] < 0.07+GMSH_EPS

    class OtherBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary \
                and not left_boundary.inside(x, on_boundary)  # \
                #and not surface_boundary.inside(x, on_boundary)
    other_boundary = OtherBoundary()

    # Boundary conditions for the velocity.
    u_bcs = [DirichletBC(V, (0.0, 0.0), other_boundary),
             DirichletBC(V.sub(0), 0.0, left_boundary),
             #DirichletBC(V.sub(1), 0.0, surface_boundary),
             ]
    #u_bcs = [DirichletBC(V, (0.0, 0.0), 'on_boundary')]
    p_bcs = []

    class HeaterBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary \
                and ((x[1] < 0.38 and GMSH_EPS < x[0]
                      and x[0] < 0.075+GMSH_EPS)
                     or x[0] < GMSH_EPS and x[1] < 0.365+GMSH_EPS)
    heater_boundary = HeaterBoundary()

    background_temp = 1400.0

    # Heat with 1580K at r=0, 1590K at r=0.075.
    heater_bcs = [(heater_boundary, '1580.0 + 133.0 * x[0]')]

    return mesh, subdomains, subdomain_materials, workpiece_index, \
        V, Q, P, u_bcs, p_bcs, background_temp, heater_bcs
Beispiel #12
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 = FacetFunction('size_t', submesh_workpiece)
    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
Beispiel #13
0
def karman():
    # mesh = Mesh('../meshes/2d/karman.xml')
    mesh = Mesh("../meshes/2d/karman-coarse2.xml")

    V = VectorFunctionSpace(mesh, "CG", 2)
    Q = FunctionSpace(mesh, "CG", 1)

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

    left_boundary = LeftBoundary()

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

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

    lower_boundary = LowerBoundary()

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

    upper_boundary = UpperBoundary()

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

    obstacle_boundary = ObstacleBoundary()

    # Boundary conditions for the velocity.
    # Proper inflow and outflow conditions are a matter of voodoo. See for
    # example Gresho/Sani, or
    #
    #     Boundary conditions for open boundaries
    #     for the incompressible Navier-Stokes equation;
    #     B.C.V. Johansson;
    #     J. Comp. Phys. 105, 233-251 (1993).
    #
    # The latter in particularly suggest for the inflow:
    #
    #     u = u0,
    #     d^r v / dx^r = v_r,
    #     div(u) = 0,
    #
    # where u and v are the velocities in normal and tangential directions,
    # respectively, and r\in{0,1,2}. The setting r=0 essentially means to set
    # (u,v) statically at the left boundary, r=1 means to set u and control
    # dv/dn, which is what we do here (namely implicitly by dv/dn=0).
    # At the outflow,
    #
    #     d^j u / dx^j = 0,
    #     d^q v / dx^q = 0,
    #     p = p0,
    #
    # is suggested with j=q+1. Choosing q=0, j=1 means setting the tangential
    # component of the outflow to 0, and letting the normal component du/dn=0
    # (again, this is achieved implicitly by the weak formulation).
    #
    inflow = Expression("100*x[1]*(0.4-x[1])", degree=2)
    u_bcs = [
        DirichletBC(V, (0.0, 0.0), upper_boundary),
        DirichletBC(V, (0.0, 0.0), lower_boundary),
        DirichletBC(V, (0.0, 0.0), obstacle_boundary),
        DirichletBC(V.sub(0), inflow, left_boundary),
        # DirichletBC(V.sub(1), 0.0, right_boundary),
    ]
    dudt_bcs = [
        DirichletBC(V, (0.0, 0.0), upper_boundary),
        DirichletBC(V, (0.0, 0.0), lower_boundary),
        DirichletBC(V, (0.0, 0.0), obstacle_boundary),
        DirichletBC(V.sub(0), 0.0, left_boundary),
        # DirichletBC(V.sub(1), 0.0, right_boundary),
    ]
    # If there is a penetration boundary (i.e., n.u!=0), then the pressure must
    # be set at the boundary to make sure that the Navier-Stokes problem
    # remains consistent.
    # It is not quite clear now where exactly to set the pressure to 0. Inlet,
    # outlet, some other place? The PPE system is consistent in all cases.
    # TODO find out more about it
    # p_bcs = [DirichletBC(Q, 0.0, right_boundary)]
    p_bcs = []
    return mesh, V, Q, u_bcs, dudt_bcs, p_bcs
Beispiel #14
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,
    )
Beispiel #15
0
def crucible_without_coils():
    base = "../meshes/2d/crucible"
    mesh = Mesh(base + ".xml")
    subdomains = MeshFunction("size_t", mesh, base + "_physical_region.xml")
    workpiece_index = 4
    subdomain_materials = {
        1: "SiC",
        2: "boron trioxide",
        3: "GaAs (solid)",
        4: "GaAs (liquid)",
    }

    submesh_workpiece = SubMesh(mesh, subdomains, workpiece_index)
    V = VectorFunctionSpace(submesh_workpiece, "CG", 2)
    P = FunctionSpace(submesh_workpiece, "CG", 1)

    Q = FunctionSpace(mesh, "CG", 2)

    # Define mesh and 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.366 + GMSH_EPS < x[1]
                and x[1] < 0.411 - GMSH_EPS
            )

    left_boundary = LeftBoundary()

    class SurfaceBoundary(SubDomain):
        def inside(self, x, on_boundary):
            # Make sure to catch the entire surface, so don't be too
            # restrictive about x[0].
            return (
                on_boundary
                and x[1] > 0.38 - GMSH_EPS
                and x[0] > 0.04 - GMSH_EPS
                and x[0] < 0.07 + GMSH_EPS
            )

    class OtherBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return (
                on_boundary
                and not left_boundary.inside(x, on_boundary)
                # and not surface_boundary.inside(x, on_boundary)
            )

    other_boundary = OtherBoundary()

    # Boundary conditions for the velocity.
    u_bcs = [
        DirichletBC(V, (0.0, 0.0), other_boundary),
        DirichletBC(V.sub(0), 0.0, left_boundary),
        # DirichletBC(V.sub(1), 0.0, surface_boundary),
    ]
    # u_bcs = [DirichletBC(V, (0.0, 0.0), 'on_boundary')]
    p_bcs = []

    class HeaterBoundary(SubDomain):
        def inside(self, x, on_boundary):
            return on_boundary and (
                (x[1] < 0.38 and GMSH_EPS < x[0] and x[0] < 0.075 + GMSH_EPS)
                or x[0] < GMSH_EPS
                and x[1] < 0.365 + GMSH_EPS
            )

    heater_boundary = HeaterBoundary()

    background_temp = 1400.0

    # Heat with 1580K at r=0, 1590K at r=0.075.
    heater_bcs = [(heater_boundary, "1580.0 + 133.0 * x[0]")]

    return (
        mesh,
        subdomains,
        subdomain_materials,
        workpiece_index,
        V,
        Q,
        P,
        u_bcs,
        p_bcs,
        background_temp,
        heater_bcs,
    )