def test_Threshold(): """ Test of the AttractorField and ThresholdField subclass of the Field base class. #* Test OK """ name = "test_Threshold" model.add(name) rect_vtcs = [geo.Point(np.array(c)) for c in [(-4, -2), (4, -2), (4, 2), (-4, 2)]] mid_N = geo.Point(np.array((0, 2))) mid_S = geo.Point(np.array((0, -2))) attrac_NW = geo.Point(np.array((-2, 1))) attrac_mid = geo.Line(mid_N, mid_S) rect_ll = geo.LineLoop(rect_vtcs, False) rect_s = geo.PlaneSurface(rect_ll) rect_s.add_gmsh() f = msh.AttractorField( points=[attrac_NW], curves=[attrac_mid], nb_pts_discretization=10 ) g = msh.ThresholdField(f, 0.2, 1, 0.03, 0.2, True) msh.set_background_mesh(g) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def test_Min(): """ Test of Min subclass of the Field base class and of the use of set_background_mesh function with a list of fields as input. #* Test OK """ name = "test_Min" model.add(name) rect_vtcs = [geo.Point(np.array(c)) for c in [(-4, -2), (4, -2), (4, 2), (-4, 2)]] rect_ll = geo.LineLoop(rect_vtcs, False) rect_s = geo.PlaneSurface(rect_ll) rect_s.add_gmsh() h1 = msh.MathEvalField("0.1") h2 = msh.MathEvalField("(x*x)+0.02") h1.add_gmsh() h2.add_gmsh() msh.set_background_mesh([h1, h2]) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def test_fctn_restrict(): """ Test of the function that has been designed to quickly specify a refinement constraint with a restriction to a given surface. #* Test OK """ name = "test_Restrict_with_fctn" model.add(name) vtcs_1 = [geo.Point(np.array(c)) for c in [(-1, -1), (1, -1), (1, 1), (-1, 1)]] vtcs_2 = [geo.Point(np.array(c)) for c in [(0, 0), (2, 0), (2, 2), (0, 2)]] ll_1 = geo.LineLoop(vtcs_1, explicit=False) ll_2 = geo.LineLoop(vtcs_2, explicit=False) surf_1 = geo.PlaneSurface(ll_1) surf_2 = geo.PlaneSurface(ll_2) surf_1.add_gmsh() surf_2.add_gmsh() f = msh.MathEvalField("0.1") g = msh.MathEvalField("(x-0.25)*(x-0.25)+0.02") h = msh.MathEvalField("(y-0.25)*(y-0.25)+0.02") gr = msh.RestrictField(g, surfaces=[surf_1], curves=surf_1.ext_contour.sides) hr = msh.RestrictField( h, surfaces=[surf_2], curves=surf_2.ext_contour.sides + surf_1.ext_contour.sides ) msh.set_background_mesh([f, gr, hr]) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def test_refine_function(): """ Test of the function that has been designed to quickly specify a refinement constraint. #* Test OK """ name = "test_refine_function" model.add(name) rect_vtcs = [geo.Point(np.array(c)) for c in [(-4, -2), (4, -2), (4, 2), (-4, 2)]] mid_N = geo.Point(np.array((0, 2))) mid_S = geo.Point(np.array((0, -2))) attrac_NW = geo.Point(np.array((-2, 1))) attrac_mid = geo.Line(mid_N, mid_S) rect_ll = geo.LineLoop(rect_vtcs, False) rect_s = geo.PlaneSurface(rect_ll) rect_s.add_gmsh() f = msh.set_mesh_refinement( [0.2, 1], [0.03, 0.2], attractors={"points": [attrac_NW], "curves": [attrac_mid]}, sigmoid_interpol=True, ) msh.set_background_mesh(f) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def test_Restrict(): """ Test of the Restrict subclass of the Field base class. #* Test OK! """ name = "test_Restrict" model.add(name) vtcs_1 = [geo.Point(np.array(c)) for c in [(-1, -1), (1, -1), (1, 1), (-1, 1)]] vtcs_2 = [geo.Point(np.array(c)) for c in [(0, 0), (2, 0), (2, 2), (0, 2)]] ll_1 = geo.LineLoop(vtcs_1, explicit=False) ll_2 = geo.LineLoop(vtcs_2, explicit=False) surf_1 = geo.PlaneSurface(ll_1) surf_2 = geo.PlaneSurface(ll_2) surf_1.add_gmsh() surf_2.add_gmsh() f = msh.MathEvalField("0.1") g = msh.MathEvalField("(x-0.25)*(x-0.25)+0.02") h = msh.RestrictField(g, surfaces=[surf_1]) msh.set_background_mesh([f, h]) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def test_MathEval(): """ Test of MathEval subclass of the Field base class. #* Test OK """ name = "test_MathEval" model.add(name) rect_vtcs = [geo.Point(np.array(c)) for c in [(-4, -2), (4, -2), (4, 2), (-4, 2)]] rect_ll = geo.LineLoop(rect_vtcs, False) rect_s = geo.PlaneSurface(rect_ll) rect_s.add_gmsh() f = msh.MathEvalField("(Cos(3.14*x) * Sin(3.14*y)+1)*0.1+0.005") f.add_gmsh() # Optional msh.set_background_mesh(f) factory.synchronize() model.mesh.generate(2) gmsh.write("%s.msh" % name) os.system("gmsh %s.msh &" % name)
def mesh_generate(self, mesh_field=None, directory: Path = None): """Generate a 2D mesh of the model which represent a RVE. Parameters ---------- mesh_field : mesh_tools.Field, optional The characteristic length of the elements can be explicitly prescribe by means of this field. The default is None. In this case, the fields that have been created with the soft_mesh_refinement and main_mesh_refinement methods are used. directory : pathlib.Path, optional Indicate in which directory the .msh file must be created. If None (default), the .msh file is written in the current working directory. Ex: Path('/media/sf_VM_share/homog') """ model.setCurrent(self.name) if not mesh_field: self.background_field = msh.set_background_mesh(self.mesh_fields) else: self.background_field = msh.set_background_mesh(mesh_field) data = model.getPhysicalGroups() logger.debug( f"Physical groups in model just before generating mesh : {data}") geo.PhysicalGroup.set_group_mesh(True) model.mesh.generate(1) gmsh.model.mesh.removeDuplicateNodes() model.mesh.generate(2) gmsh.model.mesh.removeDuplicateNodes() geo.PhysicalGroup.set_group_visibility(False) if directory: mesh_path = directory if not directory.suffix else directory.with_suffix( "") if not mesh_path.exists(): mesh_path.mkdir(mode=0o777, parents=True) else: mesh_path = Path.cwd() mesh_path = mesh_path.joinpath(f"{self.name}.msh") gmsh.write(str(mesh_path)) self.mesh_abs_path = mesh_path
run(f"gmsh {str(geo_file)} &", shell=True, check=True) logger.info("Start defining a mesh refinement constraint") constr_pts = [pt for ll in pattern_ll for pt in ll.vertices] fine_pts = [ pt 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) ] fine_pts = geo.remove_duplicates(fine_pts) for pt in fine_pts: pt.add_gmsh() factory.synchronize() f = msh.set_mesh_refinement((r, a), (r / 4, a / 3), attractors={"points": fine_pts}, sigmoid_interpol=True) msh.set_background_mesh(f) logger.info("Mesh refinement constraint Done") logger.info("Start defining a periodicity constraint for the mesh") macro_bndry = macro_ll.sides rve_s.get_boundary(recursive=True) micro_bndry = [ geo.macro_line_fragments(rve_s.boundary, M_ln) for M_ln in macro_bndry ] dirct = [(M_ln.def_pts[-1].coord - M_ln.def_pts[0].coord) for M_ln in macro_bndry] logger.debug("value and type of dirct items : " + repr([(i, type(i)) for i in dirct])) for i, crvs in enumerate(micro_bndry): msh.order_curves(crvs, dirct[i % 2], orientation=True) logger.debug("length of micro_bndry list : " + str(len(micro_bndry)))
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()
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()