def test_2_materials(): """FenicsPart instance initialized with only one instance of Material in the materials dictionnary""" L_x, L_y = 1, 1 mesh = fe.RectangleMesh(fe.Point(-L_x, -L_y), fe.Point(L_x, L_y), 20, 20) dimensions = np.array(((2 * L_x, 0.0), (0.0, 2 * L_y))) subdomains = fe.MeshFunction("size_t", mesh, 2) class Right_part(fe.SubDomain): def inside(self, x, on_boundary): return x[0] >= 0 - fe.DOLFIN_EPS subdomain_right = Right_part() subdomains.set_all(0) subdomain_right.mark(subdomains, 1) E_1, E_2, nu = 1, 3, 0.3 materials = {0: mat.Material(1, 0.3, "cp"), 1: mat.Material(3, 0.3, "cp")} rect_part = part.FenicsPart(mesh, materials, subdomains, dimensions) elem_type = "CG" degree = 2 strain_fspace = fe.FunctionSpace( mesh, fe.VectorElement(elem_type, mesh.ufl_cell(), degree, dim=3), ) strain = fe.project(fe.Expression(("1.0+x[0]*x[0]", "0", "1.0"), degree=2), strain_fspace) stress = mat.sigma(rect_part.elasticity_tensor, strain) energy = fe.assemble(fe.inner(stress, strain) * fe.dx(rect_part.mesh)) energy_theo = 2 * ((E_1 + E_2) / (1 + nu) * (1 + 28 / (15 * (1 - nu)))) assert energy == approx(energy_theo, rel=1e-13)
def test_rve_from_gmsh2drve(): a = 1 b, k = a, a / 3 panto_test = mg.pantograph.pantograph_RVE(a, b, k, 0.1, nb_cells=(2, 3), soft_mat=False, name="panto_test") panto_test.main_mesh_refinement((0.1, 0.5), (0.03, 0.3), False) panto_test.mesh_generate() run(f"gmsh {panto_test.name}.msh &", shell=True, check=True) E1, nu1 = 1.0, 0.3 E2, nu2 = E1 / 100.0, nu1 E_nu_tuples = [(E1, nu1), (E2, nu2)] phy_subdomains = panto_test.phy_surf material_dict = dict() for coeff, subdo in zip(E_nu_tuples, phy_subdomains): material_dict[subdo.tag] = mat.Material(coeff[0], coeff[1], "cp") rve = part.Fenics2DRVE.rve_from_gmsh2drve(panto_test, material_dict) assert isinstance(rve, part.Fenics2DRVE) assert hasattr(rve, "mesh") assert hasattr(rve, "gen_vect") assert hasattr(rve, "C_per") assert hasattr(rve, "rve_area")
def test_mat_without_dictionnary(): """FenicsPart instance initialized with only one instance of Material""" L_x, L_y = 1, 1 mesh = fe.RectangleMesh(fe.Point(0.0, 0.0), fe.Point(L_x, L_y), 10, 10) dimensions = np.array(((L_x, 0.0), (0.0, L_y))) E, nu = 1, 0.3 material = mat.Material(E, nu, "cp") rect_part = part.FenicsPart( mesh, materials=material, subdomains=None, global_dimensions=dimensions, facet_regions=None, ) elem_type = "CG" degree = 2 strain_fspace = fe.FunctionSpace( mesh, fe.VectorElement(elem_type, mesh.ufl_cell(), degree, dim=3), ) strain = fe.project(fe.Expression(("1.0+x[0]*x[0]", "0", "1.0"), degree=2), strain_fspace) stress = mat.sigma(rect_part.elasticity_tensor, strain) energy = fe.assemble(fe.inner(stress, strain) * fe.dx(rect_part.mesh)) energy_theo = E / (1 + nu) * (1 + 28 / (15 * (1 - nu))) assert energy == approx(energy_theo, rel=1e-13)
def test_global_area_2D(): """FenicsPart method global_aera, for a 2D part""" L_x, L_y = 10.0, 4.0 mesh = fe.RectangleMesh(fe.Point(0.0, 0.0), fe.Point(L_x, L_y), 10, 10) material = {"0": mat.Material(1.0, 0.3, "cp")} dimensions = np.array(((L_x, 0.0), (0.0, L_y))) rect_part = part.FenicsPart( mesh, materials=material, subdomains=None, global_dimensions=dimensions, facet_regions=None, ) assert rect_part.global_area == approx(40.0, rel=1e-10)
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()
def _save_all_localization_fields(xdmf_path: Path, localization_dicts: list): """Sauvegarde de tous les champs de localisation dans un .xdmf localization_dicts : list de dictionnaires.""" with fe.XDMFFile(str(xdmf_path)) as fo: fo.parameters["functions_share_mesh"] = True for d in localization_dicts: for k, fields in d.items(): for f in fields: logger.debug(f"Saving field {f.name()}") fo.write(f, 0.0) return None E, nu = 1.0, 0.3 ref_homogeneous_material = materials.Material(E, nu, "cp") def test_homogeneous_rectangular_cell(): """Test élémentaire : Homogénéisation d'une cellule homogène rectangulaire.""" logger.debug("Start test_homogeneous_rectangular_cell") # Generation du maillage : cell_vect = np.array([[1.0, 0.0], [0.0, 2.0]]) # colonnes = vecteurs periodicité name = "rectangular_homogeneous_cell" mesh_path = _mesh_homogeneous_cell(cell_vect, TEMP_DIR / f"{name}.msh") # Definition du RVE : rve = part.Fenics2DRVE.rve_from_file(mesh_path, cell_vect, ref_homogeneous_material) hom_model = homog2d.Fenics2DHomogenization(rve, element=("CG", 2))
gmsh.model.mesh.renumberNodes() gmsh.model.mesh.renumberElements() gmsh.write(str(rve_geo.mesh_abs_path)) rve_path = msh_conversion(rve_geo.mesh_abs_path, ".xdmf") # * Step 3 : Build the mesh of the part from the mesh of the RVE gmsh.logger.start() part_geo = mesh_generate_2D.Gmsh2DPartFromRVE(rve_geo, (10, 1)) process_gmsh_log(gmsh.logger.get()) gmsh.logger.stop() part_path = msh_conversion(part_geo.mesh_abs_path, ".xdmf") # * Step 4 : Defining the material properties E, nu = 1.0, 0.3 E_nu_tuples = [(E, nu)] material = materials.Material(E, nu, "cp") # * Step 5 : Calculation of the full-scale solution # * Step 5.1 : Create a part object panto_part = part.FenicsPart.file_2_FenicsPart( part_path, material, global_dimensions=part_geo.gen_vect, subdomains_import=False, plots=False, ) LX = panto_part.global_dimensions[0, 0] LY = panto_part.global_dimensions[1, 1]
# * Step 2 : Defining the material mechanical properties for each subdomain E1, nu1 = 1.0, 0.3 E2, nu2 = E1 / 100.0, nu1 E_nu_tuples = [(E1, nu1), (E2, nu2)] # * Step 3 : Creating the Python object that represents the RVE and is suitable for FEniCS # * Two alternatives : # * Step 3.1 : Conversion of the Gmsh2DRVE instance if with_soft_mat: subdo_tags = tuple( [subdo.tag for subdo in panto_test.phy_surf] ) # Here: soft_mat = True => tags = (1, 2) material_dict = dict() for coeff, tag in zip(E_nu_tuples, subdo_tags): material_dict[tag] = mat.Material(coeff[0], coeff[1], "cp") rve = part.Fenics2DRVE.rve_from_gmsh2drve(panto_test, material_dict) else: material = mat.Material(E1, nu1, "cp") rve = part.Fenics2DRVE.rve_from_gmsh2drve(panto_test, material) # ! OR: # * Step 3.2 : Initialization of the Fenics2DRVE instance from # * a mesh file + generating vectors # mesh_path = Path("panto_with_soft.msh") # gen_vect = np.array([[4., 0.], [0., 8.]]) # rve = part.Fenics2DRVE.rve_from_file(mesh_path, gen_vect, material_dict) # * Step 4 : Initializing the homogemization model hom_model = hom.Fenics2DHomogenization(rve)
lc_ratio = 1 / 3.0 d_min_max = (2 * r * a, a) lc_min_max = (lc_ratio * r * a, lc_ratio * a) for geo_model in [part_geo, rve_geo]: geo_model.main_mesh_refinement(d_min_max, lc_min_max, False) gmsh.logger.start() geo_model.mesh_generate() toolbox_gmsh.process_gmsh_log(gmsh.logger.get()) gmsh.logger.stop() # * Step 2 : Defining the material properties E, nu = 1.0, 0.3 E_nu_tuples = [(E, nu)] material_dict_part = { part_geo.phy_surf[0].tag: materials.Material(E, nu, "cp") } material_dict_rve = {rve_geo.phy_surf[0].tag: materials.Material(E, nu, "cp")} # * Step 3 : Calculation of the full-scale solution # * Step 3.1 : Create a part object panto_part = part.FenicsPart.file_2_FenicsPart( part_geo.mesh_abs_path, material_dict_part, global_dimensions=part_geo.gen_vect, subdomains_import=True, plots=False, ) LX = panto_part.global_dimensions[0, 0] LY = panto_part.global_dimensions[1, 1]
def test_homog_EGG_pantograph_1x1(generate_mesh=False): logger.debug("Start test_homog_EGG_pantograph_1x1") start = time.time() if generate_mesh: geometry.init_geo_tools() geometry.set_gmsh_option("Mesh.MshFileVersion", 4.1) a = 1 b, k = a, a / 3 r = 0.02 panto_test = mesh_generate.pantograph.pantograph_RVE( a, b, k, r, nb_cells=(1, 1), soft_mat=False, name="panto_rve_1x1") lc_ratio = 1 / 6 lc_min_max = (lc_ratio * r * a, lc_ratio * a) panto_test.main_mesh_refinement((2 * r * a, a), lc_min_max, False) panto_test.mesh_generate() gmsh.model.mesh.renumberNodes() gmsh.model.mesh.renumberElements() gmsh.write("panto_rve_1x1.msh") mesh_path = msh_conversion("panto_rve_1x1.msh", ".xdmf") E, nu = 1.0, 0.3 mesh_path = "panto_rve_1x1.xdmf" material = materials.Material(E, nu, "cp") gen_vect = np.array([[4.0, 0.0], [0.0, 8.0]]) rve = part.Fenics2DRVE.rve_from_file(mesh_path, gen_vect, material) hom_model = homog2d.Fenics2DHomogenization(rve) *localzt_dicts, constit_tensors = hom_model.homogenizationScheme("EGG") Chom_ref = np.array([ [2.58608139e-04, 3.45496903e-04, 5.16572422e-12], [3.45496903e-04, 3.81860676e-02, 6.48384646e-11], [5.16572422e-12, 6.48384646e-11, 3.27924466e-04], ]) D_ref = np.array([ [ 3.7266e-02, 2.2039e-02, 4.6218e-10, 1.5420e-10, 1.2646e-09, -1.3939e-03 ], [ 2.2039e-02, -4.3185e-03, -3.4719e-11, 2.7544e-10, 7.0720e-10, 1.2415e-02 ], [ 4.6218e-10, -3.4719e-11, 1.3071e-01, 1.5918e-02, -9.9492e-03, -2.9101e-10 ], [ 1.5420e-10, 2.7544e-10, 1.5918e-02, 1.5802e-01, 1.2891e-01, 1.5962e-09 ], [ 1.2646e-09, 7.0720e-10, -9.9492e-03, 1.2891e-01, 1.1628e-01, 1.3358e-09 ], [ -1.3939e-03, 1.2415e-02, -2.9101e-10, 1.5962e-09, 1.3358e-09, 6.3893e-05 ], ]) Chom = constit_tensors["E"]["E"] G = constit_tensors["E"]["EGGbis"] D = (constit_tensors["EG"]["EG"] - np.vstack( (G[:, :6], G[:, 6:])) - np.vstack((G[:, :6], G[:, 6:])).T) logger.debug(f"Chom : \n {Chom}") logger.debug(f"D : \n {D}") logger.debug(f"Duration : {time.time() - start}") assert Chom == approx(Chom_ref, rel=1e-3, abs=1e-10) assert D == approx(D_ref, rel=1e-3, abs=1e-8) logger.debug("End test_homog_EGG_pantograph_1x1") logger.debug(f"Duration : {time.time() - start}")