Commit 869d8386 authored by Baptiste Durand's avatar Baptiste Durand

Merge branch 'new_pantograph_microstructures'

parents 3061c5f3 d7edbd53
...@@ -120,7 +120,7 @@ class LineLoop(object): ...@@ -120,7 +120,7 @@ class LineLoop(object):
elmt.def_pts.reverse() elmt.def_pts.reverse()
self.vertices.reverse() self.vertices.reverse()
def offset(self, t): def offset(self, t, method="vertex"):
""" Opération d'offset appliquée sur tout les sommets de la LineLoop. """ Opération d'offset appliquée sur tout les sommets de la LineLoop.
Cette opération doit donc être faite assez tôt, Cette opération doit donc être faite assez tôt,
...@@ -132,7 +132,7 @@ class LineLoop(object): ...@@ -132,7 +132,7 @@ class LineLoop(object):
self.info_offset = True self.info_offset = True
for i in range(len(self.vertices)): for i in range(len(self.vertices)):
new_vrtces[i - 1] = offset( new_vrtces[i - 1] = offset(
self.vertices[i - 1], self.vertices[i - 2], self.vertices[i], t self.vertices[i - 1], self.vertices[i - 2], self.vertices[i], t, method=method
) )
self.offset_dpcmt = [ self.offset_dpcmt = [
np.linalg.norm(new.coord - prev.coord) np.linalg.norm(new.coord - prev.coord)
......
...@@ -167,17 +167,45 @@ def round_corner(inp_pt, pt_amt, pt_avl, r, junction_raduis=False, plot=False): ...@@ -167,17 +167,45 @@ def round_corner(inp_pt, pt_amt, pt_avl, r, junction_raduis=False, plot=False):
return geoList return geoList
def offset(pt, pt_dir1, pt_dir2, t): def offset(pt, pt_dir1, pt_dir2, distance, method="vertex"):
"""[summary]
Parameters
----------
pt : Point
[description]
pt_dir1 : Point
[description]
pt_dir2 : Point
[description]
distance : float
translation distance for vertices or edges depending on the method selected.
method : str, optional
- "vertex" : new vertices are at a constant distance from original vertices.
- "edge" : new edges are at a constant distance from original edges.
Default value is "vertex"
Returns
-------
Point
New instance of Point with updated coordinates.
"""
# TODOC # TODOC
v1 = pt_dir1.coord - pt.coord v1 = pt_dir1.coord - pt.coord
v2 = pt_dir2.coord - pt.coord v2 = pt_dir2.coord - pt.coord
alpha = angle_between(v1, v2, orient=False)
v_biss = bisector(v1, v2) v_biss = bisector(v1, v2)
if alpha != np.pi: if method == "edge":
dpcmt = -t / abs(np.sin(alpha / 2.0)) alpha = angle_between(v1, v2, orient=False)
if alpha != np.pi:
dpcmt = -distance / abs(np.sin(alpha / 2.0))
else:
dpcmt = -distance
elif method == "vertex":
dpcmt = -distance #! Pourquoi il y a un signe - ????
else: else:
dpcmt = -t raise TypeError("method must be 'vertex' or 'edge'.")
new_coord = pt.coord + dpcmt * v_biss new_coord = pt.coord + dpcmt * v_biss
#TODO : remplacer par translation
return Point(new_coord) return Point(new_coord)
......
...@@ -421,6 +421,9 @@ class Gmsh2DPart(object): ...@@ -421,6 +421,9 @@ class Gmsh2DPart(object):
self.mesh_abs_path = mesh_path.resolve() self.mesh_abs_path = mesh_path.resolve()
from .pantograph import pantograph_RVE, pantograph_offset_RVE, beam_pantograph_RVE
# from .other_2d_microstructures import auxetic_square_RVE
def Gmsh2DPartFromRVE(cell: Gmsh2DRVE, nb_cells, part_name=None): def Gmsh2DPartFromRVE(cell: Gmsh2DRVE, nb_cells, part_name=None):
"""[summary] """[summary]
...@@ -548,4 +551,15 @@ def Gmsh2DPartFromRVE(cell: Gmsh2DRVE, nb_cells, part_name=None): ...@@ -548,4 +551,15 @@ def Gmsh2DPartFromRVE(cell: Gmsh2DRVE, nb_cells, part_name=None):
gmsh.write(str(part_path)) gmsh.write(str(part_path))
return Gmsh2DPart(part_vect, nb_cells, phy_surfaces, part_path) return Gmsh2DPart(part_vect, nb_cells, phy_surfaces, part_path)
from . import pantograph from . import pantograph
\ No newline at end of file
__all__ = [
"pantograph_RVE",
"pantograph_offset_RVE",
"beam_pantograph_RVE",
"auxetic_square_RVE",
"Gmsh2DRVE",
"Gmsh2DPart",
"Gmsh2DPartFromRVE",
]
# coding: utf-8
"""
Created on 17/01/2019
@author: Baptiste Durand, baptiste.durand@enpc.fr
"""
import gmsh
import numpy as np
from more_itertools import flatten
import ho_homog.geometry as geo
from . import Gmsh2DRVE, logger
# nice shortcuts
model = gmsh.model
factory = model.occ
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 geometry that is specific to this microstructure is defined in this staticmethod. Then, 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))
I = 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, I, e1) for ln in center_lines]
center_lines += [geo.plane_reflection(ln, I, 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
)
# coding: utf-8
""" """
Created on 17/01/2019 Created on 17/01/2019
@author: Baptiste Durand, baptiste.durand@enpc.fr @author: Baptiste Durand, baptiste.durand@enpc.fr
""" """
import copy import copy
import gmsh import gmsh
import numpy as np import numpy as np
import ho_homog.geometry as geo import ho_homog.geometry as geo
from . import Gmsh2DRVE, logger
# ? doc about imports : https://realpython.com/absolute-vs-relative-python-imports/#syntax-of-import-statements #noqa from . import Gmsh2DRVE, logger
# nice shortcuts
model = gmsh.model model = gmsh.model
factory = model.occ factory = model.occ
...@@ -77,7 +80,6 @@ def pantograph_RVE( ...@@ -77,7 +80,6 @@ def pantograph_RVE(
sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
ll.reverse() ll.reverse()
pattern_ll += sym_ll pattern_ll += sym_ll
sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
...@@ -90,26 +92,18 @@ def pantograph_RVE( ...@@ -90,26 +92,18 @@ def pantograph_RVE(
ll.round_corner_incircle(junction_r) ll.round_corner_incircle(junction_r)
logger.info("Done rounding all corners of pattern line-loops") logger.info("Done rounding all corners of pattern line-loops")
constr_pts = [pt for ll in pattern_ll for pt in iter((ll.vertices))] constr_pts = [pt for ll in pattern_ll for pt in ll.vertices]
fine_pts = [ fine_pts = [
pt pt
for pt in constr_pts for pt in constr_pts
if pt.coord[0] % 1 < p[0] / 2.0 or pt.coord[0] % 1 > 1.0 - p[0] / 2.0 if (pt.coord[0] % 1 < p[0] / 2.0 or pt.coord[0] % 1 > 1.0 - p[0] / 2.0)
] ]
fine_pts = geo.remove_duplicates(fine_pts) fine_pts = geo.remove_duplicates(fine_pts)
return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts, soft_mat, name) return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts, soft_mat, name)
def pantograph_offset_RVE( def pantograph_offset_RVE(
a, a, b, k, thickness, fillet_r=0., nb_cells=(1, 1), offset=(0.0, 0.0), soft_mat=False, name=""
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. Generate a RVE object for the pantograph microstructure.
...@@ -132,13 +126,18 @@ def pantograph_offset_RVE( ...@@ -132,13 +126,18 @@ def pantograph_offset_RVE(
------- -------
Instance of the Gmsh2DRVE class. Instance of the Gmsh2DRVE class.
""" """
name = name if name else "pantograph" name = name if name else "pantograph"
offset = np.asarray(offset) offset = np.asarray(offset)
nb_cells = np.asarray(nb_cells) nb_cells = np.asarray(nb_cells)
logger.info("Start defining the pantograph geometry") logger.info("Start defining the pantograph geometry")
Lx = 4 * a Lx = 4 * a
Ly = 6 * a + 2 * b Ly = 6 * a + 2 * b
cell_vect = np.array(((Lx, 0.0), (0.0, Ly))) cell_vect = np.array(((Lx, 0.0), (0.0, Ly)))
e1 = np.array((a, 0.0, 0.0)) e1 = np.array((a, 0.0, 0.0))
e2 = np.array((0.0, a, 0.0)) e2 = np.array((0.0, a, 0.0))
p = np.array((k, 0.0, 0.0)) p = np.array((k, 0.0, 0.0))
...@@ -169,28 +168,28 @@ def pantograph_offset_RVE( ...@@ -169,28 +168,28 @@ def pantograph_offset_RVE(
sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
ll.reverse() ll.reverse()
pattern_ll += sym_ll pattern_ll += sym_ll
sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
ll.reverse() ll.reverse()
pattern_ll += sym_ll pattern_ll += sym_ll
pattern_ll = geo.remove_duplicates(pattern_ll) pattern_ll = geo.remove_duplicates(pattern_ll)
logger.info("Done removing of the line-loops duplicates") logger.info("Done removing of the line-loops duplicates")
constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in iter((ll.vertices))]
constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in ll.vertices]
for ll in pattern_ll: for ll in pattern_ll:
ll.offset(thickness) ll.offset(thickness)
if fillet_r: if fillet_r:
for ll in pattern_ll: for ll in pattern_ll:
ll.round_corner_explicit(fillet_r) ll.round_corner_explicit(fillet_r)
logger.info("Done rounding all corners of pattern line-loops") logger.info("Done rounding all corners of pattern line-loops")
fine_pts = [ fine_pts = [
pt pt
for pt in constr_pts for pt in constr_pts
if pt.coord[0] % 1 < p[0] / 2.0 or pt.coord[0] % 1 > 1.0 - p[0] / 2.0 if (pt.coord[0] % 1 < p[0] / 2.0 or pt.coord[0] % 1 > 1.0 - p[0] / 2.0)
] ]
fine_pts = geo.remove_duplicates(fine_pts) fine_pts = geo.remove_duplicates(fine_pts)
return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts, soft_mat, name) return Gmsh2DRVE(pattern_ll, cell_vect, nb_cells, offset, fine_pts, soft_mat, name)
...@@ -229,9 +228,11 @@ def beam_pantograph_RVE( ...@@ -229,9 +228,11 @@ def beam_pantograph_RVE(
------- -------
Instance of the Gmsh2DRVE class. Instance of the Gmsh2DRVE class.
""" """
name = name if name else "beam_pantograph" name = name if name else "beam_pantograph"
offset = np.asarray(offset) offset = np.asarray(offset)
nb_cells = np.asarray(nb_cells) nb_cells = np.asarray(nb_cells)
logger.info("Start defining the beam pantograph geometry") logger.info("Start defining the beam pantograph geometry")
Lx = 4 * a Lx = 4 * a
Ly = 6 * a + 2 * b Ly = 6 * a + 2 * b
...@@ -258,18 +259,15 @@ def beam_pantograph_RVE( ...@@ -258,18 +259,15 @@ def beam_pantograph_RVE(
sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e1) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
ll.reverse() ll.reverse()
pattern_ll += sym_ll pattern_ll += sym_ll
sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll] sym_ll = [geo.plane_reflection(ll, I, e2) for ll in pattern_ll]
for ll in sym_ll: for ll in sym_ll:
ll.reverse() ll.reverse()
pattern_ll += sym_ll pattern_ll += sym_ll
pattern_ll = geo.remove_duplicates(pattern_ll) pattern_ll = geo.remove_duplicates(pattern_ll)
constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in iter((ll.vertices))] constr_pts = [copy.deepcopy(pt) for ll in pattern_ll for pt in ll.vertices]
for ll in pattern_ll: for ll in pattern_ll:
ll.offset(w) ll.offset(w)
if junction_r: if junction_r:
for ll in pattern_ll: for ll in pattern_ll:
ll.round_corner_incircle(junction_r) ll.round_corner_incircle(junction_r)
......
...@@ -5,7 +5,7 @@ Created on 12/06/2019 ...@@ -5,7 +5,7 @@ Created on 12/06/2019
""" """
from ho_homog import geometry as geo from ho_homog import geometry as geo
from ho_homog import mesh_generate_2D as mesh2D from ho_homog import mesh_generate as mesh2D
from ho_homog.toolbox_gmsh import msh_conversion from ho_homog.toolbox_gmsh import msh_conversion
import gmsh import gmsh
...@@ -32,3 +32,22 @@ def test_rve_2_part(): ...@@ -32,3 +32,22 @@ def test_rve_2_part():
panto_part = mesh2D.Gmsh2DPartFromRVE(panto_rve, (2, 3)) panto_part = mesh2D.Gmsh2DPartFromRVE(panto_rve, (2, 3))
msh_conversion(panto_rve.mesh_abs_path, ".xdmf") msh_conversion(panto_rve.mesh_abs_path, ".xdmf")
msh_conversion(panto_part.mesh_abs_path, ".xdmf") msh_conversion(panto_part.mesh_abs_path, ".xdmf")
def test_pantograph_offset():
geo.set_gmsh_option('Mesh.MshFileVersion', 4.1)
a = 1
b, k = a, a/3
t = 0.02
panto_test = mesh2D.pantograph_offset_RVE(
a, b, k, t, nb_cells=(1, 1), soft_mat=False, name='panto_rve_1x1')
lc_ratio = 1/6
lc_min_max = (lc_ratio*t*a, lc_ratio*a)
panto_test.main_mesh_refinement((2*t*a, a), lc_min_max, False)
panto_test.mesh_generate()
gmsh.model.mesh.renumberNodes()
gmsh.model.mesh.renumberElements()
gmsh.write("panto_rve_offset.msh")
test_pantograph_offset()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment