예제 #1
0
def QuadBallSurface(center=(0., 0., 0.), radius=1., n=10, element_type="quad"):
    """Creates a surface quad mesh on sphere using midpoint subdivision algorithm
        by creating a cube and spherifying it using PostMesh's projection schemes.
        Unlike the volume QuadBall method there is no restriction on number of divisions
        here as no system of equations is solved

        inputs:

            n:                          [int] number of divsion in every direction.
                                        Given that this implementation is based on
                                        high order bases different divisions in
                                        different directions is not possible
    """

    try:
        from Florence import Mesh, BoundaryCondition, DisplacementFormulation, FEMSolver, LinearSolver
        from Florence import LinearElastic, NeoHookean
        from Florence.Tensor import prime_number_factorisation
    except ImportError:
        raise ImportError("This function needs Florence's core support")

    n = int(n)
    if not isinstance(center, tuple):
        raise ValueError(
            "The center of the circle should be given in a tuple with two elements (x,y,z)"
        )
    if len(center) != 3:
        raise ValueError(
            "The center of the circle should be given in a tuple with two elements (x,y,z)"
        )

    if n == 2 or n == 3 or n == 5 or n == 7:
        ps = [n]
    else:

        def factorise_all(n):
            if n < 2:
                n = 2
            factors = prime_number_factorisation(n)
            if len(factors) == 1 and n > 2:
                n += 1
                factors = prime_number_factorisation(n)
            return factors

        factors = factorise_all(n)
        ps = []
        for factor in factors:
            ps += factorise_all(factor)

    # Do high ps first
    ps = np.sort(ps)[::-1].tolist()
    niter = len(ps)

    sphere_igs_file_content = SphereIGS()
    with open("sphere_cad_file.igs", "w") as f:
        f.write(sphere_igs_file_content)

    sys.stdout = open(os.devnull, "w")

    ndim = 3
    scale = 1000.
    condition = 1.e020

    mesh = Mesh()
    material = LinearElastic(ndim, mu=1., lamb=4.)

    for it in range(niter):

        if it == 0:
            mesh.Parallelepiped(element_type="hex",
                                nx=1,
                                ny=1,
                                nz=1,
                                lower_left_rear_point=(-0.5, -0.5, -0.5),
                                upper_right_front_point=(0.5, 0.5, 0.5))
            mesh = mesh.CreateSurface2DMeshfrom3DMesh()
            mesh.GetHighOrderMesh(p=ps[it], equally_spaced=True)
            mesh = mesh.CreateDummy3DMeshfrom2DMesh()
            formulation = DisplacementFormulation(mesh)
        else:
            mesh.GetHighOrderMesh(p=ps[it], equally_spaced=True)
            mesh = mesh.CreateDummy3DMeshfrom2DMesh()

        boundary_condition = BoundaryCondition()
        boundary_condition.SetCADProjectionParameters(
            "sphere_cad_file.igs",
            scale=scale,
            condition=condition,
            project_on_curves=True,
            solve_for_planar_faces=True,
            modify_linear_mesh_on_projection=True,
            fix_dof_elsewhere=False)
        boundary_condition.GetProjectionCriteria(mesh)
        nodesDBC, Dirichlet = boundary_condition.PostMeshWrapper(
            formulation, mesh, None, None, FEMSolver())

        mesh.points[nodesDBC.ravel(), :] += Dirichlet
        mesh = mesh.CreateSurface2DMeshfrom3DMesh()
        mesh = mesh.ConvertToLinearMesh()

    os.remove("sphere_cad_file.igs")

    if not np.isclose(radius, 1):
        mesh.points *= radius

    mesh.points[:, 0] += center[0]
    mesh.points[:, 1] += center[1]
    mesh.points[:, 2] += center[2]

    if element_type == "tri":
        mesh.ConvertQuadsToTris()

    sys.stdout = sys.__stdout__

    return mesh
예제 #2
0
def QuadBall(center=(0., 0., 0.), radius=1., n=10, element_type="hex"):
    """Creates a fully hexahedral mesh on sphere using midpoint subdivision algorithm
        by creating a cube and spherifying it using PostMesh's projection schemes

        inputs:

            n:                          [int] number of divsion in every direction.
                                        Given that this implementation is based on
                                        high order bases different divisions in
                                        different directions is not possible
    """

    try:
        from Florence import Mesh, BoundaryCondition, DisplacementFormulation, FEMSolver, LinearSolver
        from Florence import LinearElastic, NeoHookean
        from Florence.Tensor import prime_number_factorisation
    except ImportError:
        raise ImportError("This function needs Florence's core support")

    n = int(n)
    if n > 50:
        # Values beyond this result in >1M DoFs due to internal prime factoristaion splitting
        raise ValueError(
            "The value of n={} (division in each direction) is too high".
            format(str(n)))

    if not isinstance(center, tuple):
        raise ValueError(
            "The center of the circle should be given in a tuple with two elements (x,y,z)"
        )
    if len(center) != 3:
        raise ValueError(
            "The center of the circle should be given in a tuple with two elements (x,y,z)"
        )

    if n == 2 or n == 3 or n == 5 or n == 7:
        ps = [n]
    else:

        def factorise_all(n):
            if n < 2:
                n = 2
            factors = prime_number_factorisation(n)
            if len(factors) == 1 and n > 2:
                n += 1
                factors = prime_number_factorisation(n)
            return factors

        factors = factorise_all(n)
        ps = []
        for factor in factors:
            ps += factorise_all(factor)

    # Do high ps first
    ps = np.sort(ps)[::-1].tolist()
    niter = len(ps)

    # IGS file for sphere with radius 1000.
    sphere_igs_file_content = SphereIGS()

    with open("sphere_cad_file.igs", "w") as f:
        f.write(sphere_igs_file_content)

    sys.stdout = open(os.devnull, "w")

    ndim = 3
    scale = 1000.
    condition = 1.e020

    mesh = Mesh()
    material = LinearElastic(ndim, mu=1., lamb=4.)
    # Keep the solver iterative for low memory consumption. All boundary points are Dirichlet BCs
    # so they will be exact anyway
    solver = LinearSolver(linear_solver="iterative",
                          linear_solver_type="cg2",
                          dont_switch_solver=True,
                          iterative_solver_tolerance=1e-9)

    for it in range(niter):

        if it == 0:
            mesh.Parallelepiped(element_type="hex",
                                nx=1,
                                ny=1,
                                nz=1,
                                lower_left_rear_point=(-0.5, -0.5, -0.5),
                                upper_right_front_point=(0.5, 0.5, 0.5))
        mesh.GetHighOrderMesh(p=ps[it], equally_spaced=True)

        boundary_condition = BoundaryCondition()
        boundary_condition.SetCADProjectionParameters(
            "sphere_cad_file.igs",
            scale=scale,
            condition=condition,
            project_on_curves=True,
            solve_for_planar_faces=True,
            modify_linear_mesh_on_projection=True,
            fix_dof_elsewhere=False)
        boundary_condition.GetProjectionCriteria(mesh)

        formulation = DisplacementFormulation(mesh)
        fem_solver = FEMSolver(number_of_load_increments=1,
                               analysis_nature="linear",
                               force_not_computing_mesh_qualities=True,
                               report_log_level=0,
                               optimise=True)

        solution = fem_solver.Solve(formulation=formulation,
                                    mesh=mesh,
                                    material=material,
                                    boundary_condition=boundary_condition,
                                    solver=solver)

        mesh.points += solution.sol[:, :, -1]
        mesh = mesh.ConvertToLinearMesh()

    os.remove("sphere_cad_file.igs")

    if not np.isclose(radius, 1):
        mesh.points *= radius

    mesh.points[:, 0] += center[0]
    mesh.points[:, 1] += center[1]
    mesh.points[:, 2] += center[2]

    if element_type == "tet":
        mesh.ConvertHexesToTets()

    sys.stdout = sys.__stdout__

    return mesh