Path: blob/devel/ElmerWorkflows/FreeCADBatchFEMTools/meshutils.py
3196 views
"""1FreeCADBatchFEMTools - A library for using FreeCAD for FEM preprocessing in batch mode23Copyright 1st May 2018 - , Trafotek Oy, Finland45This library is free software; you can redistribute it and/or6modify it under the terms of the GNU Lesser General Public7License as published by the Free Software Foundation; either8version 2.1 of the License, or (at your option) any later version.910This library is distributed in the hope that it will be useful,11but WITHOUT ANY WARRANTY; without even the implied warranty of12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU13Lesser General Public License for more details.1415You should have received a copy of the GNU Lesser General Public16License along with this library (in file ../LGPL-2.1); if not, write17to the Free Software Foundation, Inc., 51 Franklin Street,18Fifth Floor, Boston, MA 02110-1301 USA1920Authors: Eelis Takala, Sami Rannikko21Emails: [email protected]22Address: Trafotek Oy23Kaarinantie 7002420540 Turku25Finland2627Original Date: April 202028"""29import os30import shutil313233def parse_geo_id_list_string_to_list(geo_list_string):34"""35Collects ids from geo string.3637:param geo_list_string: A string e.g. '{15, 16};'3839:return: A list e.g ['15', '16'].40"""41id_list = []42for id_str in geo_list_string.replace(';', '').replace('{', '').replace('}', '').split(','):43id_list.append(id_str.strip())44return id_list454647def collect_geometry_ids_from_geo_file(geo_file_path):48"""49Collects geometry ids from geo file to dictionary.5051:param geo_file_path: Path to geo file.5253:return: A dictionary.54"""55geom_id_dict = {}56with open(geo_file_path, 'r') as geo_file:57for line in geo_file:58if line.startswith('Physical Volume(') or line.startswith('Physical Surface('):59left_hand_side, right_hand_side = line.split('=') # Physical Volume("SolidName") = {2, 3};60volume_or_surface_name = left_hand_side.split('"')[1]61geom_id_dict[volume_or_surface_name] = parse_geo_id_list_string_to_list(right_hand_side)62return geom_id_dict636465def _get_transfinite_line_geo_file_line(line_param_dict):66"""67Returns transfinite line geo file line e.g. 'Transfinite Line {59, 60} = 9 Using Progression 1;'68or 'Transfinite Line {59, 60} = 9 Using Bump 0.1;'.6970:param line_param_dict: A dictionary containing transfinite line params.7172:return: A string.73"""74if line_param_dict.get('comment', ''):75comment = ' // {}'.format(line_param_dict['comment'])76else:77comment = ''78if line_param_dict.get('mesh_type', ''):79mesh_type = line_param_dict['mesh_type']80else:81mesh_type = 'Progression'82coef = line_param_dict['progression']83return 'Transfinite Line {{{}}} = {} Using {} {};{}\n'.format(', '.join(line_param_dict['lines']),84line_param_dict['points'],85mesh_type, coef, comment)868788def _get_transfinite_surface_geo_file_line(surface_name, transfinite_param_dict, geometry_id_dict,89exact_surface_equality):90"""91Returns transfinite surface geo file line e.g. 'Transfinite Surface {42, 44, 43, 41, 131, 130} Right;'.9293:param surface_name: A string.94:param transfinite_param_dict: A dictionary containing transfinite parameters.95:param geometry_id_dict: A dictionary (names to geometry ids)96:param exact_surface_equality: A boolean.9798:return: A string.99"""100geo_file_surface_name = None101if exact_surface_equality:102geo_file_surface_name = surface_name103else:104for geo_file_surface_name_i in geometry_id_dict:105if surface_name in geo_file_surface_name_i: # 'A1_alpha1' in 'A1_alpha1_A2_alpha0'106geo_file_surface_name = geo_file_surface_name_i107break108if geo_file_surface_name is None or geo_file_surface_name not in geometry_id_dict:109raise ValueError('Surface {} not found from geo file'.format(surface_name))110surface_id_str_list = geometry_id_dict[geo_file_surface_name]111direction_key = '{}_direction'.format(surface_name)112if transfinite_param_dict.get(direction_key, ''):113return 'Transfinite Surface {{{}}} {}; // {}\n'.format(', '.join(surface_id_str_list),114transfinite_param_dict[direction_key],115geo_file_surface_name)116else:117return 'Transfinite Surface {{{}}}; // {}\n'.format(', '.join(surface_id_str_list), geo_file_surface_name)118119120def add_transfinite_lines_to_geo_file(directory, transfinite_param_list, file_name='shape2mesh.geo',121exact_surface_equality=False):122"""123Adds transfinite lines to file file_name.124125:param directory: Gmsh temp file location.126:param transfinite_param_list: A list containing dictionaries {'volume': 'name',127'surface_list': [s_name, s_name2]}.128:param file_name: A string.129:param exact_surface_equality: A boolean. When given surfaces are compared from geo file name use exact names.130Default values is False because surfaces can be merged (e.g. 'A1_alpha0_A2_alpha1').131132"""133geo_path = os.path.join(directory, file_name)134geo_path_cp = os.path.join(directory, 'shape2mesh_cp.geo')135shutil.copy(geo_path, geo_path_cp)136geom_id_dict = collect_geometry_ids_from_geo_file(geo_path)137with open(geo_path, 'w') as geo_file:138with open(geo_path_cp, 'r') as original_geo_file_cp:139lines_added = False140for i, line in enumerate(original_geo_file_cp):141if i == 1:142geo_file.write('General.ExpertMode = 1; // Allow all mesh algorithms for transfinite\n')143if not lines_added and line.startswith('// Characteristic Length'):144lines_added = True145for p_dict in transfinite_param_list:146geo_file.write('// Transfinite {}\n'.format(p_dict['volume']))147for line_p_dict in p_dict.get('line_params', []):148geo_file.write(_get_transfinite_line_geo_file_line(line_p_dict))149for surface_name in p_dict['surface_list']:150geo_file.write(_get_transfinite_surface_geo_file_line(surface_name, p_dict, geom_id_dict,151exact_surface_equality))152if p_dict.get('volume_corner_points', None):153geo_file.write('Transfinite Volume {{{}}} = {{{}}};\n'.format(', '.join(geom_id_dict[p_dict['volume']]),154', '.join(p_dict['volume_corner_points'])))155else:156geo_file.write('Transfinite Volume {{{}}};\n'.format(', '.join(geom_id_dict[p_dict['volume']])))157geo_file.write('\n')158geo_file.write(line)159os.remove(geo_path_cp)160161162163164165166