Path: blob/devel/ElmerWorkflows/FreeCADBatchFEMTools/tests/cubemeshtest/cubemeshtest_freecadscript.py
3206 views
doc = App.newDocument('cube geometry')1import sys2import os3import time4import math5import FreeCAD67sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..'))8import FreeCADBatchFEMTools91011def cut_xy_plane(part, cut_len, cut_width, cut_height):12doc.recompute()13doc.recompute()14reduced_name = part.Name + '_xy'15tool_box = doc.addObject("Part::Box", "CutBox" + reduced_name + '_obj')16tool_box.Length = cut_len17tool_box.Width = cut_width18tool_box.Height = cut_height19c_x = part.Shape.BoundBox.Center.x20c_y = part.Shape.BoundBox.Center.y21tool_box.Placement = App.Placement(App.Vector(c_x-cut_len/2., c_y-cut_width/2., -cut_height),22App.Rotation(App.Vector(0, 0, 1), 0))2324cut_part = doc.addObject("Part::Cut", reduced_name + '_obj')25cut_part.Base = part26cut_part.Tool = tool_box27return cut_part2829def print_line(line_str, start_time):30"""31Prints elapsed time and flushes stdout.3233:param line_str: A string.34:param start_time: A float.35"""36elapsed_time = round(time.time() - start_time, 1)37print('Elapsed time: {} seconds'.format(elapsed_time))38print(line_str)39sys.stdout.flush()40return elapsed_time4142def create_air_geometry(entities_list, length, width, height, shift, mesh_size):43"""44Creates air around created parts in part_list.4546:param entities_list: A list containing entities dicts.47:param length: A float.48:param width: A float.49:param height: A float.50:param shift: A float.51:param mesh_size: A float or None.5253:return: Air part object.54"""55bounding_box_part = doc.addObject("Part::Box", "air_obj")56bounding_box_part.Length = length57bounding_box_part.Width = width58bounding_box_part.Height = height59bounding_box_part.Placement = App.Placement(App.Vector(-shift, -shift, 0),60App.Rotation(App.Vector(0, 0, 1), 0))61doc.recompute()6263solid_objects = [bounding_box_part] + [solid['main object'] for solid in entities_list]64air_part = FreeCADBatchFEMTools.create_xor_object(solid_objects, doc)65doc.recompute()66# remove already created faces67faces_in_symmetry_plane = FreeCADBatchFEMTools.faces_with_vertices_in_symmetry_plane(air_part.Shape.Faces,68plane='xy')69used_faces = []70for part in entities_list:71used_faces.extend([face_entity['geometric object'] for face_entity in part['faces']])72FreeCADBatchFEMTools.remove_compare_faces_from_list(used_faces, faces_in_symmetry_plane)73faces = []74for face in faces_in_symmetry_plane:75FreeCADBatchFEMTools.add_entity_in_list(faces, 'beta0', face)76solids = []77FreeCADBatchFEMTools.add_entity_in_list(solids, 'air', air_part, {'mesh size': mesh_size})78entities_dict = FreeCADBatchFEMTools.create_entities_dict('air', faces, solids, main_object=air_part)79doc.recompute()8081return entities_dict8283def create_sphere_geometry(nof_spheres, mesh_size, diameter, distance):84"""85Create sphere geometry. Spheres are moved down 10% and cut from xy plane86because caused problems with air otherwise.8788:param nof_spheres: Number of spheres.89:param mesh_size: Mesh size of spheres.90:param diameter: Diameter of spheres.91:param distance: Distance between spheres.9293:return: A list containing entities dictionaries.94"""95sphere_entities_dict_list = []96r = diameter/2.097shift = diameter/10.098n = int(math.ceil(math.sqrt(nof_spheres)))99bbox_len = n*(diameter+distance)100counter = 0101for i in range(n):102for j in range(n):103sphere_name = 'sphere{:04d}'.format(counter + 1)104sphere = doc.addObject('Part::Sphere', sphere_name + '_obj')105sphere.Radius = r106sphere.Placement = App.Placement(App.Vector(r + i*(diameter+distance), r + j*(diameter+distance), r-shift),107App.Rotation(App.Vector(0, 0, 1), 0))108doc.recompute()109sphere = cut_xy_plane(sphere, bbox_len, bbox_len, diameter)110doc.recompute()111# create entities dict112face_picks = [('alpha1', 0), ('beta0', 1)]113faces = FreeCADBatchFEMTools.pick_faces_from_geometry(sphere, face_picks)114solids = []115FreeCADBatchFEMTools.add_entity_in_list(solids, sphere_name, sphere, {'mesh size': mesh_size})116entities_dict = FreeCADBatchFEMTools.create_entities_dict(sphere_name, faces, solids, sphere)117sphere_entities_dict_list.append(entities_dict)118doc.recompute()119counter += 1120if counter == nof_spheres:121return sphere_entities_dict_list122123def create_cube_geometry(nof_cubes, mesh_size, length, width, height, cube_distance):124"""125Create cube geometry.126127:param nof_cubes: Number of cubes.128:param mesh_size: Mesh size of cubes.129:param length: Length of cubes.130:param width: Width of cubes.131:param height: Height of cubes.132:param cube_distance: Distance between cubes.133134:return: A list containing entities dictionaries.135"""136cube_entities_dict_list = []137n = int(math.ceil(math.sqrt(nof_cubes)))138counter = 0139for i in range(n):140for j in range(n):141cube_name = 'cube{:04d}'.format(counter + 1)142cube = doc.addObject('Part::Box', cube_name + '_obj')143cube.Length = length144cube.Width = width145cube.Height = height146cube.Placement = App.Placement(App.Vector(i * (length+cube_distance), j * (width+cube_distance), 0),147App.Rotation(App.Vector(0, 0, 1), 0))148doc.recompute()149# create entities dict150face_picks = [('alpha0', 5), ('alpha1', 0), ('beta0', 4), ('beta1', 2), ('gamma0', 3), ('gamma1', 1)]151faces = FreeCADBatchFEMTools.pick_faces_from_geometry(cube, face_picks)152solids = []153FreeCADBatchFEMTools.add_entity_in_list(solids, cube_name, cube, {'mesh size': mesh_size})154entities_dict = FreeCADBatchFEMTools.create_entities_dict(cube_name, faces, solids, cube)155cube_entities_dict_list.append(entities_dict)156doc.recompute()157counter += 1158if counter == nof_cubes:159return cube_entities_dict_list160161162def create_geometry(nof_cubes, mesh_size, find_boundaries_from_entities_dict, find_solids_from_entities_dict, directory,163add_air, point_search, use_spheres, mesh_size_air):164"""165Creates geometry for cubes/spheres and exports unv file.166167:param nof_cubes: Number of cubes/spheres created.168:param mesh_size: Mesh size for cubes/spheres.169:param find_boundaries_from_entities_dict: 'True' or 'False'.170:param find_solids_from_entities_dict: 'True' or 'False'.171:param directory: Path to directory of this script.172:param add_air: A boolean. Is air added to geometry.173:param point_search: A boolean.174:param use_spheres: A boolean.175:param mesh_size_air: A float.176177:return: A list containing tuples (name, execution time).178"""179total_start_time = time.time()180entities_list = []181return_time_list = []182cube_edge_length, cube_distance = 200, 20183mesh_size_max = max(mesh_size, mesh_size_air)184if use_spheres:185print_line('Creating sphere geometry...', total_start_time)186entities_list.extend(create_sphere_geometry(nof_cubes, mesh_size, cube_edge_length, cube_distance))187else:188print_line('Creating cube geometry...', total_start_time)189entities_list.extend(create_cube_geometry(nof_cubes, mesh_size, cube_edge_length, cube_edge_length,190cube_edge_length, cube_distance))191if add_air:192n = int(math.ceil(math.sqrt(nof_cubes)))193air_edge_length = n*(cube_edge_length+cube_distance) + cube_distance194air_height = cube_edge_length+2*cube_distance195print_line("Creating air geometry...", total_start_time)196entities_list.append(create_air_geometry(entities_list, air_edge_length, air_edge_length, air_height,197cube_distance, mesh_size_air))198entities_list.reverse() # give air first to get mesh sizes correctly199print_line("Merging entities dictionaries...", total_start_time)200entities_dict = FreeCADBatchFEMTools.merge_entities_dicts(entities_list, 'All', default_mesh_size=mesh_size_max,201add_prefixes={'solids': False, 'faces': True})202print_line("Getting solids from entities dictionaries...", total_start_time)203solid_objects = FreeCADBatchFEMTools.get_solids_from_entities_dict(entities_dict)204print_line("Creating mesh object and compound filter...", total_start_time)205mesh_object, compound_filter = FreeCADBatchFEMTools.create_mesh_object_and_compound_filter(solid_objects,206mesh_size_max, doc)207if find_boundaries_from_entities_dict.lower() == 'true':208print_line("Finding boundaries...", total_start_time)209start_time = time.time()210FreeCADBatchFEMTools.find_boundaries_with_entities_dict(mesh_object, compound_filter,211entities_dict, doc)212return_time_list.append(('-Find boundaries:', time.time() - start_time))213if find_solids_from_entities_dict.lower() == 'true':214print_line("Finding bodies...", total_start_time)215start_time = time.time()216body_mesh_groups = FreeCADBatchFEMTools.find_bodies_with_entities_dict(mesh_object, compound_filter,217entities_dict, doc, point_search)218return_time_list.append(('-Find solids:', time.time() - start_time))219print_line("Defining mesh sizes...", total_start_time)220start_time = time.time()221# ignore air from mesh definition, mesh_object forces air to largest mesh222if find_solids_from_entities_dict.lower() == 'true':223FreeCADBatchFEMTools.define_mesh_sizes_with_mesh_groups(mesh_object, body_mesh_groups, doc, ignore_list=['air'])224else: # in this case mesh sizes needs to be found225FreeCADBatchFEMTools.define_mesh_sizes(mesh_object, compound_filter, entities_dict, doc, point_search,226ignore_list=['air'])227return_time_list.append(('-Define mesh sizes:', time.time() - start_time))228FreeCADBatchFEMTools.fit_view()229start_time = time.time()230print_line("Creating mesh...", total_start_time)231FreeCADBatchFEMTools.create_mesh(mesh_object)232return_time_list.append(('-Create mesh:', time.time() - start_time))233print_line("Exporting unv...", total_start_time)234FreeCADBatchFEMTools.export_unv(os.path.join(directory, 'cubemeshtest.unv'), mesh_object)235print_line("Geometry done", total_start_time)236return return_time_list + [('-Total time:', time.time() - total_start_time)]237238239script_directory = os.path.dirname(__file__)240241with open(os.path.join(script_directory, 'cubemeshtestparameters.txt')) as f:242[number_of_cubes, cube_mesh_size, find_boundaries, find_solids, create_air, air_mesh_size,243find_with_points, create_spheres, append_file] = f.read().split()244245create_air = create_air.lower() == 'true'246find_with_points = find_with_points.lower() == 'true'247create_spheres = create_spheres.lower() == 'true'248if air_mesh_size == 'None':249air_mesh_size = cube_mesh_size250try:251elapsed_times = create_geometry(int(number_of_cubes), float(cube_mesh_size), find_boundaries, find_solids,252script_directory, create_air, find_with_points, create_spheres, float(air_mesh_size))253except Exception:254import traceback255print(str(traceback.format_exc()))256else:257if create_air:258info_line = '\nexecution times with {} cubes (air: {}, spheres: {}, fb: {}, '.format(number_of_cubes, create_air,259create_spheres, find_boundaries)260info_line += 'fs: {}, mesh_size: {}, air_mesh_size: {}, point_search: {}):'.format(find_solids, cube_mesh_size,261air_mesh_size, find_with_points)262else:263info_line = '\nexecution times with {} cubes (air: {}, spheres: {}, fb: {}, '.format(number_of_cubes, create_air,264create_spheres, find_boundaries)265info_line += 'fs: {}, mesh_size: {}, point_search: {}):'.format(find_solids, cube_mesh_size, find_with_points)266print(info_line)267for time_tuple in elapsed_times:268print(time_tuple[0], round(time_tuple[1], 1))269sys.stdout.flush()270if append_file.lower() == 'true':271with open(os.path.join(script_directory, 'cubemeshtestexecutiontimes.txt'), 'a') as f:272f.write(info_line + '\n')273for time_tuple in elapsed_times:274f.write('{} {}\n'.format(time_tuple[0], round(time_tuple[1], 1)))275f.write('\n')276if not FreeCAD.GuiUp:277exit()278279280