Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
ElmerCSC
GitHub Repository: ElmerCSC/elmerfem
Path: blob/devel/fem/obsolete/SC2Elmer.c
5271 views
1
/*
2
* A program to convert Silicomp mesh file to elmer mesh.
3
*
4
* Usage: SC2Elmer silicomp_file
5
*
6
* the result is files: mesh.header, mesh.nodes, mesh.elements, mesh.boundary
7
* containing the mesh in elmer format.
8
*
9
* boundaries may be grouped based on boundary normals if file groups.dat
10
* is found in current directory. The groups.dat file consist of following:
11
*
12
* n tolerance_angle
13
* nx_1 ny_1
14
* ...
15
* ...
16
*
17
* nx_n ny_n
18
*
19
* tolerance angle is given in degrees.
20
*/
21
22
#include <stdio.h>
23
#include <math.h>
24
#include <stdlib.h>
25
26
#define MAX_LEN 1000
27
char buf[MAX_LEN+1];
28
29
typedef struct edge
30
{
31
struct edge *next;
32
33
int n1,n2,n3,p1,p2;
34
} edge_t;
35
36
double *nx, *ny, *fx;
37
38
/*
39
* return next line from file.
40
*/
41
char *scan( FILE *fp )
42
{
43
char *ptr;
44
45
*buf = ' ';
46
while( 1 )
47
{
48
if ( feof(fp) || ferror(fp) ) break;
49
fgets( buf, MAX_LEN, fp );
50
51
ptr = buf;
52
while( *ptr != '\0' && *ptr != ' ' ) ptr++;
53
54
if ( *ptr != '\0' ) break;
55
}
56
57
return buf;
58
}
59
60
/*
61
* Find mesh edges.
62
*/
63
int findedges( int n, int *el[8], edge_t **edge )
64
{
65
int i, j, k, e1,e2, e3, edges, n1,n2,n3;
66
edge_t *ptr, *ptr0;
67
68
int map[4][3] = { { 0,1,4 }, { 1,2,5 }, { 2,3,6 }, { 3,0,7 } };
69
70
edges = 0;
71
for( i=0; i<n; i++ )
72
{
73
for( j=0; j<4; j++ ) {
74
n1 = el[map[j][0]][i];
75
n2 = el[map[j][1]][i];
76
n3 = el[map[j][2]][i];
77
78
if ( n2 < n1 ) { k=n1; n1=n2; n2=k; }
79
80
ptr0 = edge[n1];
81
ptr = edge[n1];
82
while( ptr )
83
{
84
if ( ptr->n2 == n2 ) {
85
ptr->p2 = i;
86
break;
87
}
88
ptr0 = ptr;
89
ptr = ptr->next;
90
}
91
92
if ( !ptr ) {
93
if ( !ptr0 ) {
94
ptr = edge[n1] = (edge_t *)calloc( sizeof( edge_t ), 1 );
95
} else {
96
ptr = ptr0->next = (edge_t *)calloc( sizeof( edge_t ), 1 );
97
}
98
99
ptr->n1 = n1;
100
ptr->n2 = n2;
101
ptr->n3 = n3;
102
ptr->p1 = i;
103
ptr->p2 = -1;
104
105
edges++;
106
}
107
}
108
}
109
fprintf( stderr, "found edges: %d\n", edges );
110
111
return edges;
112
}
113
114
/*
115
* Compute boundary element outer normal
116
*/
117
void normal( double *n, int p1, int p2, double cx, double cy )
118
{
119
double dxdu, dydu, detA;
120
121
dxdu = nx[p2] - nx[p1];
122
dydu = ny[p2] - ny[p1];
123
124
detA = dxdu*dxdu + dydu*dydu;
125
detA = 1.0 / sqrt(detA);
126
127
n[0] = -dydu * detA;
128
n[1] = dxdu * detA;
129
130
cx = cx - ( nx[p1] + nx[p2] ) / 2;
131
cy = cy - ( ny[p1] + ny[p2] ) / 2;
132
133
if ( n[0]*cx + n[1]*cy > 0 ) { n[0] = -n[0]; n[1] = -n[1]; }
134
}
135
136
int main( int argc, char **argv )
137
{
138
FILE *fp = fopen( argv[1], "r" ), *fp_out, *fp_grp;
139
140
char *line;
141
142
int i,j,k,i1,i2,i3,i4,i5,i6,i7,i8,nodes,elements,*ref, *renumber, *el[8], grp, groups;
143
edge_t **edge, *ptr;
144
double x,y,n[2],cx,cy, g, *groups_x, *groups_y, s, twopi, ang;
145
146
line = scan( fp );
147
sscanf( line, "%d %d", &elements, &nodes );
148
149
for( i=0; i<8; i++ )
150
el[i] = (int *)malloc( elements*sizeof(int) );
151
152
edge = (edge_t **)calloc( nodes,sizeof(edge_t *) );
153
154
ref = (int *)calloc( nodes, sizeof(int) );
155
renumber = (int *)calloc( nodes, sizeof(int) );
156
157
nx = (double *)calloc( nodes, sizeof(double) );
158
ny = (double *)calloc( nodes, sizeof(double) );
159
fx = (double *)calloc( nodes, sizeof(double) );
160
161
/*
162
* Read the elements from silicomp format file, store in memory
163
*/
164
for( i=0; i<elements; i++ )
165
{
166
line = scan( fp );
167
j = sscanf( line, "%d %d %d %d %d %d %d %d %d", &k, &i1,&i2,&i3,&i4,&i5,&i6,&i7,&i8 );
168
if ( j != 9 ) break;
169
170
ref[i1] = 1;
171
ref[i2] = 1;
172
ref[i3] = 1;
173
ref[i4] = 1;
174
ref[i5] = 1;
175
ref[i6] = 1;
176
ref[i7] = 1;
177
ref[i8] = 1;
178
179
el[0][i] = i1;
180
el[1][i] = i2;
181
el[2][i] = i3;
182
el[3][i] = i4;
183
el[4][i] = i5;
184
el[5][i] = i6;
185
el[6][i] = i7;
186
el[7][i] = i8;
187
}
188
if ( i>=elements) scan( fp );
189
elements = i;
190
191
/*
192
* Do a continuous renumbering of nodal points.
193
*/
194
k = 0;
195
for( i=0; i<nodes; i++ )
196
{
197
if ( ref[i] ) { renumber[i] = k++; }
198
}
199
200
/*
201
* Output elements in ELMER format.
202
*/
203
fp_out = fopen( "mesh.elements", "w" );
204
for( i=0; i<elements; i++ )
205
{
206
for ( j=0; j<8; j++ ) el[j][i] = renumber[ el[j][i] ];
207
208
fprintf( fp_out, "%d 1 408 %d %d %d %d %d %d %d %d\n", i+1,
209
el[0][i]+1,
210
el[1][i]+1,
211
el[2][i]+1,
212
el[3][i]+1,
213
el[4][i]+1,
214
el[5][i]+1,
215
el[6][i]+1,
216
el[7][i]+1 );
217
}
218
fclose( fp_out );
219
220
/*
221
* Read nodal points from Silicomp format file.
222
*/
223
for( i=0; i<nodes; i++ )
224
{
225
if ( 3 != sscanf( line, "%d %lf %lf", &i1, &x, &y ) ) break;
226
line = scan( fp );
227
228
nx[renumber[i1]] = x;
229
ny[renumber[i1]] = y;
230
}
231
if ( i>=nodes ) scan( fp );
232
nodes = i;
233
234
/*
235
* Write nodal points in ELMER format.
236
*/
237
fp_out = fopen( "mesh.nodes", "w" );
238
for( i=0; i<nodes; i++ )
239
{
240
fprintf( fp_out, "%d -1 %g %g 0.0\n", i+1, nx[i], ny[i] );
241
}
242
fclose( fp_out );
243
244
/*
245
* Read temperature field from Silicomp format file.
246
*/
247
for( i=0; i<nodes; i++ )
248
{
249
sscanf( line, "%d %lf", &i1, &y );
250
fx[renumber[i1]] = y;
251
line = scan( fp );
252
}
253
254
/*
255
* Write temperature field in ELMER format.
256
*/
257
fp_out = fopen( "result.dat", "w" );
258
fprintf( fp_out,
259
"Degrees of freedom:\n"
260
"temperature 1 :heat equation\n"
261
"Total DOFs: 1\n"
262
"Time: 1 1 0.100000000000E+001\n"
263
"temperature\n" );
264
265
for( i=0; i<nodes; i++ )
266
{
267
fprintf( fp_out, "%d %d %g\n", i+1,i+1,fx[i] );
268
}
269
fclose( fp_out );
270
271
/*
272
* Find all edges of the mesh. Boundaries are identified as edges
273
* who have only one parent element.
274
*/
275
k = findedges( elements, el,edge );
276
277
/*
278
* Read in groups.dat file which gives normals to organize
279
* boundaries to separate groups:
280
*
281
* * if given group normal and outward boundary normal are
282
* within given angle add boundary element to boundary group.
283
*/
284
fp_grp = fopen( "groups.dat", "r" );
285
groups = 0;
286
if ( fp_grp ) {
287
twopi = 4 * acos(0.0);
288
ang = 0.0;
289
fscanf( fp_grp, "%d %lf", &groups, &ang );
290
ang = 1.0 - cos( ang * twopi / 360.0 );
291
groups_x = (double *)malloc( groups*sizeof(double) );
292
groups_y = (double *)malloc( groups*sizeof(double) );
293
for( i=0; i<groups; i++ )
294
{
295
fscanf( fp_grp, "%lf %lf", &groups_x[i], &groups_y[i] );
296
s = sqrt( groups_x[i]*groups_x[i] + groups_y[i]*groups_y[i] );
297
groups_x[i] /= s;
298
groups_y[i] /= s;
299
}
300
fclose(fp_grp);
301
}
302
303
/*
304
* Output boundary elements in ELMER format.
305
*/
306
fp_out = fopen( "mesh.boundary", "w" );
307
j = 0;
308
for( i=0; i<nodes; i++ )
309
{
310
ptr = edge[i];
311
while( ptr ) {
312
if ( ptr->p2 < 0 ) {
313
j++;
314
k = ptr->p1;
315
cx = (nx[el[0][k]] + nx[el[1][k]] + nx[el[2][k]] + nx[el[3][k]]) / 4.0;
316
cy = (ny[el[0][k]] + ny[el[1][k]] + ny[el[2][k]] + ny[el[3][k]]) / 4.0;
317
318
normal( n, ptr->n1, ptr->n2, cx,cy );
319
for( k=0; k<groups; k++ )
320
{
321
if ( fabs( 1 - n[0]*groups_x[k] + n[1]*groups_y[k] ) < ang+1.0e-10 ) break;
322
}
323
fprintf( fp_out, "%d %d %d 0 203 %d %d %d\n", j,k+1, ptr->p1+1,ptr->n1+1,ptr->n2+1,ptr->n3+1 );
324
}
325
ptr = ptr->next;
326
}
327
}
328
fclose( fp_out );
329
330
/*
331
* Output mesh header in ELMER format.
332
*/
333
fp_out = fopen( "mesh.header", "w" );
334
fprintf( fp_out, "%d %d %d\n", nodes, elements, j );
335
336
fprintf( fp_out, "2\n408 %d\n203 %d\n", elements, j );
337
fclose( fp_out );
338
}
339
340