예제 #1
0
파일: __init__.py 프로젝트: bd1747/HO_homog
def duplicate_pattern(cell_ll, nb_cells, gen_vect):
    """
    Propager la cellule de base dans selon les directions de l'espace.

    Parameters
    ----------
    cell_ll : list
        The LineLoops that will be replicated. They define the pattern for a unit cell.
    np_cells : tuple, dimension 2 or 3
        Number of cells in each direction.
    gen_vect : array
        The generating vectors that are related to the given microstruture.
        Vecteurs de périodicité, en colonnes

    Returns
    -------
    repeated_ll : list
        Repeated lineloops that define the pattern over the whole domain associated with the given numbers of cells.
    """
    repeated_ll = cell_ll
    if gen_vect.shape != (3, 3):
        gen_vect_3D = np.zeros((3, 3))
        gen_vect_3D[:gen_vect.shape[0], :gen_vect.shape[1]] = gen_vect
    else:
        gen_vect_3D = gen_vect
    for k in range(len(nb_cells)):
        if nb_cells[k] > 1:
            new_contours = list()
            for i in range(1, int(nb_cells[k])):
                new_contours += [
                    geo.translation(ll, i * gen_vect_3D[:, k])
                    for ll in repeated_ll
                ]
            repeated_ll += new_contours
    repeated_ll = geo.remove_duplicates(repeated_ll)
    return repeated_ll
예제 #2
0
파일: __init__.py 프로젝트: bd1747/HO_homog
def offset_pattern(cell_ll, offset, cell_vect):
    """
    Translation of the lineloops that define the microstructure geometry of a unit cell.

    Parameters
    ----------
    cell_ll : list of instances of LineLoop
    offset : 1D array
        relative coordinates with respect to the unit-cell generating vectors of the point that will be moved to the origin
    gen_vect : 2D array
        The generating vectors that are related to the given unit-cell.
    """
    if cell_vect.shape != (3, 3):
        cell_vect_3D = np.zeros((3, 3))
        cell_vect_3D[:cell_vect.shape[0], :cell_vect.shape[1]] = cell_vect
    else:
        cell_vect_3D = cell_vect
    offset_vect_relat = np.zeros(3)
    for i, val in enumerate(offset):
        offset_vect_relat[i] = val % 1.0
    offset_vect_abs = np.dot(cell_vect_3D, offset_vect_relat)
    t_vect = -1 * offset_vect_abs
    shifted_ll = [geo.translation(ll, t_vect) for ll in cell_ll]
    return shifted_ll
예제 #3
0
E2 = geo.Point(e2)
E1m = geo.Point(-1 * e1)
E2m = geo.Point(-1 * e2)
O_pt = np.zeros((3, ))
L = geo.Point(2 * (e1 + e2))
Lm = geo.Point(2 * (e1 - e2))
M = geo.Point(e1 + 1.5 * e2 + b / 2)
N = geo.Point(2 * (e1 + 1.5 * e2 + b / 2))

contours = list()
contours.append([E1, E2, E1m, E2m])
contours.append([E1, Lm, geo.Point(3 * e1), L])
contours.append([
    E2,
    L,
    geo.translation(L, b / 2 - p),
    geo.translation(L, b),
    geo.translation(E2, b),
    geo.translation(E2, b / 2 + p),
])
pattern_ll = [geo.LineLoop(pt_list, explicit=False) for pt_list in contours]

pattern_ll += [geo.point_reflection(ll, M) for ll in pattern_ll]
sym_ll = [geo.plane_reflection(ll, N, e1) for ll in pattern_ll]
for ll in sym_ll:
    ll.reverse()
pattern_ll += sym_ll
sym_ll = [geo.plane_reflection(ll, N, e2) for ll in pattern_ll]
for ll in sym_ll:
    ll.reverse()
pattern_ll += sym_ll
예제 #4
0
def test_get_domains_gmsh(plots=False):
    """ Get subdomains and partition of the boundary from a .msh file. """
    name = "test_domains"
    local_dir = Path(__file__).parent
    mesh_file = local_dir.joinpath(name + ".msh")
    gmsh.model.add(name)
    L_x, L_y = 2.0, 2.0
    H = 1.0
    vertices = [(0.0, 0.0), (0.0, L_y), (L_x, L_y), (L_x, 0.0)]
    contour = geo.LineLoop([geo.Point(np.array(c)) for c in vertices], False)
    surface = geo.PlaneSurface(contour)
    inclusion_vertices = list()
    for coord in [
        (H / 2, -H / 2, 0.0),
        (H / 2, H / 2, 0.0),
        (-H / 2, H / 2, 0.0),
        (-H / 2, -H / 2, 0.0),
    ]:
        vertex = geo.translation(geo.Point((L_x / 2, L_y / 2)), coord)
        inclusion_vertices.append(vertex)
    inclusion = geo.PlaneSurface(geo.LineLoop(inclusion_vertices, False))
    for s in [surface, inclusion]:
        s.add_gmsh()
    factory.synchronize()
    (stiff_s, ) = geo.surface_bool_cut(surface, inclusion)
    factory.synchronize()
    (soft_s, ) = geo.surface_bool_cut(surface, stiff_s)
    factory.synchronize()
    domains = {
        "stiff": geo.PhysicalGroup(stiff_s, 2),
        "soft": geo.PhysicalGroup(soft_s, 2),
    }
    boundaries = {
        "S": geo.PhysicalGroup(surface.ext_contour.sides[0], 1),
        "W": geo.PhysicalGroup(surface.ext_contour.sides[1], 1),
        "N": geo.PhysicalGroup(surface.ext_contour.sides[2], 1),
        "E": geo.PhysicalGroup(surface.ext_contour.sides[3], 1),
    }
    for group in domains.values():
        group.add_gmsh()
    for group in boundaries.values():
        group.add_gmsh()
    charact_field = mesh_tools.MathEvalField("0.05")
    mesh_tools.set_background_mesh(charact_field)
    geo.set_gmsh_option("Mesh.SaveAll", 0)
    model.mesh.generate(1)
    model.mesh.generate(2)
    gmsh.model.mesh.removeDuplicateNodes()
    gmsh.write(str(mesh_file))
    E_1, E_2, nu = 1, 3, 0.3
    materials = {
        domains["soft"].tag: mat.Material(E_1, nu, "cp"),
        domains["stiff"].tag: mat.Material(E_1, nu, "cp"),
    }
    test_part = part.FenicsPart.part_from_file(mesh_file,
                                               materials,
                                               subdomains_import=True)
    assert test_part.mat_area == approx(L_x * L_y)
    elem_type = "CG"
    degree = 2
    V = fe.VectorFunctionSpace(test_part.mesh, elem_type, degree)
    W = fe.FunctionSpace(
        test_part.mesh,
        fe.VectorElement(elem_type, test_part.mesh.ufl_cell(), degree, dim=3),
    )
    boundary_conditions = {
        boundaries["N"].tag: fe.Expression(("x[0]-1", "1"), degree=1),
        boundaries["S"].tag: fe.Expression(("x[0]-1", "-1"), degree=1),
        boundaries["E"].tag: fe.Expression(("1", "x[1]-1"), degree=1),
        boundaries["W"].tag: fe.Expression(("-1", "x[1]-1"), degree=1),
    }
    bcs = list()
    for tag, val in boundary_conditions.items():
        bcs.append(fe.DirichletBC(V, val, test_part.facet_regions, tag))
    ds = fe.Measure("ds",
                    domain=test_part.mesh,
                    subdomain_data=test_part.facet_regions)
    v = fe.TestFunctions(V)
    u = fe.TrialFunctions(V)
    F = (fe.inner(mat.sigma(test_part.elasticity_tensor, mat.epsilon(u)),
                  mat.epsilon(v)) * fe.dx)
    a, L = fe.lhs(F), fe.rhs(F)
    u_sol = fe.Function(V)
    fe.solve(a == L, u_sol, bcs)
    strain = fe.project(mat.epsilon(u_sol), W)
    if plots:
        import matplotlib.pyplot as plt

        plt.figure()
        plot = fe.plot(u_sol)
        plt.colorbar(plot)
        plt.figure()
        plot = fe.plot(strain[0])
        plt.colorbar(plot)
        plt.figure()
        plot = fe.plot(strain[1])
        plt.colorbar(plot)
        plt.figure()
        plot = fe.plot(strain[2])
        plt.colorbar(plot)
        plt.show()
    error = fe.errornorm(
        strain,
        fe.Expression(("1", "1", "0"), degree=0),
        degree_rise=3,
        mesh=test_part.mesh,
    )
    assert error == approx(0, abs=1e-12)

    materials = {
        domains["soft"].tag: mat.Material(E_1, nu, "cp"),
        domains["stiff"].tag: mat.Material(E_2, nu, "cp"),
    }
    test_part = part.FenicsPart.part_from_file(mesh_file,
                                               materials,
                                               subdomains_import=True)
    V = fe.VectorFunctionSpace(test_part.mesh, elem_type, degree)
    W = fe.FunctionSpace(
        test_part.mesh,
        fe.VectorElement(elem_type, test_part.mesh.ufl_cell(), degree, dim=3),
    )
    bcs = list()
    for tag, val in boundary_conditions.items():
        bcs.append(fe.DirichletBC(V, val, test_part.facet_regions, tag))
    v = fe.TestFunctions(V)
    u = fe.TrialFunctions(V)
    F = (fe.inner(mat.sigma(test_part.elasticity_tensor, mat.epsilon(u)),
                  mat.epsilon(v)) * fe.dx)
    a, L = fe.lhs(F), fe.rhs(F)
    u_sol = fe.Function(V)
    fe.solve(a == L, u_sol, bcs)
    strain = mat.epsilon(u_sol)
    stress = mat.sigma(test_part.elasticity_tensor, strain)
    energy = 0.5 * fe.assemble(
        fe.inner(stress, strain) * fe.dx(test_part.mesh))
    energy_abaqus = 12.8788939
    assert energy == approx(energy_abaqus, rel=1e-3)
    geo.reset()
예제 #5
0
def test_mat_area():
    """FenicsPart method global_aera, for 2D parts created from a gmsh mesh and from a FEniCS mesh"""
    L_x, L_y = 4.0, 5.0
    H = 1.0
    size = 0.5
    rectangle = mshr.Rectangle(fe.Point(0.0, 0), fe.Point(L_x, L_y))
    hole = mshr.Rectangle(
        fe.Point(L_x / 2 - H / 2, L_y / 2 - H / 2),
        fe.Point(L_x / 2 + H / 2, L_y / 2 + H / 2),
    )
    domain = rectangle - hole
    domain.set_subdomain(1, rectangle)
    mesh = mshr.generate_mesh(domain, size)
    dimensions = np.array(((L_x, 0.0), (0.0, L_y)))
    material = {"0": mat.Material(1.0, 0.3, "cp")}
    rect_part = part.FenicsPart(
        mesh,
        materials=material,
        subdomains=None,
        global_dimensions=dimensions,
        facet_regions=None,
    )
    assert rect_part.mat_area == (L_x * L_y - H**2)

    name = "test_mat_area"
    local_dir = Path(__file__).parent
    mesh_file = local_dir.joinpath(name + ".msh")
    gmsh.model.add(name)
    vertices = [(0.0, 0.0), (0.0, L_y), (L_x, L_y), (L_x, 0.0)]
    contour = geo.LineLoop([geo.Point(np.array(c)) for c in vertices], False)
    surface = geo.PlaneSurface(contour)
    cut_vertices = list()
    for local_coord in [(H, 0.0, 0.0), (0.0, H, 0.0), (-H, 0.0, 0.0),
                        (0.0, -H, 0.0)]:
        vertex = geo.translation(contour.vertices[2], np.array(local_coord))
        cut_vertices.append(vertex)
    cut_surface = geo.PlaneSurface(geo.LineLoop(cut_vertices, False))
    for s in [surface, cut_surface]:
        s.add_gmsh()
    factory.synchronize()
    (surface, ) = geo.surface_bool_cut(surface, cut_surface)
    factory.synchronize()
    for dim_tag in model.getEntities(2):
        if not dim_tag[1] == surface.tag:
            model.removeEntities([dim_tag], True)
    charact_field = mesh_tools.MathEvalField("0.1")
    mesh_tools.set_background_mesh(charact_field)
    geo.set_gmsh_option("Mesh.SaveAll", 1)
    model.mesh.generate(2)
    gmsh.write(str(mesh_file))
    cmd = f"dolfin-convert {mesh_file} {mesh_file.with_suffix('.xml')}"
    run(cmd, shell=True, check=True)
    mesh = fe.Mesh(str(mesh_file.with_suffix(".xml")))
    dimensions = np.array(((L_x, 0.0), (0.0, L_y)))
    material = {"0": mat.Material(1.0, 0.3, "cp")}
    rect_part = part.FenicsPart(
        mesh,
        materials=material,
        subdomains=None,
        global_dimensions=dimensions,
        facet_regions=None,
    )
    assert rect_part.mat_area == approx(L_x * L_y - H * H / 2)
    geo.reset()
예제 #6
0
def rotating_squares_RVE(theta,
                         r,
                         a=None,
                         b=None,
                         nb_cells=(1, 1),
                         offset=(0.0, 0.0),
                         name=""):
    """[summary]

    Parameters
    ----------
    theta : float
        Angle d'ouverture, \in [0; \pi/4].
            0 -> configuration refermé
            \pi/4 -> configuration complètement ouverte
    r : float
        junction thinness, = rayon du cercle inscrit / côté d'un triangle
    a : float
        longueur du côté bas de la cellule
    b : float
        longueur des côtés des carrés constitutifs
    name : str


    Returns
    -------
    Instance of the Gmsh2DRVE class.

    Si a est imposée :
    La cellule est de taille fixe,
    par contre la longueur des côtés des carrés dépend de l'angle d'ouverture de la microstructure.
    Si b est imposé :
    C'est l'inverse.
    Carrés de dimensions fixes, dimensions de la cellules dépendent de l'ouverture.
    """

    logger.info("Start defining the geometry")
    name = name if name else "rot_square"

    if (not a) and (not b):
        raise ValueError("a or b (exclusive OR) must be imposed")
    elif a and b:
        raise ValueError("a and b cannot be imposed simultaneously")
    elif b:
        # si on choisit la taille des carrés b
        a = rotating_squares_square_2_cell(theta, b)
    elif a:
        b = rotating_squares_cell_2_square(theta, a)

    gen_vect = np.array(((a, 0.0), (0.0, a)))
    nb_cells, offset = np.asarray(nb_cells), np.asarray(offset)

    a0 = np.array((a, 0.0, 0.0))
    a1 = np.array((0.0, a, 0.0))

    s, c = np.sin(theta), np.cos(theta)

    vertices_base_ll = [
        [0, -b * c],
        [b * s, 0],
        [0, b * c],
        [-b * s, 0],
    ]
    translat_h = [
        (0.0, a / 2, 0.0),
        (a, a / 2, 0.0),
        (a / 2, 0.0, 0.0),
        (a / 2, a, 0.0),
    ]
    rot_1 = np.pi / 2

    translat_v = [(a / 2, a / 2, 0.0), (0.0, a, 0.0), (a, 0.0, 0.0),
                  (a, a, 0.0)]
    # translat_v2 #
    z_axis = [0, 0, 1]
    # Definition of the LineLoops
    vertices_base_ll = [geo.Point(c) for c in vertices_base_ll]
    ll_base_vert = geo.LineLoop(vertices_base_ll, explicit=False)
    ll_base_horiz = geo.rotation(ll_base_vert, rot_1, z_axis)
    pattern_ll = [ll_base_vert]
    pattern_ll += [geo.translation(ll_base_vert, t) for t in translat_v]
    pattern_ll += [geo.translation(ll_base_horiz, t) for t in translat_h]
    pattern_ll = geo.remove_duplicates(pattern_ll)
    logger.info("Removing duplicate pattern line-loops: Done")
    logger.info(f"Number of pattern line-loops: {len(pattern_ll)}")
    for ll in pattern_ll:
        ll.round_corner_incircle(r)
    logger.info("Rounding all corners of pattern line-loops: Done")

    fine_pts = [pt for ll in pattern_ll for pt in ll.vertices]
    fine_pts = geo.remove_duplicates(fine_pts)

    return Gmsh2DRVE(pattern_ll, gen_vect, nb_cells, offset, fine_pts, False,
                     name)
예제 #7
0
def auxetic_square_RVE(L,
                       a,
                       t,
                       nb_cells=(1, 1),
                       offset=(0.0, 0.0),
                       soft_mat=False,
                       name=""):
    """
    Create an instance of Gmsh2DRVE that represents a RVE of
    the auxetic square microstructure.

    The generic operations will be performed with the Gmsh2DRVE methods.

    Parameters
    ----------
    L : float
        Length of the sides of the square cell.
    a : float
        Length of the slits beetween squares.
    t : float
        Width of the slits beetween squares.
    nb_cells : tuple or 1D array
        nb of cells in each direction of repetition
    offset : tuple or 1D array
        Relative position inside a cell of the point that
        will coincide with the origin of the global domain.

    Returns
    -------
    Instance of the Gmsh2DRVE class.
    """

    name = name if name else "aux_square"
    model.add(name)
    # geo.reset()

    offset = np.asarray(offset)
    nb_cells = np.asarray(nb_cells)

    logger.info("Start defining the auxetic_square geometry")
    gen_vect = np.array(((L, 0.0), (0.0, L)))
    b = (L - a) / 2.0
    e1 = np.array((L, 0.0, 0.0))
    e2 = np.array((0.0, L, 0.0))
    C = geo.Point(1 / 2.0 * (e1 + e2))
    M = geo.Point(1 / 4.0 * (e1 + e2))

    e3 = np.array((0.0, 0.0, 1.0))

    center_pts = [[(b, 0.0), (a + b, 0.0)], [(0.0, -a / 2.0), (0.0, a / 2.0)]]
    center_pts = [[geo.Point(np.array(coord)) for coord in gp]
                  for gp in center_pts]
    center_lines = [geo.Line(*pts) for pts in center_pts]
    center_lines += [geo.point_reflection(ln, M) for ln in center_lines]
    center_lines += [geo.plane_reflection(ln, C, e1) for ln in center_lines]
    center_lines += [geo.plane_reflection(ln, C, e2) for ln in center_lines]
    center_lines = geo.remove_duplicates(center_lines)

    for ln in center_lines:
        ln.ortho_dir = np.cross(e3, ln.direction())
    pattern_ll = list()
    for ln in center_lines:
        vertices = [
            geo.translation(ln.def_pts[0], t / 2 * ln.ortho_dir),
            geo.translation(ln.def_pts[1], t / 2 * ln.ortho_dir),
            geo.translation(ln.def_pts[1], -t / 2 * ln.ortho_dir),
            geo.translation(ln.def_pts[0], -t / 2 * ln.ortho_dir),
        ]
        pattern_ll.append(geo.LineLoop(vertices))
    tmp_nb_bef = len(pattern_ll)
    pattern_ll = geo.remove_duplicates(pattern_ll)

    logger.debug(
        f"Number of line-loops removed from pattern-ll : {tmp_nb_bef - len(pattern_ll)}."
    )
    logger.debug(
        f"Final number of pattern line-loops for auxetic square : {len(pattern_ll)}"
    )

    for ll in pattern_ll:
        ll.round_corner_explicit(t / 2)
        filter_sides = list()
        # * Pour ne pas essayer d'ajouter au model gmsh des lignes de longueur nulle.
        # * (Error : could not create line)
        for crv in ll.sides:
            if not crv.def_pts[0] == crv.def_pts[-1]:
                filter_sides.append(crv)
        ll.sides = filter_sides

    fine_pts = geo.remove_duplicates(
        flatten([ln.def_pts for ln in center_lines]))

    return Gmsh2DRVE(pattern_ll, gen_vect, nb_cells, offset, fine_pts,
                     soft_mat, name)
예제 #8
0
def pantograph_E11only_RVE(
        a,
        thickness,
        fillet_r=0.0,
        nb_cells=(1, 1),
        offset=(0.0, 0.0),
        soft_mat=False,
        name="",
):
    """
    Generate a RVE object for the simplified pantograph microstructure.
    Only one floppy mode : E11
    Junctions are obtained by creating offset curves from the microstructure contour.
    + fillets -> avoid stress concentration

    Parameters
    ----------
    a: floats
        main dimension of the microstruture
    thickness : float
        distance of translation prescribed for the vertices of the contour
    fillet_r : float
        radius of the fillets for the contour
    nb_cells : tuple or 1D array
        nb of cells in each direction of repetition
    offset : tuple or 1D array
        Relative position inside a cell of the point that will coincide with the origin of the global domain

    Returns
    -------
    Instance of the Gmsh2DRVE class.
    """
    name = name if name else "pantograph"
    offset = np.asarray(offset)
    nb_cells = np.asarray(nb_cells)
    logger.info("Start defining the pantograph geometry")
    Lx = 4 * a
    Ly = 4 * a + 2 * thickness
    cell_vect = np.array(((Lx, 0.0), (0.0, Ly)))
    e1 = np.array((a, 0.0, 0.0))
    e2 = np.array((0.0, a, 0.0))
    pt_L = 2 * (e1 + e2)

    square = [e1, e2, -e1, -e2]
    square = [p + pt_L for p in square]
    square = [geo.Point(p) for p in square]

    rhombus_v = [np.array((0.0, 0.0)), e1 + 2 * e2, 4 * e2, -e1 + 2 * e2]
    rhombus_v = [geo.Point(p) for p in rhombus_v]

    cut_shape_h = [
        np.array((0.0, 0.0)),
        0.25 * (-2 * e1 + e2),
        0.25 * (-4 * e1 + e2),
        0.25 * (-4 * e1 - e2),
        4 * e1 + 0.25 * (4 * e1 - e2),
        4 * e1 + 0.25 * (4 * e1 + e2),
        4 * e1 + 0.25 * (2 * e1 + e2),
        4 * e1,
        e2 + 2 * e1,
    ]
    cut_shape_h = [geo.Point(p) for p in cut_shape_h]

    square = geo.LineLoop(square, explicit=False)
    rhombus_v = geo.LineLoop(rhombus_v, explicit=False)
    cut_shape_h = geo.LineLoop(cut_shape_h, explicit=False)
    pattern = [square, rhombus_v, cut_shape_h]
    sym_rhombus = [
        geo.plane_reflection(rhombus_v, pt_L, e1),
        geo.plane_reflection(cut_shape_h, pt_L, e2),
    ]
    for ll in sym_rhombus:
        ll.reverse()
    pattern += sym_rhombus
    pattern = geo.remove_duplicates(pattern)
    translated_pattern = list()
    for ll in pattern:
        translated_pattern.append(
            geo.translation(ll, np.array((0.0, thickness, 0.0))))
    logger.info("Done removing of the line-loops duplicates")
    pattern = translated_pattern
    constr_pts = [
        copy.deepcopy(pt) for ll in pattern for pt in iter((ll.vertices))
    ]
    for ll in pattern:
        ll.offset(thickness)

    if fillet_r:
        for ll in pattern:
            ll.round_corner_explicit(fillet_r)
    logger.info("Done rounding all corners of pattern line-loops")
    fine_pts = geo.remove_duplicates(constr_pts)
    return Gmsh2DRVE(pattern, cell_vect, nb_cells, offset, fine_pts, soft_mat,
                     name)
예제 #9
0
def beam_pantograph_RVE(a,
                        b,
                        w,
                        junction_r=0.0,
                        nb_cells=(1, 1),
                        offset=(0.0, 0.0),
                        soft_mat=False,
                        name=""):
    """
    Create an instance of Gmsh2DRVE that represents a RVE of the beam pantograph microstructure.
    The geometry that is specific to this microstructure is defined in this staticmethod. Then, the generic operations will be performed with the Gmsh2DRVE methods.

    Parameters
    ----------
    a, b : floats
        main lengths of the microstruture
    w : float
        width of the constitutive beams
    junction_r : float, optional
        Radius of the corners/fillets that are created between concurrent borders of beams.
        The default is 0., which implies that the angles will not be rounded.
    nb_cells : tuple or 1D array, optional
        nb of cells in each direction of repetition (the default is (1, 1).)
    offset : tuple, optional
        If (0., 0.) or False : No shift of the microstructure.
        Else : The microstructure is shift with respect to the macroscopic domain.
        offset is the relative position inside a cell of the point that will coincide with the origin of the global domain.
    soft_mat : bool, optional
        If True : the remaining surface inside the RVE is associated with a second material domain and a mesh is genereted to represent it.
        Else, this space remains empty.
    name : str, optional
        The name of the RVE. It is use for the gmsh model and the mesh files.
        If name is '' (default) or False, the name of the RVE is 'beam_pantograph'.

    Returns
    -------
    Instance of the Gmsh2DRVE class.
    """

    name = name if name else "beam_pantograph"
    offset = np.asarray(offset)
    nb_cells = np.asarray(nb_cells)

    logger.info("Start defining the beam pantograph geometry")
    Lx = 4 * a
    Ly = 6 * a + 2 * b
    cell_vect = np.array(((Lx, 0.0), (0.0, Ly)))
    e1 = np.array((a, 0.0, 0.0))
    e2 = np.array((0.0, a, 0.0))
    b_ = b / a * e2
    E1 = geo.Point(e1)
    E2 = geo.Point(e2)
    E1m = geo.Point(-1 * e1)
    E2m = geo.Point(-1 * e2)
    L = geo.Point(2 * (e1 + e2))
    Lm = geo.Point(2 * (e1 - e2))
    M = geo.Point(e1 + 1.5 * e2 + b_ / 2)
    I = geo.Point(2 * (e1 + 1.5 * e2 + b_ / 2))
    contours = [
        [E1, E2, E1m, E2m],
        [E1, Lm, geo.Point(3 * e1), L],
        [E1, L, E2],
        [E2, L, geo.translation(L, b_),
         geo.translation(E2, b_)],
    ]
    pattern_ll = [
        geo.LineLoop(pt_list, explicit=False) for pt_list in contours
    ]
    pattern_ll += [geo.point_reflection(ll, M) for ll in pattern_ll]
    sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()
    pattern_ll += sym_ll
    sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()
    pattern_ll += sym_ll
    pattern_ll = geo.remove_duplicates(pattern_ll)
    constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in ll.vertices]
    for ll in pattern_ll:
        ll.offset(w)
    if junction_r:
        for ll in pattern_ll:
            ll.round_corner_incircle(junction_r)

    fine_pts = geo.remove_duplicates(constr_pts)
    return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts,
                     soft_mat, name)
예제 #10
0
def pantograph_RVE(a,
                   b,
                   k,
                   junction_r,
                   nb_cells=(1, 1),
                   offset=(0.0, 0.0),
                   soft_mat=False,
                   name=""):
    """
    Create an instance of Gmsh2DRVE that represents a RVE of the pantograph microstructure.
    The geometry that is specific to this microstructure is defined in this staticmethod. Then, the generic operations will be performed with the Gmsh2DRVE methods.

    Parameters
    ----------
    a,b and k : floats
        main lengths of the microstruture
    junction_r : float
        radius of the junctions inside the pantograph microstructure
    nb_cells : tuple or 1D array
        nb of cells in each direction of repetition
    offset : tuple or 1D array
        Relative position inside a cell of the point that will coincide with the origin of the global domain

    Returns
    -------
    Instance of the Gmsh2DRVE class.
    """
    name = name if name else "pantograph"

    offset = np.asarray(offset)
    nb_cells = np.asarray(nb_cells)

    logger.info("Start defining the pantograph geometry")
    Lx = 4 * a
    Ly = 6 * a + 2 * b
    cell_vect = np.array(((Lx, 0.0), (0.0, Ly)))

    e1 = np.array((a, 0.0, 0.0))
    e2 = np.array((0.0, a, 0.0))
    p = np.array((k, 0.0, 0.0))
    b_ = b / a * e2
    E1 = geo.Point(e1)
    E2 = geo.Point(e2)
    E1m = geo.Point(-1 * e1)
    E2m = geo.Point(-1 * e2)
    L = geo.Point(2 * (e1 + e2))
    Lm = geo.Point(2 * (e1 - e2))
    M = geo.Point(e1 + 1.5 * e2 + b_ / 2)
    I = geo.Point(2 * (e1 + 1.5 * e2 + b_ / 2))

    contours = list()
    contours.append([E1, E2, E1m, E2m])
    contours.append([E1, Lm, geo.Point(3 * e1), L])
    contours.append([
        E2,
        L,
        geo.translation(L, 0.5 * b_ - p),
        geo.translation(L, b_),
        geo.translation(E2, b_),
        geo.translation(E2, 0.5 * b_ + p),
    ])
    pattern_ll = [
        geo.LineLoop(pt_list, explicit=False) for pt_list in contours
    ]
    pattern_ll += [geo.point_reflection(ll, M) for ll in pattern_ll]
    sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()
    pattern_ll += sym_ll
    sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()

    pattern_ll += sym_ll
    pattern_ll = geo.remove_duplicates(pattern_ll)
    logger.info("Done removing of the line-loops duplicates")
    for ll in pattern_ll:
        ll.round_corner_incircle(junction_r)
    logger.info("Done rounding all corners of pattern line-loops")

    constr_pts = [pt for ll in pattern_ll for pt in ll.vertices]
    fine_pts = [pt for pt in constr_pts if _filter_free_rhombus_vertex(pt, k)]
    fine_pts = geo.remove_duplicates(fine_pts)
    return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts,
                     soft_mat, name)
예제 #11
0
def pantograph_offset_RVE(
        a,
        b,
        k,
        thickness,
        fillet_r=0.0,
        nb_cells=(1, 1),
        offset=(0.0, 0.0),
        soft_mat=False,
        name="",
):
    """
    Generate a RVE object for the pantograph microstructure.
    Junctions are obtained by creating offset curves from the microstructure contour.

    Parameters
    ----------
    a,b and k : floats
        main lengths of the microstruture
    thickness : float
        distance of translation prescribed for the vertices of the contour
    fillet_r : float
        radius of the fillets for the contour
    nb_cells : tuple or 1D array
        nb of cells in each direction of repetition
    offset : tuple or 1D array
        Relative position inside a cell of the point that will coincide with the origin of the global domain

    Returns
    -------
    Instance of the Gmsh2DRVE class.
    """

    name = name if name else "pantograph"

    offset = np.asarray(offset)
    nb_cells = np.asarray(nb_cells)

    logger.info("Start defining the pantograph geometry")

    Lx = 4 * a
    Ly = 6 * a + 2 * b
    cell_vect = np.array(((Lx, 0.0), (0.0, Ly)))

    e1 = np.array((a, 0.0, 0.0))
    e2 = np.array((0.0, a, 0.0))
    p = np.array((k, 0.0, 0.0))
    b_ = b / a * e2
    E1 = geo.Point(e1)
    E2 = geo.Point(e2)
    E1m = geo.Point(-1 * e1)
    E2m = geo.Point(-1 * e2)
    L = geo.Point(2 * (e1 + e2))
    Lm = geo.Point(2 * (e1 - e2))
    M = geo.Point(e1 + 1.5 * e2 + b_ / 2)
    I = geo.Point(2 * (e1 + 1.5 * e2 + b_ / 2))
    contour_1 = [E1, E2, E1m, E2m]
    contour_2 = [E1, Lm, geo.Point(3 * e1), L]
    contour_3 = [
        E2,
        L,
        geo.translation(L, 0.5 * b_ - p),
        geo.translation(L, b_),
        geo.translation(E2, b_),
        geo.translation(E2, 0.5 * b_ + p),
    ]
    contours = [contour_1, contour_2, contour_3]

    pattern_ll = [
        geo.LineLoop(pt_list, explicit=False) for pt_list in contours
    ]
    pattern_ll += [geo.point_reflection(ll, M) for ll in pattern_ll]
    sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()
    pattern_ll += sym_ll
    sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
    for ll in sym_ll:
        ll.reverse()
    pattern_ll += sym_ll
    pattern_ll = geo.remove_duplicates(pattern_ll)
    logger.info("Done removing of the line-loops duplicates")

    constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in ll.vertices]

    for ll in pattern_ll:
        ll.offset(thickness)

    if fillet_r:
        for ll in pattern_ll:
            ll.round_corner_explicit(fillet_r)
        logger.info("Done rounding all corners of pattern line-loops")
    fine_pts = [pt for pt in constr_pts if _filter_free_rhombus_vertex(pt, k)]
    fine_pts = geo.remove_duplicates(fine_pts)
    return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts,
                     soft_mat, name)