Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/ElmerWorkflows/FreeCADBatchFEMTools/meshutils.py
3196 views
1
"""
2
FreeCADBatchFEMTools - A library for using FreeCAD for FEM preprocessing in batch mode
3
4
Copyright 1st May 2018 - , Trafotek Oy, Finland
5
6
This library is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public
8
License as published by the Free Software Foundation; either
9
version 2.1 of the License, or (at your option) any later version.
10
11
This library is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Lesser General Public License for more details.
15
16
You should have received a copy of the GNU Lesser General Public
17
License along with this library (in file ../LGPL-2.1); if not, write
18
to the Free Software Foundation, Inc., 51 Franklin Street,
19
Fifth Floor, Boston, MA 02110-1301 USA
20
21
Authors: Eelis Takala, Sami Rannikko
22
Emails: [email protected]
23
Address: Trafotek Oy
24
Kaarinantie 700
25
20540 Turku
26
Finland
27
28
Original Date: April 2020
29
"""
30
import os
31
import shutil
32
33
34
def parse_geo_id_list_string_to_list(geo_list_string):
35
"""
36
Collects ids from geo string.
37
38
:param geo_list_string: A string e.g. '{15, 16};'
39
40
:return: A list e.g ['15', '16'].
41
"""
42
id_list = []
43
for id_str in geo_list_string.replace(';', '').replace('{', '').replace('}', '').split(','):
44
id_list.append(id_str.strip())
45
return id_list
46
47
48
def collect_geometry_ids_from_geo_file(geo_file_path):
49
"""
50
Collects geometry ids from geo file to dictionary.
51
52
:param geo_file_path: Path to geo file.
53
54
:return: A dictionary.
55
"""
56
geom_id_dict = {}
57
with open(geo_file_path, 'r') as geo_file:
58
for line in geo_file:
59
if line.startswith('Physical Volume(') or line.startswith('Physical Surface('):
60
left_hand_side, right_hand_side = line.split('=') # Physical Volume("SolidName") = {2, 3};
61
volume_or_surface_name = left_hand_side.split('"')[1]
62
geom_id_dict[volume_or_surface_name] = parse_geo_id_list_string_to_list(right_hand_side)
63
return geom_id_dict
64
65
66
def _get_transfinite_line_geo_file_line(line_param_dict):
67
"""
68
Returns transfinite line geo file line e.g. 'Transfinite Line {59, 60} = 9 Using Progression 1;'
69
or 'Transfinite Line {59, 60} = 9 Using Bump 0.1;'.
70
71
:param line_param_dict: A dictionary containing transfinite line params.
72
73
:return: A string.
74
"""
75
if line_param_dict.get('comment', ''):
76
comment = ' // {}'.format(line_param_dict['comment'])
77
else:
78
comment = ''
79
if line_param_dict.get('mesh_type', ''):
80
mesh_type = line_param_dict['mesh_type']
81
else:
82
mesh_type = 'Progression'
83
coef = line_param_dict['progression']
84
return 'Transfinite Line {{{}}} = {} Using {} {};{}\n'.format(', '.join(line_param_dict['lines']),
85
line_param_dict['points'],
86
mesh_type, coef, comment)
87
88
89
def _get_transfinite_surface_geo_file_line(surface_name, transfinite_param_dict, geometry_id_dict,
90
exact_surface_equality):
91
"""
92
Returns transfinite surface geo file line e.g. 'Transfinite Surface {42, 44, 43, 41, 131, 130} Right;'.
93
94
:param surface_name: A string.
95
:param transfinite_param_dict: A dictionary containing transfinite parameters.
96
:param geometry_id_dict: A dictionary (names to geometry ids)
97
:param exact_surface_equality: A boolean.
98
99
:return: A string.
100
"""
101
geo_file_surface_name = None
102
if exact_surface_equality:
103
geo_file_surface_name = surface_name
104
else:
105
for geo_file_surface_name_i in geometry_id_dict:
106
if surface_name in geo_file_surface_name_i: # 'A1_alpha1' in 'A1_alpha1_A2_alpha0'
107
geo_file_surface_name = geo_file_surface_name_i
108
break
109
if geo_file_surface_name is None or geo_file_surface_name not in geometry_id_dict:
110
raise ValueError('Surface {} not found from geo file'.format(surface_name))
111
surface_id_str_list = geometry_id_dict[geo_file_surface_name]
112
direction_key = '{}_direction'.format(surface_name)
113
if transfinite_param_dict.get(direction_key, ''):
114
return 'Transfinite Surface {{{}}} {}; // {}\n'.format(', '.join(surface_id_str_list),
115
transfinite_param_dict[direction_key],
116
geo_file_surface_name)
117
else:
118
return 'Transfinite Surface {{{}}}; // {}\n'.format(', '.join(surface_id_str_list), geo_file_surface_name)
119
120
121
def add_transfinite_lines_to_geo_file(directory, transfinite_param_list, file_name='shape2mesh.geo',
122
exact_surface_equality=False):
123
"""
124
Adds transfinite lines to file file_name.
125
126
:param directory: Gmsh temp file location.
127
:param transfinite_param_list: A list containing dictionaries {'volume': 'name',
128
'surface_list': [s_name, s_name2]}.
129
:param file_name: A string.
130
:param exact_surface_equality: A boolean. When given surfaces are compared from geo file name use exact names.
131
Default values is False because surfaces can be merged (e.g. 'A1_alpha0_A2_alpha1').
132
133
"""
134
geo_path = os.path.join(directory, file_name)
135
geo_path_cp = os.path.join(directory, 'shape2mesh_cp.geo')
136
shutil.copy(geo_path, geo_path_cp)
137
geom_id_dict = collect_geometry_ids_from_geo_file(geo_path)
138
with open(geo_path, 'w') as geo_file:
139
with open(geo_path_cp, 'r') as original_geo_file_cp:
140
lines_added = False
141
for i, line in enumerate(original_geo_file_cp):
142
if i == 1:
143
geo_file.write('General.ExpertMode = 1; // Allow all mesh algorithms for transfinite\n')
144
if not lines_added and line.startswith('// Characteristic Length'):
145
lines_added = True
146
for p_dict in transfinite_param_list:
147
geo_file.write('// Transfinite {}\n'.format(p_dict['volume']))
148
for line_p_dict in p_dict.get('line_params', []):
149
geo_file.write(_get_transfinite_line_geo_file_line(line_p_dict))
150
for surface_name in p_dict['surface_list']:
151
geo_file.write(_get_transfinite_surface_geo_file_line(surface_name, p_dict, geom_id_dict,
152
exact_surface_equality))
153
if p_dict.get('volume_corner_points', None):
154
geo_file.write('Transfinite Volume {{{}}} = {{{}}};\n'.format(', '.join(geom_id_dict[p_dict['volume']]),
155
', '.join(p_dict['volume_corner_points'])))
156
else:
157
geo_file.write('Transfinite Volume {{{}}};\n'.format(', '.join(geom_id_dict[p_dict['volume']])))
158
geo_file.write('\n')
159
geo_file.write(line)
160
os.remove(geo_path_cp)
161
162
163
164
165
166