-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeotofenics.py
179 lines (145 loc) · 6.09 KB
/
geotofenics.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
#!/usr/bin/env python3
"""
Created on Wed Jun 3 20:42:08 2020
Usage: ./geotofenics.py filename.geo
Note: A new file called 'filename.geo.xml' will be created if all goes
well. Make sure you don't have a file with the same name you want to keep
before running this.
EXPORTING FROM SOLIDWORKS SIMULATION
------------------------------------
1. Create your desired geometry in Solidworks. The model
can be a part or an assembly. If it is an asssembly, each part will
be stored in the mesh file as a domain. This is done by tagging
the elements with integers, starting from zero.
2. Choose Simulation->New Study->Thermal
3. Right-click Mesh->Create Mesh...
4. Choose your resolution (Mesh Parameters)
5. From the menu at the top Simulation->Export
6. From the "Save as" type menu, you MUST select Simulation files (*.geo)
7. IMPORTANT. CLick on Options and select "Export FEM only"
8. Save to a file WITHOUT a space in the name
READING IN FENICS AND VISUALIZE
------------------------------------
This script is particularly useful for multi-domains (i.e., multi-parts)
geometries. To import the generated mesh in fenics and visualize the
geometry with the various domains do something like (assuming
output_mesh.xml was generated by this script)
from fenics import *
from dolfin import *
mesh = Mesh("output_mesh.xml")
mf = MeshFunction("size_t", mesh, 3, mesh.domains())
domains_file = File('output_mesh.pvd')
domains_file << mf
Then, open output_mesh.pvd with Paraview and see the geometry and the
various domains.
This script was tested with
- Fenics/Dolfin 2019.1.0
- Solidworks 2019 Education Edition
- Python 3.6.10 on Ubuntu
@author: Alberto Corrias (Github: albertocorrias)
"""
import sys
if (len(sys.argv) != 2):
raise Exception('Only filename expected. Usage: ./geotofenics.py filename.geo')
sw_filename = sys.argv[1]
output_xml_filename = sw_filename + '.xml';
try:
input_sw_file = open(sw_filename, "r")
except:
print('ERROR: Unable to open input file ' + sw_filename)
exit();
try:
output_file = open(output_xml_filename, "w")
except:
print('ERROR: Unable to open putput file')
exit();
#Headers and footers
header = '<?xml version="1.0"?> \n \
<dolfin xmlns:dolfin="http://fenicsproject.org"> \n \
<mesh celltype="tetrahedron" dim="3"> \n';
footer = '<data /> </mesh> \n \
</dolfin>\n'
output_file.write(header);
#########################
#First sweep just to count elements, nodes and number of domains (parts)
nodes=0;
elems = 0;
domain_tags = []
for line in input_sw_file:
if (line.find('ND')!=-1) and (line.find('FND')==-1) and (line.find('DND')==-1):
#This is a "node" line
nodes = nodes + 1
if (line.find('EL,')!=-1):
#This is an "element" line
split_line = line.split();
tag_for_element = int(split_line[3].strip(','))
if tag_for_element not in domain_tags:
domain_tags.append(tag_for_element)#Store unique element tag
elems = elems + 1
input_sw_file.close()
#other headers and footers based on mesh size
node_string_header = '<vertices size="' + str(nodes) + '">\n';
output_file.write(node_string_header)
node_string_footer = '</vertices> \n'
elem_string_header = '<cells size="' + str(elems) + '">\n'
elem_string_footer = '</cells> \n'
num_domains = len(domain_tags)
domain_string_header = ' <domains> \n \
<mesh_value_collection name="f" type="uint" dim="3" size="' + str(elems) + '">\n'
domain_string_footer = '</mesh_value_collection> \n </domains>';
#Reopen the file and re-loop to get nodes and elements
input_sw_file = open(sw_filename, "r")
node_counter=0;
elem_counter = 0;
elem_domain_pairs = [[],[]] #This will be used for domains later
nodes_used = []
for line in input_sw_file:
if (line.find('ND')!=-1) and (line.find('FND')==-1) and (line.find('DND')==-1):
#This is a "node" line
split_line = line.split()
xml_node_line = '<vertex index="' + str(node_counter)+ \
'" x="' + str(split_line[2]) +\
'" y="' + str(split_line[3]) +\
'" z="' + str(split_line[4]) +'" />\n'
output_file.write(xml_node_line)
node_counter = node_counter + 1
if (line.find('EL,')!=-1):
#This is an "element" line
if (elem_counter==0):
output_file.write(node_string_footer)
output_file.write(elem_string_header)
split_line = line.split();
#note that we need to subtract 1 from the node number
#as Solidworks counts from 1
xml_elem_line = '<tetrahedron index="'+str(elem_counter) +\
'" v0="' + str(int(split_line[5])-1) +\
'" v1="' + str(int(split_line[6])-1) +\
'" v2="' + str(int(split_line[7])-1) +\
'" v3="' + str(int(split_line[8])-1) + '" />\n'
if (int(split_line[5])-1) not in nodes_used:
nodes_used.append(int(split_line[5])-1)
if (int(split_line[6])-1) not in nodes_used:
nodes_used.append(int(split_line[6])-1)
if (int(split_line[7])-1) not in nodes_used:
nodes_used.append(int(split_line[7])-1)
if (int(split_line[8])-1) not in nodes_used:
nodes_used.append(int(split_line[8])-1)
output_file.write(xml_elem_line)
#store element - domain pairs for later
tag_for_element = int(split_line[3].strip(','))-1
elem_domain_pairs[0].append(elem_counter)
elem_domain_pairs[1].append(tag_for_element)
elem_counter = elem_counter + 1
input_sw_file.close()
output_file.write(elem_string_footer)
print (node_counter, ' ', len(nodes_used))
#Add domains info before closing
output_file.write(domain_string_header)
for el_idx in elem_domain_pairs[0]:
domain_element_string = '<value cell_index="' + str(el_idx) +\
'" local_entity="0" value="'+str(elem_domain_pairs[1][el_idx])+'" />\n'
output_file.write(domain_element_string)
output_file.write(domain_string_footer)
#Footers and close
output_file.write(footer)
output_file.close();