EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
egnative.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file egnative.cpp
1 /*
2  ElmerGrid - A simple mesh generation and manipulation utility
3  Copyright (C) 1995- , CSC - IT Center for Science Ltd.
4 
5  Author: Peter Råback
6  Email: Peter.Raback@csc.fi
7  Address: CSC - IT Center for Science Ltd.
8  Keilaranta 14
9  02101 Espoo, Finland
10 
11  This program is free software; you can redistribute it and/or
12  modify it under the terms of the GNU General Public License
13  as published by the Free Software Foundation; either version 2
14  of the License, or (at your option) any later version.
15 
16  This program is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU General Public License for more details.
20 
21  You should have received a copy of the GNU General Public License
22  along with this program; if not, write to the Free Software
23  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24 */
25 
26 
27  /* -----------------------: egnative.c :----------------------
28 
29  These subroutines are used to create the native mesh of ElmerGrid.
30  */
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <math.h>
35 #include <stddef.h>
36 #include <string.h>
37 #include <ctype.h>
38 #include <float.h>
39 #include <stdarg.h>
40 
41 #include "egutils.h"
42 #include "egdef.h"
43 #include "egtypes.h"
44 #include "egnative.h"
45 #include "egmesh.h"
46 
48 
49 #if HAVE_MATC
50 char *mtc_domath(const char *);
51 void mtc_init(FILE * input, FILE * output, FILE * error);
52 #endif
53 
54 
55 void InitGrid(struct GridType *grid)
56 /* Initializes the grid of a specific mesh. A grid can differ
57  between various differential equations.
58  */
59 {
60  int i,j;
61 
62  grid->layered = FALSE;
63  grid->layeredbc = TRUE;
64  grid->triangles = FALSE;
65  grid->triangleangle = 0.0;
66  grid->partitions = FALSE;
67  grid->wantedelems = 0;
68  grid->limitdx = 0.0;
69  grid->limitdxverify = FALSE;
70 
71  grid->dimension = 2;
72  grid->xcells = grid->ycells = grid->zcells = 0;
73  grid->nocells = 0;
74  grid->noknots = grid->noelements = 0;
75  grid->totxelems = grid->totyelems = grid->totzelems = 0;
76  grid->minxelems = grid->minyelems = 1;
77  grid->minzelems = 2;
78  grid->firstmaterial = 1;
79  grid->lastmaterial = MAXMATERIALS;
80  grid->autoratio = 1;
81  grid->xyratio = 1.0;
82  grid->xzratio = 1.0;
83  grid->nonodes = 4;
84  grid->numbering = NUMBER_XY;
85  grid->rotate = FALSE;
86  grid->rotateradius1 = 0.0;
87  grid->rotateradius2 = 0.0;
88  grid->rotateimprove = 1.0;
89  grid->rotateblocks = 4;
90  grid->rotatecartesian = FALSE;
91  grid->reduceordermatmin = 0;
92  grid->reduceordermatmax = 0;
93  grid->polarradius = 1.0;
94  grid->elemorder = 1;
95  grid->elemmidpoints = FALSE;
96 
97  grid->rotatecurve = FALSE;
98  grid->curverad = 0.5;
99  grid->curveangle = 90.0;
100  grid->curvezet = 1.0;
101 
102  for(i=0;i<=MAXCELLS;i++) {
103  grid->xelems[i] = 0;
104  grid->xlinear[i] = TRUE;
105  grid->xratios[i] = 1.;
106  grid->xexpand[i] = 1.;
107  grid->xdens[i] = 1.;
108  grid->x[i] = 0.;
109  }
110  for(i=0;i<=MAXCELLS;i++) {
111  grid->yelems[i] = 0;
112  grid->ylinear[i] = TRUE;
113  grid->yratios[i] = 1.0;
114  grid->yexpand[i] = 1.0;
115  grid->ydens[i] = 1.0;
116  grid->y[i] = 0.;
117  }
118  for(i=0;i<=MAXCELLS;i++) {
119  grid->zelems[i] = 0;
120  grid->zlinear[i] = TRUE;
121  grid->zratios[i] = 1.0;
122  grid->zexpand[i] = 1.0;
123  grid->zdens[i] = 1.0;
124  grid->z[i] = 0.;
125  grid->zfirstmaterial[i] = 1;
126  grid->zlastmaterial[i] = MAXMATERIALS;
127  grid->zmaterial[i] = 0;
128  }
129 
130  /* Initilizes the numbering of the cells. */
131  for(j=0;j<=MAXCELLS+1;j++)
132  for(i=0;i<=MAXCELLS+1;i++)
133  grid->structure[j][i] = MAT_NOTHING;
134 
135  for(j=0;j<=MAXCELLS+1;j++)
136  for(i=0;i<=MAXCELLS+1;i++)
137  grid->numbered[j][i] = 0;
138 
139  grid->noboundaries = 0;
140  for(i=0;i<MAXBOUNDARIES;i++) {
141  grid->boundint[i] = 0;
142  grid->boundext[i] = 0;
143  grid->boundsolid[i] = 0;
144  grid->boundtype[i] = 0;
145  }
146 
147  grid->mappings = 0;
148  for(i=0;i<MAXMAPPINGS;i++) {
149  grid->mappingtype[i] = 0;
150  grid->mappingline[i] = 0;
151  grid->mappinglimits[2*i] = 0;
152  grid->mappinglimits[2*i+1] = 0;
153  grid->mappingpoints[i] = 0;
154  }
155 }
156 
157 
158 static void ExampleGrid1D(struct GridType **grids,int *nogrids,int info)
159 /* Creates an example grid that might be used to analyze
160  flow trough a step. */
161 {
162  int j;
163  struct GridType *grid;
164 
165  (*nogrids) = 1;
166  (*grids) = (struct GridType*)
167  malloc((size_t) (*nogrids)*sizeof(struct GridType));
168 
169  grid = grids[0];
170 
171  InitGrid(grid);
172 
173  grid->nonodes = 2;
174  grid->xcells = 3;
175  grid->ycells = 1;
176  grid->wantedelems = 40;
177  grid->firstmaterial = 1;
178  grid->lastmaterial = 1;
179  grid->autoratio = 1;
180  grid->coordsystem = COORD_CART1;
181  grid->numbering = NUMBER_1D;
182 
183  grid->x[0] = 0.0;
184  grid->x[1] = 1.0;
185  grid->x[2] = 3.0;
186  grid->x[3] = 4.0;
187 
188  grid->xexpand[1] = 2.0;
189  grid->xexpand[3] = 0.5;
190  grid->xdens[2] = 0.5;
191 
192  for(j=1;j<=3;j++)
193  grid->structure[1][j] = 1;
194 
195  grid->noboundaries = 2;
196  grid->boundint[0] = 1;
197  grid->boundint[1] = 1;
198 
199  grid->boundext[0] = -1;
200  grid->boundext[1] = -2;
201 
202  grid->boundtype[0] = 1;
203  grid->boundtype[1] = 2;
204 
205  grid->boundsolid[0] = 1;
206  grid->boundsolid[1] = 1;
207 
208  grid->mappings = 0;
209 
210  if(info) printf("A simple 1D example mesh was created\n");
211 }
212 
213 
214 static void ExampleGrid2D(struct GridType **grids,int *nogrids,int info)
215 /* Creates an example grid that might be used to analyze
216  flow trough a step. */
217 {
218  int j;
219  struct GridType *grid;
220 
221  (*nogrids) = 1;
222  (*grids) = (struct GridType*)
223  malloc((size_t) (*nogrids)*sizeof(struct GridType));
224 
225  grid = grids[0];
226 
227  InitGrid(grid);
228 
229  grid->xcells = 4;
230  grid->ycells = 3;
231  grid->wantedelems = 100;
232  grid->totxelems = grid->totyelems = grid->totzelems = 10;
233  grid->firstmaterial = 1;
234  grid->lastmaterial = 1;
235  grid->autoratio = 1;
236  grid->coordsystem = COORD_CART2;
237  grid->numbering = NUMBER_XY;
238 
239  grid->x[0] = -1.0;
240  grid->x[1] = 0.0;
241  grid->x[2] = 2.0;
242  grid->x[3] = 6.0;
243  grid->x[4] = 7.0;
244 
245  grid->y[0] = 0.0;
246  grid->y[1] = 0.5;
247  grid->y[2] = 0.75;
248  grid->y[3] = 1.0;
249 
250  grid->xexpand[2] = 0.4;
251  grid->xexpand[3] = 5.0;
252 
253  grid->yexpand[2] = 2.0;
254  grid->yexpand[3] = 0.5;
255 
256  for(j=1;j<=3;j++)
257  grid->structure[j][1] = 2;
258  for(j=1;j<=3;j++)
259  grid->structure[j][2] = 1;
260  grid->structure[1][2] = 0;
261  for(j=1;j<=3;j++)
262  grid->structure[j][3] = 1;
263  for(j=1;j<=3;j++)
264  grid->structure[j][4] = 3;
265 
266  grid->noboundaries = 3;
267  grid->boundint[0] = 1;
268  grid->boundint[1] = 1;
269  grid->boundint[2] = 1;
270 
271  grid->boundext[0] = 2;
272  grid->boundext[1] = 3;
273  grid->boundext[2] = 0;
274 
275  grid->boundtype[0] = 1;
276  grid->boundtype[1] = 2;
277  grid->boundtype[2] = 3;
278 
279  grid->boundsolid[0] = 1;
280  grid->boundsolid[1] = 1;
281  grid->boundsolid[2] = 1;
282 
283  grid->mappings = 2;
284  grid->mappingtype[0] = 1;
285  grid->mappingtype[1] = 1;
286  grid->mappingline[0] = 0;
287  grid->mappingline[1] = 3;
288  grid->mappinglimits[0] = grid->mappinglimits[1] = 0.5;
289  grid->mappinglimits[2] = grid->mappinglimits[3] = 0.5;
290  grid->mappingpoints[0] = grid->mappingpoints[1] = 4;
291  grid->mappingparams[0] = Rvector(0,grid->mappingpoints[0]);
292  grid->mappingparams[1] = Rvector(0,grid->mappingpoints[1]);
293  grid->mappingparams[0][0] = 2.0;
294  grid->mappingparams[0][1] = 0.0;
295  grid->mappingparams[0][2] = 6.0;
296  grid->mappingparams[0][3] = -0.2;
297  grid->mappingparams[1][0] = 0.0;
298  grid->mappingparams[1][1] = 0.0;
299  grid->mappingparams[1][2] = 6.0;
300  grid->mappingparams[1][3] = 0.3;
301 
302  if(info) printf("A simple 2D example mesh was created\n");
303 }
304 
305 
306 static void ExampleGrid3D(struct GridType **grids,int *nogrids,int info)
307 /* Creates an example grid that might be used to analyze
308  a simple accelaration sensor. */
309 {
310  int i,j;
311  struct GridType *grid;
312 
313  (*nogrids) = 1;
314  (*grids) = (struct GridType*)
315  malloc((size_t) (*nogrids)*sizeof(struct GridType));
316 
317  grid = grids[0];
318 
319  InitGrid(grid);
320 
321  grid->dimension = 3;
322  grid->coordsystem = COORD_CART3;
323  grid->layered = TRUE;
324 
325  grid->xcells = 4;
326  grid->ycells = 5;
327  grid->zcells = 5;
328 
329  grid->wantedelems = 1000;
330  grid->firstmaterial = 1;
331  grid->lastmaterial = 3;
332  grid->autoratio = 1;
333  grid->coordsystem = COORD_CART3;
334  grid->numbering = NUMBER_XY;
335 
336  grid->x[0] = 0.0;
337  grid->x[1] = 0.1;
338  grid->x[2] = 0.4;
339  grid->x[3] = 0.5;
340  grid->x[4] = 0.6;
341 
342  grid->y[0] = 0.0;
343  grid->y[1] = 0.1;
344  grid->y[2] = 0.2;
345  grid->y[3] = 0.4;
346  grid->y[4] = 0.5;
347  grid->y[5] = 0.6;
348 
349  grid->z[0] = 0.0;
350  grid->z[1] = 0.1;
351  grid->z[2] = 0.2;
352  grid->z[3] = 0.4;
353  grid->z[4] = 0.5;
354  grid->z[5] = 0.6;
355 
356  for(j=1;j<=5;j++)
357  for(i=1;i<=4;i++)
358  grid->structure[j][i] = 1;
359 
360  grid->structure[2][2] = 3;
361  grid->structure[2][3] = 3;
362  grid->structure[3][3] = 3;
363  grid->structure[4][3] = 3;
364  grid->structure[4][2] = 3;
365 
366  grid->structure[3][2] = 2;
367 
368  grid->zlastmaterial[5] = 3;
369  grid->zlastmaterial[2] = 1;
370  grid->zlastmaterial[3] = 2;
371  grid->zlastmaterial[4] = 1;
372  grid->zlastmaterial[5] = 3;
373 
374  grid->zmaterial[1] = 1;
375  grid->zmaterial[2] = 2;
376  grid->zmaterial[3] = 3;
377  grid->zmaterial[4] = 4;
378  grid->zmaterial[5] = 5;
379 
380  grid->noboundaries = 4;
381  grid->boundint[0] = 1;
382  grid->boundint[1] = 1;
383  grid->boundint[2] = 1;
384  grid->boundint[2] = 2;
385 
386  grid->boundext[0] = 0;
387  grid->boundext[1] = 2;
388  grid->boundext[2] = 3;
389  grid->boundext[3] = 3;
390 
391  grid->boundtype[0] = 1;
392  grid->boundtype[1] = 2;
393  grid->boundtype[2] = 3;
394  grid->boundtype[3] = 4;
395 
396  grid->boundsolid[0] = 1;
397  grid->boundsolid[1] = 1;
398  grid->boundsolid[2] = 1;
399  grid->boundsolid[3] = 1;
400 
401  if(info) printf("A simple 3D example mesh was created\n");
402 }
403 
404 
405 void CreateExampleGrid(int dim,struct GridType **grids,int *nogrids,int info)
406 {
407  switch (dim) {
408 
409  case 1:
410  ExampleGrid1D(grids,nogrids,info);
411  break;
412 
413  case 2:
414  ExampleGrid2D(grids,nogrids,info);
415  break;
416 
417  case 3:
418  ExampleGrid3D(grids,nogrids,info);
419  break;
420  }
421 }
422 
423 
424 
425 
426 void SetElementDivision(struct GridType *grid,Real relh,int info)
427 /* Given the densities and ratios in each cell finds the
428  optimum way to devide the mesh into elements.
429  The procedure is the following:
430  For each subcell set the minimum number of elements
431  then add one element at a time till the number of
432  elements is the desired one. The added element
433  is always set to the subcell having the sparsest mesh.
434  Also numbers the cells taking into consideration only
435  materials that have indeces in interval [firstmat,lastmat].
436  */
437 {
438  int i,j,nx,ny,nxmax = 0,nymax = 0;
439  int sumxelems,sumyelems,sumxyelems;
440  int wantedelems,wantedelemsx,wantedelemsy;
441  Real ratio,linearlimit;
442  Real dxmax = 0,dymax = 0,dx = 0,dy = 0,dxlimit = 0;
443 
444  if(0) printf("SetElementDivision\n");
445 
446  if(grid->dimension == 1)
447  grid->numbering = NUMBER_1D;
448 
449  nx = grid->xcells;
450  ny = grid->ycells;
451  linearlimit = 0.001;
452 
453  /* Lets number the cells from left to right and up to down. */
454  grid->nocells = 0;
455  for(j=1;j<=ny;j++)
456  for(i=1;i<=nx;i++) {
457  if (grid->structure[j][i] >= grid->firstmaterial &&
458  grid->structure[j][i] <= grid->lastmaterial)
459  grid->numbered[j][i] = ++grid->nocells;
460  }
461  if(0) printf("The mesh is devided into %d separate subcells.\n",grid->nocells);
462 
463  /* Put the linearity flags. */
464  for(i=1; i<= nx ;i++) {
465  if (fabs(1.-grid->xexpand[i]) < linearlimit)
466  grid->xlinear[i] = TRUE;
467  else if (fabs(1.+grid->xexpand[i]) < linearlimit)
468  grid->xlinear[i] = TRUE;
469  else
470  grid->xlinear[i] = FALSE;
471  }
472 
473  for(i=1; i <= ny ;i++) {
474  if(fabs(1.-grid->yexpand[i]) < linearlimit)
475  grid->ylinear[i] = TRUE;
476  else if(fabs(1.+grid->yexpand[i]) < linearlimit)
477  grid->ylinear[i] = TRUE;
478  else
479  grid->ylinear[i] = FALSE;
480  }
481 
482 
483  /* If there are no materials no elements either.
484  Otherwise at least grid->minelems elments
485  If you want to number elements even if they are
486  not there change this initialization to minelems. */
487  if(grid->autoratio) {
488  for(i=1;i<=nx;i++)
489  grid->xelems[i] = grid->minxelems;
490  for(i=1;i<=ny;i++)
491  grid->yelems[i] = grid->minyelems;
492  }
493  else {
494  for(i=1;i<=nx;i++)
495  if(grid->xelems[i] < grid->minxelems) grid->xelems[i] = grid->minxelems;
496  for(i=1;i<=ny;i++)
497  if(grid->yelems[i] < grid->minyelems) grid->yelems[i] = grid->minyelems;
498  }
499 
500  sumxelems = 0;
501  for(i=1;i<=nx;i++) {
502  if(grid->dimension == 1 && !grid->numbered[1][i]) continue;
503  sumxelems += grid->xelems[i];
504  }
505  sumyelems = 0;
506  for(i=1;i<=ny;i++)
507  sumyelems += grid->yelems[i];
508 
509  if(grid->dimension == 1) {
510  grid->autoratio = 2;
511  grid->totxelems = grid->wantedelems;
512  grid->totyelems = 1;
513  }
514 
515  /* Allocate elements for both axis separately */
516  if(grid->autoratio == 2) {
517 
518  wantedelemsx = (int) (1.0*grid->totxelems / relh);
519  wantedelemsy = (int) (1.0*grid->totyelems / relh);
520 
521  if(sumxelems > wantedelemsx) {
522  printf("SetElementDivision: %d is too few elements in x-direction\n",grid->totxelems);
523  wantedelemsx = sumxelems+1;
524  }
525  if(sumyelems > wantedelemsy ) {
526  printf("SetElementDivision: %d is too few elements in y-direction\n",grid->totyelems);
527  wantedelemsy = sumyelems+1;
528  }
529 
530  for(;sumxelems < wantedelemsx;) {
531  dxmax = 0.0;
532  for(i=1;i<=nx;i++) {
533  if(grid->xelems[i] == 0) continue;
534 
535  /* Don't put elements to passive subcells */
536  if(grid->dimension == 1 && !grid->numbered[1][i]) continue;
537 
538  if(grid->xlinear[i] == TRUE || grid->xelems[i]==1)
539  dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
540  else {
541  if(grid->xexpand[i] > 0.0) {
542  ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));
543  dx = (grid->x[i] - grid->x[i-1]) *
544  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));
545  if(ratio < 1.)
546  dx *= grid->xexpand[i];
547  }
548  else {
549  if(grid->xelems[i]==2) {
550  dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
551  }
552  else if(grid->xelems[i]%2 == 0) {
553  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));
554  dx = 0.5 * (grid->x[i] - grid->x[i-1]) *
555  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));
556  }
557  else if(grid->xelems[i]%2 == 1) {
558  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));
559  dx = (grid->x[i] - grid->x[i-1]) /
560  (2.0*(1.-pow(ratio,(Real)(grid->xelems[i]/2)))/
561  (1-ratio) + pow(ratio,(Real)(grid->xelems[i]/2+0.5)));
562  }
563  }
564  }
565  dx *= grid->xdens[i];
566  if(dx > dxmax) {
567  dxmax = dx;
568  nxmax = i;
569  }
570  }
571  grid->xelems[nxmax] += 1;
572  sumxelems++;
573  }
574 
575 
576  if(grid->dimension > 1) {
577  for(;sumyelems < wantedelemsy;) {
578  dymax = 0.0;
579  for(i=1;i<=ny;i++) {
580  if(grid->yelems[i] == 0) continue;
581  if(grid->ylinear[i] || grid->yelems[i]==1)
582  dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];
583  else {
584  ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1));
585  dy = (grid->y[i] - grid->y[i-1]) *
586  (1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));
587  if(ratio < 1.)
588  dy *= grid->yexpand[i];
589  }
590  dy *= grid->ydens[i];
591  if(dy > dymax) {
592  dymax = dy;
593  nymax = i;
594  }
595  }
596  grid->yelems[nymax] += 1;
597  sumyelems++;
598  }
599  }
600  }
601 
602 
603  /* Both axis dependently */
604  if(grid->autoratio == 1) {
605 
606  wantedelems = (int) (1.0*grid->wantedelems / (relh*relh));
607 
608  sumxyelems = 0;
609  for(;;) {
610  dxmax = 0.0;
611 
612  for(i=1;i<=nx;i++) {
613 
614  if(grid->xelems[i] == 0) continue;
615  if(grid->xlinear[i] || grid->xelems[i]==1)
616  dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
617  else {
618  if(grid->xexpand[i] > 0.0) {
619  ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));
620  dx = (grid->x[i] - grid->x[i-1]) *
621  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));
622  if(ratio < 1.)
623  dx *= grid->xexpand[i];
624  }
625  else if(grid->xelems[i]==2) {
626  dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
627  }
628  else if(grid->xelems[i]%2 == 0) {
629  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));
630  dx = 0.5 * (grid->x[i] - grid->x[i-1]) *
631  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));
632  }
633  else if(grid->xelems[i]%2 == 1) {
634  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));
635  dx = (grid->x[i] - grid->x[i-1]) /
636  (2.0*(1.-pow(ratio,(Real)(grid->xelems[i]/2)))/
637  (1-ratio) + pow(ratio,(Real)(grid->xelems[i]/2+0.5)));
638  }
639  }
640 
641  dx *= grid->xdens[i];
642  if(dx > dxmax) {
643  dxmax = dx;
644  nxmax = i;
645  }
646  }
647 
648 
649  dymax = 0.0;
650  for(i=1;i<=ny;i++) {
651 
652  if(grid->yelems[i] == 0) continue;
653  if(grid->ylinear[i] || grid->yelems[i]==1)
654  dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];
655  else {
656  if(grid->yexpand[i] > 0.0) {
657  ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1));
658  dy = (grid->y[i] - grid->y[i-1]) *
659  (1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));
660  if(ratio < 1.)
661  dy *= grid->yexpand[i];
662  }
663  else if(grid->yelems[i]==2) {
664  dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];
665  }
666  else if(grid->yelems[i]%2 == 0) {
667  ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2-1.));
668  dy = 0.5 * (grid->y[i] - grid->y[i-1]) *
669  (1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2)));
670  }
671  else if(grid->yelems[i]%2 == 1) {
672  ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));
673  dy = (grid->y[i] - grid->y[i-1]) /
674  (2.0*(1.-pow(ratio,(Real)(grid->yelems[i]/2)))/
675  (1-ratio) + pow(ratio,(Real)(grid->yelems[i]/2+0.5)));
676  }
677  }
678  dy *= grid->ydens[i];
679  if(dy > dymax) {
680  dymax = dy;
681  nymax = i;
682  }
683  }
684  dymax /= grid->xyratio;
685 
686  if(dxmax > dymax) {
687  grid->xelems[nxmax] += 1;
688  sumxelems++;
689  dxlimit = dxmax;
690  }
691  else {
692  grid->yelems[nymax] += 1;
693  sumyelems++;
694  dxlimit = dymax;
695  }
696 
697  sumxyelems = 0;
698  for(j=1;j<=grid->ycells;j++)
699  for(i=1;i<=grid->xcells;i++)
700  if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];
701 
702  if(wantedelems <= sumxyelems) break;
703  }
704  }
705 
706 
707 
708  if(grid->autoratio == 3 || grid->limitdxverify) {
709 
710  if(grid->autoratio == 3) {
711  dxlimit = relh * grid->limitdx;
712  dxmax = dymax = dxlimit;
713  }
714 
715  for(i=1;i<=nx;i++) {
716 
717  for(;;) {
718  if(grid->xlinear[i] || grid->xelems[i]==0)
719  dx = (grid->x[i] - grid->x[i-1])/(grid->xelems[i]+1);
720  else {
721  if(grid->xexpand[i] > 0.0) {
722  ratio = pow(grid->xexpand[i],1./grid->xelems[i]);
723  dx = (grid->x[i] - grid->x[i-1]) *
724  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]+1)));
725  if(ratio < 1.)
726  dx *= grid->xexpand[i];
727  }
728  else if(grid->xelems[i]==1) {
729  dx = (grid->x[i] - grid->x[i-1])/(grid->xelems[i]+1);
730  }
731  else if((grid->xelems[i]+1)%2 == 0) {
732  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));
733  dx = 0.5 * (grid->x[i] - grid->x[i-1]) *
734  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2+1)));
735  }
736  else if((grid->xelems[i]+1)%2 == 1) {
737  ratio = pow(-grid->xexpand[i],1./((grid->xelems[i]+1)/2));
738  dx = (grid->x[i] - grid->x[i-1]) /
739  (2.0*(1.-pow(ratio,(Real)((grid->xelems[i]+1)/2)))/
740  (1-ratio) + pow(ratio,(Real)((grid->xelems[i]+1)/2+0.5)));
741  }
742  }
743  dx *= grid->xdens[i];
744 
745  /* choose the best fit for desired density */
746  if(fabs(dx-dxlimit) < fabs( dx*(1+1.0/grid->xelems[i]) -dxlimit) )
747  grid->xelems[i] += 1;
748  else
749  break;
750  }
751  sumxelems += grid->xelems[i];
752  }
753 
754 
755  for(i=1;i<=ny;i++) {
756 
757  for(;;) {
758  if(grid->ylinear[i] || grid->yelems[i]==0)
759  dy = (grid->y[i] - grid->y[i-1])/(grid->yelems[i]+1);
760  else {
761  if(grid->yexpand[i] > 0.0) {
762  ratio = pow(grid->yexpand[i],1./grid->yelems[i]);
763  dy = (grid->y[i] - grid->y[i-1]) *
764  (1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]+1)));
765  if(ratio < 1.)
766  dy *= grid->yexpand[i];
767  }
768  else if(grid->yelems[i]==1) {
769  dy = (grid->y[i] - grid->y[i-1])/(grid->yelems[i]+1);
770  }
771  else if((grid->yelems[i]+1)%2 == 0) {
772  ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));
773  dy = 0.5 * (grid->y[i] - grid->y[i-1]) *
774  (1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2+1)));
775  }
776  else if((grid->yelems[i]+1)%2 == 1) {
777  ratio = pow(-grid->yexpand[i],1./((grid->yelems[i]+1)/2));
778  dy = (grid->y[i] - grid->y[i-1]) /
779  (2.0*(1.-pow(ratio,(Real)((grid->yelems[i]+1)/2)))/
780  (1-ratio) + pow(ratio,(Real)((grid->yelems[i]+1)/2+0.5)));
781  }
782  }
783 
784  dy *= grid->ydens[i] / grid->xyratio;
785  /* choose the best fit for desired density */
786  if(fabs(dy-dxlimit) < fabs( dy*(1+1.0/grid->yelems[i]) -dxlimit) )
787  grid->yelems[i] += 1;
788  else
789  break;
790  }
791  sumyelems += grid->yelems[i];
792  }
793 
794  sumxyelems = 0;
795  for(j=1;j<=grid->ycells;j++)
796  for(i=1;i<=grid->xcells;i++)
797  if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];
798  }
799 
800 
801  /* Put the linearity flags if there is only one division. */
802  for(i=1; i<= nx ;i++)
803  if (grid->xelems[i] == 1)
804  grid->xlinear[i] = TRUE;
805  for(i=1; i <= ny ;i++)
806  if(grid->yelems[i] == 1)
807  grid->ylinear[i] = TRUE;
808 
809 
810  /* Set the size of the first element within each subcell */
811  for(i=1;i<=nx;i++) {
812 
813  if(grid->xlinear[i] == TRUE)
814  grid->dx[i] = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
815  else {
816  if(grid->xexpand[i] > 0.0) {
817  ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));
818  grid->xratios[i] = ratio;
819  grid->dx[i] = (grid->x[i] - grid->x[i-1]) *
820  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));
821  }
822  else if(grid->xelems[i] == 2) {
823  grid->dx[i] = (grid->x[i] - grid->x[i-1])/grid->xelems[i];
824  }
825  else if(grid->xelems[i]%2 == 0) {
826  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));
827  grid->xratios[i] = ratio;
828  grid->dx[i] = 0.5 * (grid->x[i] - grid->x[i-1]) *
829  (1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));
830  }
831  else if(grid->xelems[i]%2 == 1) {
832  ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));
833  grid->xratios[i] = ratio;
834  grid->dx[i] = (grid->x[i] - grid->x[i-1]) /
835  (2.0*(1.-pow(ratio,(Real)(grid->xelems[i]/2)))/
836  (1-ratio) + pow(ratio,(Real)(grid->xelems[i]/2+0.5)));
837  }
838  }
839  }
840 
841  for(i=1;i<=ny;i++) {
842 
843  if(grid->ylinear[i] == TRUE)
844  grid->dy[i] = (grid->y[i] - grid->y[i-1])/grid->yelems[i];
845  else {
846  if(grid->yexpand[i] > 0.0) {
847  ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1.));
848  grid->yratios[i] = ratio;
849  grid->dy[i] = (grid->y[i] - grid->y[i-1]) *
850  (1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));
851  }
852  else if(grid->yelems[i] == 2) {
853  grid->dy[i] = (grid->y[i] - grid->y[i-1])/grid->yelems[i];
854  }
855  else if(grid->yelems[i]%2 == 0) {
856  ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2-1.));
857  grid->yratios[i] = ratio;
858  grid->dy[i] = 0.5 * (grid->y[i] - grid->y[i-1]) *
859  (1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2)));
860  }
861  else if(grid->yelems[i]%2 == 1) {
862  ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));
863  grid->yratios[i] = ratio;
864  grid->dy[i] = (grid->y[i] - grid->y[i-1]) /
865  (2.0*(1.-pow(ratio,(Real)(grid->yelems[i]/2)))/
866  (1-ratio) + pow(ratio,(Real)(grid->yelems[i]/2+0.5)));
867  }
868  }
869  }
870 
871  /* Calculate the total number of elements */
872  sumxyelems = 0;
873  for(j=1;j<=grid->ycells;j++)
874  for(i=1;i<=grid->xcells;i++)
875  if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];
876 
877  grid->noelements = sumxyelems;
878 
879  if(0) printf("Created a total of %d elements\n",sumxyelems);
880 
881  grid->dx0 = dxmax;
882  grid->dy0 = dymax;
883 }
884 
885 
886 
887 
888 void SetCellData(struct GridType *grid,struct CellType *cell,int info)
889 /* Sets the data that can directly be derived from type GridType.
890  */
891 {
892  int i,j,cnew=0;
893 
894  for(j=1;j<= grid->ycells ;j++) /* cells direction up */
895  for(i=1;i<= grid->xcells; i++) /* cells direction right */
896  if( cnew = grid->numbered[j][i] ) { /* if cell is occupied */
897 
898  /* Initialize the numbering to zero */
899  cell[cnew].left1st = 0;
900  cell[cnew].left2nd = 0;
901  cell[cnew].leftlast = 0;
902  cell[cnew].levelwidth = 0;
903  cell[cnew].levelwidthcenter = 0;
904  cell[cnew].leftcenter = 0;
905  cell[cnew].elemwidth = 0;
906  cell[cnew].elem1st = 0;
907 
908  /* Set the element type */
909  cell[cnew].nonodes = grid->nonodes;
910  cell[cnew].numbering = grid->numbering;
911 
912  /* Set the cell coordinates */
913  cell[cnew].xcorner[TOPLEFT] = cell[cnew].xcorner[BOTLEFT] = grid->x[i-1];
914  cell[cnew].xcorner[TOPRIGHT] = cell[cnew].xcorner[BOTRIGHT] = grid->x[i];
915  cell[cnew].ycorner[BOTRIGHT] = cell[cnew].ycorner[BOTLEFT] = grid->y[j-1];
916  cell[cnew].ycorner[TOPRIGHT] = cell[cnew].ycorner[TOPLEFT] = grid->y[j];
917 
918  /* Set the cell width in both directions */
919  cell[cnew].xwidth = grid->x[i] - grid->x[i-1];
920  cell[cnew].ywidth = grid->y[j] - grid->y[j-1];
921 
922  /* Set the number of elements in a subcell */
923  cell[cnew].xelem = grid->xelems[i];
924  cell[cnew].yelem = grid->yelems[j];
925 
926  /* Set the the ratio of elements when going left to right and down to up */
927  cell[cnew].xratio = grid->xratios[i];
928  cell[cnew].yratio = grid->yratios[j];
929  cell[cnew].xlinear = grid->xlinear[i];
930  cell[cnew].ylinear = grid->ylinear[j];
931  cell[cnew].xlinear = grid->xlinear[i];
932  cell[cnew].ylinear = grid->ylinear[j];
933  if(grid->xexpand[i] < 0.0 && grid->xlinear[i] == FALSE) {
934  if(grid->xelems[i] == 2) cell[cnew].xlinear = 1;
935  else cell[cnew].xlinear = 2;
936  }
937  if(grid->yexpand[j] < 0.0 && grid->ylinear[j] == FALSE) {
938  if(grid->yelems[j] == 2) cell[cnew].ylinear = 1;
939  else cell[cnew].ylinear = 2;
940  }
941 
942  /* Set the length of the first element in both directions */
943  cell[cnew].dx1 = grid->dx[i];
944  cell[cnew].dy1 = grid->dy[j];
945 
946  /* Set the material in question */
947  cell[cnew].material = grid->structure[j][i];
948 
949  /* Set the boundary types for sides and corners */
950  cell[cnew].boundary[LEFT] = grid->structure[j][i-1];
951  cell[cnew].boundary[DOWN] = grid->structure[j-1][i];
952  cell[cnew].boundary[RIGHT]= grid->structure[j][i+1];
953  cell[cnew].boundary[UP] = grid->structure[j+1][i];
954  cell[cnew].boundary[4] = grid->structure[j-1][i-1];
955  cell[cnew].boundary[5] = grid->structure[j-1][i+1];
956  cell[cnew].boundary[6] = grid->structure[j+1][i+1];
957  cell[cnew].boundary[7] = grid->structure[j+1][i-1];
958 
959  /* Set the neighbour cell indices for sides and corners */
960  cell[cnew].neighbour[LEFT] = grid->numbered[j][i-1];
961  cell[cnew].neighbour[DOWN] = grid->numbered[j-1][i];
962  cell[cnew].neighbour[RIGHT]= grid->numbered[j][i+1];
963  cell[cnew].neighbour[UP] = grid->numbered[j+1][i];
964  cell[cnew].neighbour[4] = grid->numbered[j-1][i-1];
965  cell[cnew].neighbour[5] = grid->numbered[j-1][i+1];
966  cell[cnew].neighbour[6] = grid->numbered[j+1][i+1];
967  cell[cnew].neighbour[7] = grid->numbered[j+1][i-1];
968  }
969 
970  if(0) printf("%d cells were created.\n",grid->nocells);
971 }
972 
973 
974 
975 int SetCellKnots(struct GridType *grid, struct CellType *cell,int info)
976 /* Uses given mesh to number the knots present in the cells.
977  The knots are numbered independently of the cells from left
978  to right and up to down. Only the numbers of four knots at the
979  left side of each cell are saved for later use. The number of
980  each knot can later be easily recalled using simple functions.
981  The subroutine was initially written for ordering the knots
982  from left to right and down to up. However, this does not always
983  produce reasonably small bandwidth and therefore a numbering
984  scheme for the other order was later added. Therefore the algorithm
985  may not be that clear for this other scheme.
986  Numbers the knots in rectangular elements. There may be
987  4, 5, 8, 9, 12 or 16 nodes in each elements.
988  */
989 {
990  int i,j,level,center;
991  int degree,centernodes,sidenodes,nonodes;
992  int cnew = 0,cup = 0,cleft = 0,cleftup = 0;
993  int elemno,knotno;
995  int xcells,ycells,*yelems,*xelems;
996 
997  numbering = grid->numbering;
998  nonodes = grid->nonodes;
999  knotno = 0;
1000  elemno = 0;
1001 
1002  if(numbering == NUMBER_XY) {
1003  xcells = grid->xcells;
1004  ycells = grid->ycells;
1005  xelems = grid->xelems;
1006  yelems = grid->yelems;
1007  }
1008  else if(numbering == NUMBER_YX) {
1009  xcells = grid->ycells;
1010  ycells = grid->xcells;
1011  xelems = grid->yelems;
1012  yelems = grid->xelems;
1013  }
1014  else {
1015  printf("No %d numbering scheme exists!\n",numbering);
1016  return(1);
1017  }
1018 
1019  switch (nonodes) {
1020  case 4:
1021  centernodes = FALSE;
1022  sidenodes = FALSE;
1023  degree = 1;
1024  break;
1025  case 5:
1026  centernodes = TRUE;
1027  sidenodes = FALSE;
1028  degree = 2;
1029  break;
1030  case 8:
1031  centernodes = FALSE;
1032  sidenodes = TRUE;
1033  degree = 2;
1034  break;
1035  case 9:
1036  centernodes = TRUE;
1037  sidenodes = TRUE;
1038  degree = 2;
1039  break;
1040  case 12:
1041  centernodes = FALSE;
1042  sidenodes = TRUE;
1043  degree = 3;
1044  break;
1045  case 16:
1046  centernodes = TRUE;
1047  sidenodes = TRUE;
1048  degree = 3;
1049  break;
1050  default:
1051  printf("CreateCells: No numbering scheme for %d-node elements.\n",
1052  grid->nonodes);
1053  return(2);
1054  }
1055 
1056  for(j=1;j<= ycells ;j++) /* cells direction up */
1057  for(level=0; level <= yelems[j] ;level++) /* lines inside cells */
1058  for(center=0; center < degree; center++)
1059  for(i=1;i<= xcells; i++) /* cells direction right */
1060  {
1061  if(numbering == NUMBER_XY) {
1062  cnew = grid->numbered[j][i];
1063  cleft= grid->numbered[j][i-1];
1064  cup = grid->numbered[j+1][i];
1065  cleftup = grid->numbered[j+1][i-1];
1066  if(cnew) {
1067  cell[cnew].xind = i;
1068  cell[cnew].yind = j;
1069  }
1070  }
1071  else if(numbering == NUMBER_YX) {
1072  cnew = grid->numbered[i][j];
1073  cleft= grid->numbered[i-1][j];
1074  cup = grid->numbered[i][j+1];
1075  cleftup = grid->numbered[i-1][j+1];
1076  if(cnew) {
1077  cell[cnew].xind = j;
1078  cell[cnew].yind = i;
1079  }
1080  }
1081 
1082  if(center == 0) {
1083  /* the first line of an occupied cell is unnumbered,
1084  this happens only in the bottom */
1085  if (cnew && level==0 && !cell[cnew].left1st) {
1086  if(!cleft) knotno++;
1087  cell[cnew].left1st = knotno;
1088  if(sidenodes)
1089  knotno += degree * xelems[i];
1090  else
1091  knotno += xelems[i];
1092  } /* level=0 */
1093 
1094  /* the n:th line of an occupied cell */
1095  else if (cnew && level > 0 && level < yelems[j]) {
1096  if(!cleft) knotno++;
1097  if(level==1)
1098  cell[cnew].left2nd = knotno;
1099  if(level==2)
1100  cell[cnew].levelwidth = knotno - cell[cnew].left2nd;
1101  if(sidenodes)
1102  knotno += degree * xelems[i];
1103  else
1104  knotno += xelems[i];
1105  } /* 1 <= level < n */
1106 
1107  /* last line of this cell or first line of upper cell */
1108  else if ((cnew || cup) && level == yelems[j]) {
1109  if(!cleft && !cleftup)
1110  knotno++;
1111  if(cnew)
1112  cell[cnew].leftlast = knotno;
1113  if(level==2)
1114  cell[cnew].levelwidth = knotno - cell[cnew].left2nd;
1115  if(yelems[j] == 1)
1116  cell[cnew].left2nd = cell[cnew].leftlast;
1117  if(cup)
1118  cell[cup].left1st = knotno;
1119  if(sidenodes)
1120  knotno += degree * xelems[i];
1121  else
1122  knotno += xelems[i];
1123  } /* level=n */
1124 
1125  /* Number the elements */
1126  if(cnew && level > 0) {
1127  if(level==1)
1128  cell[cnew].elem1st = elemno+1;
1129  if(level==2)
1130  cell[cnew].elemwidth = (elemno+1) - cell[cnew].elem1st;
1131  elemno += xelems[i];
1132  }
1133  }
1134 
1135  if(center && level < yelems[j]) {
1136  if (cnew) {
1137  if(!cleft && sidenodes)
1138  knotno++;
1139  if(level==0 && center==1)
1140  cell[cnew].leftcenter = knotno;
1141  if(level==0 && center==2)
1142  cell[cnew].left2center = knotno;
1143  if(level==1 && center==1)
1144  cell[cnew].levelwidthcenter = knotno - cell[cnew].leftcenter;
1145  if(centernodes && sidenodes)
1146  knotno += degree * xelems[i];
1147  else
1148  knotno += xelems[i];
1149  }
1150  }
1151 
1152  } /* x-cell loop */
1153 
1154 
1155  maxwidth = 0;
1156  for(j=1;j<= ycells ;j++)
1157  for(i=1;i<= xcells; i++) {
1158  if(numbering == NUMBER_XY)
1159  cnew = grid->numbered[j][i];
1160  else if(numbering == NUMBER_YX)
1161  cnew = grid->numbered[i][j];
1162  if(cnew) {
1163  width = cell[cnew].left2nd - cell[cnew].left1st;
1164  if(width > maxwidth)
1165  maxwidth = width;
1166  width = cell[cnew].levelwidth;
1167  if(width > maxwidth)
1168  maxwidth = width;
1169  width = cell[cnew].leftlast-cell[cnew].left2nd
1170  -(yelems[j]-2)*cell[cnew].levelwidth;
1171  if(width > maxwidth)
1172  maxwidth = width;
1173  }
1174  }
1175  maxwidth += 2;
1176 
1177  grid->maxwidth = maxwidth;
1178  grid->noknots = knotno;
1179  grid->noelements = elemno;
1180 
1181  if(info) {
1182  printf("There are %d knots in %d %d-node elements.\n",knotno,elemno,nonodes);
1183  if(numbering == NUMBER_XY)
1184  if(0) printf("Numbering order was <x><y> and max levelwidth %d.\n",
1185  maxwidth);
1186  else if(numbering == NUMBER_YX)
1187  if(0) printf("Numbering order was <y><x> and max levelwidth %d.\n",
1188  maxwidth);
1189  }
1190 
1191  return(0);
1192 }
1193 
1194 
1195 
1196 int SetCellKnots1D(struct GridType *grid, struct CellType *cell,int info)
1197 {
1198  int i;
1199  int degree,nonodes;
1200  int cnew,cleft;
1201  int elemno,knotno;
1202  int maxwidth;
1203  int xcells,*xelems;
1204 
1205  nonodes = grid->nonodes;
1206  knotno = 0;
1207  elemno = 0;
1208 
1209  xcells = grid->xcells;
1210  xelems = grid->xelems;
1211 
1212  switch (nonodes) {
1213  case 2:
1214  degree = 1;
1215  break;
1216  case 3:
1217  degree = 2;
1218  break;
1219  case 4:
1220  degree = 3;
1221  break;
1222 
1223  default:
1224  printf("CreateCells: No numbering scheme for %d-node elements.\n",
1225  grid->nonodes);
1226  return(2);
1227  }
1228 
1229  for(i=1;i<= xcells; i++) {
1230 
1231  cnew = grid->numbered[1][i];
1232  cleft= grid->numbered[1][i-1];
1233  if(cnew) cell[cnew].xind = i;
1234 
1235  if (cnew) {
1236  /* Number the nodes */
1237  if(!cleft) knotno++;
1238  cell[cnew].left1st = knotno;
1239  knotno += degree * xelems[i];
1240 
1241  /* Number the elements */
1242  cell[cnew].elem1st = elemno+1;
1243  elemno += xelems[i];
1244  }
1245  } /* x-cell loop */
1246 
1247  maxwidth = degree;
1248 
1249  grid->maxwidth = maxwidth;
1250  grid->noknots = knotno;
1251  grid->noelements = elemno;
1252 
1253  if(info) {
1254  printf("Numbered %d knots in %d %d-node elements.\n",knotno,elemno,nonodes);
1255  }
1256 
1257  return(0);
1258 }
1259 
1260 
1261 
1262 
1263 int GetKnotIndex(struct CellType *cell,int i,int j)
1264 /* Given the cell and knot indices gives the corresponding
1265  global knot index. The indices are expected to be in the
1266  range [0..n] and [0..m]. Requires only the structure CellType.
1267  */
1268 {
1269  int ind,aid,maxj = 0;
1270 
1271  if(cell->numbering == NUMBER_1D) {
1272  ind = cell->left1st;
1273  if(cell->nonodes == 2)
1274  ind += i;
1275  else if(cell->nonodes == 3)
1276  ind += 2*i;
1277  else if(cell->nonodes == 4)
1278  ind += 3*i;
1279  return(ind);
1280  }
1281 
1282  if(cell->numbering == NUMBER_XY)
1283  maxj = cell->yelem;
1284  else if(cell->numbering == NUMBER_YX) {
1285  aid = j; j = i; i = aid;
1286  maxj = cell->xelem;
1287  }
1288 
1289  if(j == 0)
1290  ind = cell->left1st;
1291  else if (j == maxj)
1292  ind = cell->leftlast;
1293  else
1294  ind = cell->left2nd + (j-1) * cell->levelwidth;
1295 
1296  if(cell->nonodes == 4)
1297  ind += i;
1298  else if(cell->nonodes == 5)
1299  ind += i;
1300  else if(cell->nonodes == 8 || cell->nonodes == 9)
1301  ind += 2*i;
1302  else if(cell->nonodes == 12 || cell->nonodes == 16)
1303  ind += 3*i;
1304 
1305  return(ind);
1306 }
1307 
1308 
1309 int GetKnotCoordinate(struct CellType *cell,int i,int j,Real *x,Real *y)
1310 /* Given the cell and element indices inside the cell gives the
1311  corresponding global knot numbers. The indices are expected
1312  to be in the range [0..n] and [0..m]. Requires only the
1313  structure CellType.
1314  */
1315 {
1316  int ind;
1317 
1318  if(cell->xlinear == 1)
1319  (*x) = cell->xcorner[BOTLEFT] + cell->dx1 * i;
1320  else if(cell->xlinear == 0)
1321  (*x) = cell->xcorner[BOTLEFT] + cell->dx1 *
1322  (1.- pow(cell->xratio,(Real)(i))) / (1.-cell->xratio);
1323  else if(cell->xlinear == 2) {
1324  if(i<=cell->xelem/2) {
1325  (*x) = cell->xcorner[BOTLEFT] + cell->dx1 *
1326  (1.- pow(cell->xratio,(Real)(i))) / (1.-cell->xratio);
1327  }
1328  else {
1329  (*x) = cell->xcorner[BOTRIGHT] - cell->dx1 *
1330  (1.- pow(cell->xratio,(Real)(cell->xelem-i))) / (1.-cell->xratio);
1331  }
1332  }
1333 
1334  if(cell->ylinear == 1)
1335  (*y) = cell->ycorner[BOTLEFT] + cell->dy1 * j;
1336  else if(cell->ylinear == 0)
1337  (*y) = cell->ycorner[BOTLEFT] + cell->dy1 *
1338  (1.- pow(cell->yratio,(Real)(j))) / (1.-cell->yratio);
1339  else if(cell->ylinear == 2) {
1340  if(j<=cell->yelem/2) {
1341  (*y) = cell->ycorner[BOTLEFT] + cell->dy1 *
1342  (1.- pow(cell->yratio,(Real)(j))) / (1.-cell->yratio);
1343  }
1344  else {
1345  (*y) = cell->ycorner[TOPLEFT] - cell->dy1 *
1346  (1.- pow(cell->yratio,(Real)(cell->yelem-j))) / (1.-cell->yratio);
1347  }
1348  }
1349 
1350  ind = GetKnotIndex(cell,i,j);
1351 
1352  return(ind);
1353 }
1354 
1355 
1356 
1357 int GetElementIndices(struct CellType *cell,int i,int j,int *ind)
1358 /* For given element gives the coordinates and index for each knot.
1359  The indices i and j are expected to range from [1..n] and [1..m].
1360  requires only the structure CellType.
1361  */
1362 {
1363  int nonodes,numbering,elemind = 0;
1364 
1365  nonodes = cell->nonodes;
1366  numbering = cell->numbering;
1367 
1368  if(numbering != NUMBER_1D) {
1369  ind[TOPRIGHT] = GetKnotIndex(cell,i,j);
1370  ind[BOTRIGHT] = GetKnotIndex(cell,i,j-1);
1371  ind[TOPLEFT] = GetKnotIndex(cell,i-1,j);
1372  ind[BOTLEFT] = GetKnotIndex(cell,i-1,j-1);
1373  }
1374 
1375  if(numbering == NUMBER_XY) {
1376  elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;
1377  if(nonodes == 4) return(elemind);
1378 
1379  if(nonodes == 5) {
1380  ind[4] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;
1381  }
1382  else if(nonodes == 8) {
1383  ind[4] = ind[0]+1;
1384  ind[6] = ind[3]+1;
1385  ind[5] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;
1386  ind[7] = ind[5]-1;
1387  }
1388  else if(nonodes == 9) {
1389  ind[4] = ind[0]+1;
1390  ind[6] = ind[3]+1;
1391  ind[5] = cell->leftcenter + (j-1) * cell->levelwidthcenter + 2*i;
1392  ind[7] = ind[5]-2;
1393  ind[8] = ind[5]-1;
1394  }
1395  else if(nonodes == 12) {
1396  ind[4] = ind[0]+1;
1397  ind[5] = ind[0]+2;
1398  ind[9] = ind[3]+1;
1399  ind[8] = ind[3]+2;
1400  ind[6] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;
1401  ind[11] = ind[6]-1;
1402  ind[7] = cell->left2center + (j-1) * cell->levelwidthcenter + i;
1403  ind[10] = ind[7]-1;
1404  }
1405  else if(nonodes == 16) {
1406  ind[4] = ind[0]+1;
1407  ind[5] = ind[0]+2;
1408  ind[9] = ind[3]+1;
1409  ind[8] = ind[3]+2;
1410  ind[6] = cell->leftcenter + (j-1) * cell->levelwidthcenter + 3*i;
1411  ind[11] = ind[6]-3;
1412  ind[7] = cell->left2center + (j-1) * cell->levelwidthcenter + 3*i;
1413  ind[10] = ind[7]-3;
1414  ind[13] = ind[6]-1;
1415  ind[12] = ind[6]-2;
1416  ind[14] = ind[7]-1;
1417  ind[15] = ind[7]-2;
1418  }
1419  else
1420  printf("GetElementIndices: not implemented for %d nodes.\n",nonodes);
1421  }
1422 
1423  else if(numbering == NUMBER_YX) {
1424  elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;
1425 
1426  if(nonodes == 4) return(elemind);
1427 
1428  if(nonodes == 5) {
1429  ind[4] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;
1430  }
1431  else if (nonodes==8) {
1432  ind[7] = ind[0]+1;
1433  ind[5] = ind[1]+1;
1434  ind[6] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;
1435  ind[4] = ind[6]-1;
1436  }
1437  else if(nonodes == 9) {
1438  ind[7] = ind[0]+1;
1439  ind[5] = ind[1]+1;
1440  ind[6] = cell->leftcenter + (i-1) * cell->levelwidthcenter + 2*j;
1441  ind[4] = ind[6]-2;
1442  ind[8] = ind[6]-1;
1443  }
1444  else if(nonodes == 12) {
1445  ind[11]= ind[0]+1;
1446  ind[10]= ind[0]+2;
1447  ind[6] = ind[1]+1;
1448  ind[7] = ind[1]+2;
1449  ind[9] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;
1450  ind[4] = ind[9]-1;
1451  ind[8] = cell->left2center + (i-1) * cell->levelwidthcenter + j;
1452  ind[5] = ind[8]-1;
1453  }
1454  else if(nonodes == 16) {
1455  ind[11]= ind[0]+1;
1456  ind[10]= ind[0]+2;
1457  ind[6] = ind[1]+1;
1458  ind[7] = ind[1]+2;
1459  ind[9] = cell->leftcenter + (i-1) * cell->levelwidthcenter + 3*j;
1460  ind[4] = ind[9]-3;
1461  ind[15]= ind[9]-1;
1462  ind[12]= ind[9]-2;
1463  ind[8] = cell->left2center + (i-1) * cell->levelwidthcenter + 3*j;
1464  ind[5] = ind[8]-3;
1465  ind[14]= ind[8]-1;
1466  ind[13]= ind[8]-2;
1467  }
1468  else
1469  printf("GetElementIndices: not implemented for %d nodes.\n",nonodes);
1470  }
1471 
1472  else if(numbering == NUMBER_1D) {
1473  elemind = cell->elem1st+(i-1);
1474  ind[0] = GetKnotIndex(cell,i-1,1);
1475  if(nonodes == 2) {
1476  ind[1] = ind[0] + 1;
1477  }
1478  else if(nonodes == 3) {
1479  ind[2] = ind[0] + 1;
1480  ind[1] = ind[0] + 2;
1481  }
1482  else if(nonodes == 4) {
1483  ind[2] = ind[0] + 1;
1484  ind[3] = ind[0] + 2;
1485  ind[1] = ind[0] + 3;
1486  }
1487  }
1488  return(elemind);
1489 }
1490 
1491 
1492 int GetElementIndex(struct CellType *cell,int i,int j)
1493 /* For given element gives the element index.
1494  The indices i and j are expected to range from [1..n] and [1..m].
1495  requires only the structure CellType.
1496  */
1497 {
1498  int elemind = 0;
1499 
1500  if(cell->numbering == NUMBER_XY)
1501  elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;
1502  else if(cell->numbering == NUMBER_YX)
1503  elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;
1504 
1505  return(elemind);
1506 }
1507 
1508 
1509 
1510 int GetElementCoordinates(struct CellType *cell,int i,int j,
1511  Real *globalcoord,int *ind)
1512 /* For given element gives the coordinates and index for each knot.
1513  The indices i and j are expected to range from [1..n] and [1..m].
1514  requires only the structure CellType
1515  Note that this subroutine assumes that the elements are
1516  rectangular.
1517  */
1518 {
1519  int k,nonodes,numbering,elemind = 0;
1520  Real xrat,yrat;
1521 
1522  k = nonodes = cell->nonodes;
1523  numbering = cell->numbering;
1524 
1525  if(numbering == NUMBER_1D) {
1526  elemind = cell->elem1st+(i-1);
1527  ind[0] = GetKnotCoordinate(cell,i-1,j-1,&globalcoord[0],
1528  &globalcoord[nonodes]);
1529  ind[1] = GetKnotCoordinate(cell,i,j-1,&globalcoord[1],
1530  &globalcoord[nonodes+1]);
1531 
1532  if(nonodes == 3) {
1533  globalcoord[2] = (globalcoord[0]+globalcoord[1])/2.0;
1534  globalcoord[5] = (globalcoord[3]+globalcoord[4])/2.0;
1535  ind[2] = ind[0] + 1;
1536  }
1537  else if(nonodes == 4) {
1538  globalcoord[2] = (2.0*globalcoord[0]+globalcoord[1])/3.0;
1539  globalcoord[6] = (2.0*globalcoord[4]+globalcoord[5])/3.0;
1540  ind[2] = ind[0] + 1;
1541  globalcoord[3] = (globalcoord[0]+2.0*globalcoord[1])/3.0;
1542  globalcoord[7] = (globalcoord[4]+2.0*globalcoord[5])/3.0;
1543  ind[3] = ind[0] + 2;
1544  }
1545 
1546  return(elemind);
1547  }
1548  else if(numbering == NUMBER_XY)
1549  elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;
1550  else if(numbering == NUMBER_YX)
1551  elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;
1552 
1553 
1554  ind[TOPRIGHT] = GetKnotCoordinate(cell,i,j,&globalcoord[TOPRIGHT],
1555  &globalcoord[TOPRIGHT+nonodes]);
1556  ind[BOTRIGHT] = GetKnotCoordinate(cell,i,j-1,&globalcoord[BOTRIGHT],
1557  &globalcoord[BOTRIGHT+nonodes]);
1558  ind[TOPLEFT] = GetKnotCoordinate(cell,i-1,j,&globalcoord[TOPLEFT],
1559  &globalcoord[TOPLEFT+nonodes]);
1560  ind[BOTLEFT] = GetKnotCoordinate(cell,i-1,j-1,&globalcoord[BOTLEFT],
1561  &globalcoord[BOTLEFT+nonodes]);
1562  if(nonodes == 4) return(elemind);
1563 
1564  GetElementIndices(cell,i,j,ind);
1565 
1566 #if 0
1567  if(cell->xlinear)
1568  xrat = 1.0;
1569  else
1570  xrat = sqrt(cell->xratio);
1571 
1572  if(cell->ylinear)
1573  yrat = 1.0;
1574  else
1575  yrat = sqrt(cell->yratio);
1576 #endif
1577  xrat = yrat = 1.0;
1578 
1579  if(nonodes == 5) {
1580  globalcoord[4] = 0.5*(globalcoord[0]+globalcoord[2]);
1581  globalcoord[4+k] = 0.5*(globalcoord[k]+globalcoord[2+k]);
1582  }
1583  else if(nonodes == 8 || nonodes == 9) {
1584  globalcoord[4] = (xrat*globalcoord[0]+globalcoord[1])/(1+xrat);
1585  globalcoord[4+k] = globalcoord[k];
1586  globalcoord[5] = globalcoord[1];
1587  globalcoord[5+k] =
1588  (yrat*globalcoord[1+k]+globalcoord[2+k])/(1+yrat);
1589  globalcoord[6] = globalcoord[4];
1590  globalcoord[6+k] = globalcoord[2+k];
1591  globalcoord[7] = globalcoord[3];
1592  globalcoord[7+k] = globalcoord[5+k];
1593  if(nonodes == 9) {
1594  globalcoord[8] = globalcoord[4];
1595  globalcoord[8+k] = globalcoord[5+k];
1596  }
1597  }
1598  else if(nonodes == 12 || nonodes == 16) {
1599  globalcoord[4] = (2.*globalcoord[0]+globalcoord[1])/3.0;
1600  globalcoord[4+k] = (2.*globalcoord[k]+globalcoord[1+k])/3.0;
1601  globalcoord[5] = (2.*globalcoord[1]+globalcoord[0])/3.0;
1602  globalcoord[5+k] = (2.*globalcoord[1+k]+globalcoord[k])/3.0;
1603  globalcoord[6] = (2.*globalcoord[1]+globalcoord[2])/3.0;
1604  globalcoord[6+k] = (2.*globalcoord[1+k]+globalcoord[2+k])/3.0;
1605  globalcoord[7] = (2.*globalcoord[2]+globalcoord[1])/3.0;
1606  globalcoord[7+k] = (2.*globalcoord[2+k]+globalcoord[1+k])/3.0;
1607  globalcoord[8] = (2.*globalcoord[2]+globalcoord[3])/3.0;
1608  globalcoord[8+k] = (2.*globalcoord[2+k]+globalcoord[3+k])/3.0;
1609  globalcoord[9] = (2.*globalcoord[3]+globalcoord[2])/3.0;
1610  globalcoord[9+k] = (2.*globalcoord[3+k]+globalcoord[2+k])/3.0;
1611  globalcoord[10] = (2.*globalcoord[3]+globalcoord[0])/3.0;
1612  globalcoord[10+k] = (2.*globalcoord[3+k]+globalcoord[k])/3.0;
1613  globalcoord[11] = (2.*globalcoord[0]+globalcoord[3])/3.0;
1614  globalcoord[11+k] = (2.*globalcoord[k]+globalcoord[3+k])/3.0;
1615  if(nonodes == 16) {
1616  globalcoord[12] = (2.*globalcoord[11]+globalcoord[6])/3.0;
1617  globalcoord[12+k] = (2.*globalcoord[11+k]+globalcoord[6+k])/3.0;
1618  globalcoord[13] = (2.*globalcoord[6]+globalcoord[11])/3.0;
1619  globalcoord[13+k] = (2.*globalcoord[6+k]+globalcoord[11+k])/3.0;
1620  globalcoord[14] = (2.*globalcoord[7]+globalcoord[10])/3.0;
1621  globalcoord[14+k] = (2.*globalcoord[7+k]+globalcoord[10+k])/3.0;
1622  globalcoord[15] = (2.*globalcoord[10]+globalcoord[7])/3.0;
1623  globalcoord[15+k] = (2.*globalcoord[10+k]+globalcoord[7+k])/3.0;
1624  }
1625  }
1626 
1627 #if 0
1628  for(i=0;i<k;i++)
1629  printf("ind[%d]=%d x=%.4lg y=%.4lg\n",i,ind[i],
1630  globalcoord[i],globalcoord[i+k]);
1631 #endif
1632 
1633  return(elemind);
1634 }
1635 
1636 
1637 int GetSideInfo(struct CellType *cell,int cellno,int side,int element,
1638  int *elemind)
1639 /* Given the side and element numbers returns the indices of
1640  the side element. When the end of the side is reached the function
1641  returns FALSE, otherwise TRUE.
1642  */
1643 {
1644  int more,sideno;
1645  int ind[MAXNODESD2];
1646 
1647  more = TRUE;
1648 
1649  if(cell[cellno].numbering == NUMBER_1D) {
1650 
1651  switch(side) {
1652  case 0:
1653  more = FALSE;
1654  elemind[0] = GetElementIndices(&(cell[cellno]),1,element,&(ind[0]));
1655  if(sideno = cell[cellno].neighbour[LEFT])
1656  elemind[1] = GetElementIndices(&(cell[sideno]),cell[sideno].xelem,element,&(ind[0]));
1657  else
1658  elemind[1] = 0;
1659  break;
1660 
1661 
1662  case 1:
1663  more = FALSE;
1664  elemind[0] = GetElementIndices(&(cell)[cellno],cell[cellno].xelem,element,&(ind[0]));
1665  if(sideno = cell[cellno].neighbour[RIGHT])
1666  elemind[1] = GetElementIndices(&(cell[sideno]),1,element,&(ind[0]));
1667  else
1668  elemind[1] = 0;
1669  break;
1670  }
1671 
1672  return(more);
1673  }
1674 
1675 
1676  switch(side) {
1677 
1678  case LEFT:
1679  if(element == cell[cellno].yelem) more = FALSE;
1680  elemind[0] = GetElementIndices(&(cell[cellno]),1,element,&(ind[0]));
1681  if(sideno = cell[cellno].neighbour[LEFT])
1682  elemind[1] = GetElementIndices(&(cell[sideno]),cell[sideno].xelem,element,&(ind[0]));
1683  else
1684  elemind[1] = 0;
1685  break;
1686 
1687  case RIGHT:
1688  if(element == cell[cellno].yelem) more = FALSE;
1689  elemind[0] = GetElementIndices(&(cell)[cellno],cell[cellno].xelem,element,&(ind[0]));
1690  if(sideno = cell[cellno].neighbour[RIGHT])
1691  elemind[1] = GetElementIndices(&(cell[sideno]),1,element,&(ind[0]));
1692  else
1693  elemind[1] = 0;
1694  break;
1695 
1696  case DOWN:
1697  if(element == cell[cellno].xelem) more = FALSE;
1698  elemind[0] = GetElementIndices(&(cell)[cellno],element,1,&(ind[0]));
1699  if(sideno = cell[cellno].neighbour[DOWN])
1700  elemind[1] = GetElementIndices(&(cell[sideno]),element,cell[sideno].yelem,&(ind[0]));
1701  else
1702  elemind[1] = 0;
1703  break;
1704 
1705  case UP:
1706  if(element == cell[cellno].xelem) more = FALSE;
1707  elemind[0] = GetElementIndices(&(cell)[cellno],element,cell[cellno].yelem,&(ind[0]));
1708  if(sideno = cell[cellno].neighbour[UP])
1709  elemind[1] = GetElementIndices(&(cell[sideno]),element,1,&(ind[0]));
1710  else
1711  elemind[1] = 0;
1712  break;
1713 
1714  default:
1715  printf("Impossible option in GetSideInfo.\n");
1716  }
1717 
1718  return(more);
1719 }
1720 
1721 
1722 
1724 {
1725  int i,nzmax = 0,sumzelems;
1726  Real ratio,linearlimit;
1727  Real dzmax = 0,dz = 0;
1728 
1729  linearlimit = 0.001;
1730 
1731  if(grid->autoratio) {
1732  for(i=1;i<=grid->zcells;i++)
1733  grid->zelems[i] = grid->minzelems;
1734  }
1735  else {
1736  for(i=1;i<=grid->zcells;i++)
1737  if(grid->zelems[i] < grid->minzelems) grid->zelems[i] = grid->minzelems;
1738  }
1739 
1740  sumzelems = grid->zcells * grid->minzelems;
1741  if(sumzelems > grid->totzelems) {
1742 #if 0
1743  printf("SetElementDivision: %d is too few elements in z-direction (min. %d)\n",
1744  grid->totzelems,sumzelems);
1745 #endif
1746  grid->totzelems = sumzelems;
1747  }
1748 
1749  /* Put the linearity flags. */
1750  for(i=1; i<= grid->zcells ;i++) {
1751  if (fabs(1.-grid->zexpand[i]) < linearlimit)
1752  grid->zlinear[i] = TRUE;
1753  else
1754  grid->zlinear[i] = FALSE;
1755  }
1756 
1757  if(grid->autoratio) {
1758  int active;
1759  for(;;) {
1760  dzmax = 0.0;
1761  active = FALSE;
1762 
1763  for(i=1;i<=grid->zcells;i++) {
1764  if(grid->zelems[i] == 0) continue;
1765  if(grid->zlinear[i] == TRUE)
1766  dz = (grid->z[i] - grid->z[i-1])/(grid->zelems[i]+1);
1767  else {
1768  if(grid->zexpand[i] > 0.0) {
1769  ratio = pow(grid->zexpand[i],1./(1.*grid->zelems[i]));
1770  dz = (grid->z[i] - grid->z[i-1]) *
1771  (1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]+1)));
1772  if(ratio < 1.)
1773  dz *= grid->zexpand[i];
1774  }
1775  else if(grid->zelems[i]==1) {
1776  dz = (grid->z[i] - grid->z[i-1])/(grid->zelems[i]+1);
1777  }
1778  else if((grid->zelems[i]+1)%2 == 0) {
1779  ratio = pow(-grid->zexpand[i],1./((grid->zelems[i]+1)/2-1.));
1780  dz = 0.5 * (grid->z[i] - grid->z[i-1]) *
1781  (1.-ratio) / (1.-pow(ratio,(Real)((grid->zelems[i]+1)/2)));
1782  }
1783  else if((grid->zelems[i]+1)%2 == 1) {
1784  ratio = pow(-grid->zexpand[i],1./((grid->zelems[i]+1)/2));
1785  dz = (grid->z[i] - grid->z[i-1]) /
1786  (2.0*(1.-pow(ratio,(Real)((grid->zelems[i]+1)/2)))/
1787  (1-ratio) + pow(ratio,(Real)((grid->zelems[i]+1)/2+0.5)));
1788  }
1789  }
1790  dz *= grid->zdens[i] / grid->xzratio;
1791 
1792  if(dz > dzmax) {
1793  dzmax = dz;
1794  nzmax = i;
1795  }
1796 
1797  if(grid->autoratio) {
1798  if(fabs(dz - grid->dx0) < fabs( dz*(1.0/(1.0-1.0/grid->zelems[i])) - grid->dx0) ) {
1799  grid->zelems[i] += 1;
1800  sumzelems++;
1801  active = TRUE;
1802  }
1803  }
1804  }
1805 
1806  if(grid->autoratio) {
1807  if(!active) break;
1808  }
1809  else {
1810  grid->zelems[nzmax] += 1;
1811  sumzelems++;
1812  if(sumzelems >= grid->totzelems) break;
1813  }
1814  }
1815  }
1816 
1817  /* Set the size of the first element within each subcell */
1818  grid->totzelems = 0;
1819  for(i=1;i<=grid->zcells;i++) {
1820  grid->totzelems += grid->zelems[i];
1821  if(grid->zlinear[i] == TRUE || grid->zelems[i]==1)
1822  grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];
1823  else if(grid->zexpand[i] > 0.0) {
1824  ratio = pow(grid->zexpand[i],1./(grid->zelems[i]-1.));
1825  grid->zratios[i] = ratio;
1826  grid->dz[i] = (grid->z[i] - grid->z[i-1]) *
1827  (1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i])));
1828  }
1829  else if(grid->zelems[i] == 2) {
1830  grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];
1831  }
1832  else if(grid->zelems[i]%2 == 0) {
1833  ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2-1.));
1834  grid->zratios[i] = ratio;
1835  grid->dz[i] = 0.5 * (grid->z[i] - grid->z[i-1]) *
1836  (1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]/2)));
1837  }
1838  else if(grid->zelems[i]%2 == 1) {
1839  ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2));
1840  grid->zratios[i] = ratio;
1841  grid->dz[i] = (grid->z[i] - grid->z[i-1]) /
1842  (2.0*(1.-pow(ratio,(Real)(grid->zelems[i]/2)))/
1843  (1-ratio) + pow(ratio,(Real)(grid->zelems[i]/2+0.5)));
1844  }
1845  }
1846 
1847  if(info) printf("Created %d extruded divisions.\n",
1848  grid->totzelems);
1849  grid->dz0 = dzmax;
1850 }
1851 
1852 
1853 
1855 {
1856  int i,k;
1857  Real ratio,eps;
1858  Real dzmax;
1859 
1860  eps = 1.0e-8;
1861 
1862  grid->zcells = 2*grid->rotateblocks;
1863  grid->z[0] = 0.0;
1864  for(i=0;grid->x[i]<eps;i++); k=i;
1865  grid->rotateradius1 = grid->x[k];
1866 
1867  if(grid->rotateradius2 < 0.0) {
1868  grid->rotatecartesian = TRUE;
1869  grid->rotateradius2 = 1.0e6;
1870  }
1871  if(grid->rotateradius2 <= sqrt(2.0)*grid->rotateradius1) {
1872  if(k+1 <= grid->xcells)
1873  grid->rotateradius2 = grid->x[k+1];
1874  grid->rotateradius2 = MAX(sqrt(2.0)*grid->rotateradius1,
1875  grid->rotateradius2);
1876  }
1877 
1878  if(!grid->xlinear[k])
1879  printf("SetElementDivisionCylinder: The division must be linear!\n");
1880 
1881  for(i=1;i<=grid->zcells;i++) {
1882  grid->z[i] = i*(2.0*FM_PI)/8.0;
1883  grid->zelems[i] = grid->xelems[k];
1884  grid->zlinear[i] = grid->xlinear[k];
1885  grid->zratios[i] = grid->xratios[k];
1886  grid->zexpand[i] = grid->xexpand[k];
1887  grid->zmaterial[i] = 0;
1888  }
1889 
1890  grid->totzelems = grid->zcells * grid->xelems[k];
1891 
1892  dzmax = 0.0;
1893  for(i=1;i<=grid->zcells;i++) {
1894  if(grid->zlinear[i] == TRUE || grid->zelems[i]==1)
1895  grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];
1896  else if(grid->zexpand[i] > 0.0) {
1897  ratio = pow(grid->zexpand[i],1./(grid->zelems[i]-1.));
1898  grid->zratios[i] = ratio;
1899  grid->dz[i] = (grid->z[i] - grid->z[i-1]) *
1900  (1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i])));
1901  }
1902  else if(grid->zelems[i] == 2) {
1903  grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];
1904  }
1905  else if(grid->zelems[i]%2 == 0) {
1906  ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2-1.));
1907  grid->zratios[i] = ratio;
1908  grid->dz[i] = 0.5 * (grid->z[i] - grid->z[i-1]) *
1909  (1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]/2)));
1910  }
1911  else if(grid->zelems[i]%2 == 1) {
1912  ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2));
1913  grid->zratios[i] = ratio;
1914  grid->dz[i] = (grid->z[i] - grid->z[i-1]) /
1915  (2.0*(1.-pow(ratio,(Real)(grid->zelems[i]/2)))/
1916  (1-ratio) + pow(ratio,(Real)(grid->zelems[i]/2+0.5)));
1917  }
1918 
1919  if(dzmax < grid->dz[i]) dzmax = grid->dz[i];
1920  }
1921 
1922  if(info) printf("Created %d divisions in %d cells for rotation [%.2lg %.2lg].\n",
1923  grid->totzelems,grid->zcells,
1924  grid->rotateradius1,grid->rotateradius2);
1925  grid->dz0 = dzmax;
1926 }
1927 
1928 
1929 
1930 static int Getline(char *line1,FILE *io)
1931 {
1932  int i,isend;
1933  char line0[MAXLINESIZE],*charend;
1934 
1935  for(i=0;i<MAXLINESIZE;i++)
1936  line0[i] = ' ';
1937 
1938  newline:
1939 
1940  charend = fgets(line0,MAXLINESIZE,io);
1941  isend = (charend == NULL);
1942 
1943  if(isend) return(1);
1944 
1945  if(line0[0] == '#' || line0[0] == '%' || line0[0] == '!') goto newline;
1946  if(!matcactive && line0[0] == '*') goto newline;
1947 
1948 #if HAVE_MATC
1949  if(matcactive) {
1950  matcpntr0 = strchr(line0,'$');
1951  if(matcpntr0) {
1952  matcpntr = mtc_domath(&matcpntr0[1]);
1953  if(matcpntr) {
1954  strcpy(matcpntr0, matcpntr);
1955  if(0) printf("A: %s\n%s\n",matcpntr0,matcpntr);
1956  }
1957  }
1958  }
1959 #endif
1960 
1961  if(strstr(line0,"subcell boundaries")) goto newline;
1962  if(strstr(line0,"material structure")) goto newline;
1963  if(strstr(line0,"mode")) goto newline;
1964  if(strstr(line0,"type")) goto newline;
1965 
1966  for(i=0;i<MAXLINESIZE;i++)
1967  line1[i] = toupper(line0[i]);
1968 
1969  return(0);
1970 }
1971 
1972 
1973 static int GetCommand(char *line1,char *line2,FILE *io)
1974 {
1975  int i,j,isend,empty;
1976  char line0[MAXLINESIZE],*charend;
1977 
1978  newline:
1979 
1980  for(i=0;i<MAXLINESIZE;i++)
1981  line2[i] = line1[i] = line0[i] = ' ';
1982 
1983  charend = fgets(line0,MAXLINESIZE,io);
1984  isend = (charend == NULL);
1985 
1986  if(isend) return(1);
1987 
1988  if(line0[0] == '#' || line0[0] == '%' || line0[0] == '!' || line0[0] == '\n' || line0[1] == '\n') goto newline;
1989  if(!matcactive && line0[0] == '*') goto newline;
1990 
1991  empty = TRUE;
1992  for(i=1;i<20;i++) if(line0[i] != ' ') empty = FALSE;
1993  if(empty) goto newline;
1994 
1995 #if HAVE_MATC
1996  if(matcactive) {
1997  matcpntr0 = strchr(line0,'$');
1998  if(matcpntr0) {
1999  matcpntr = mtc_domath(&matcpntr0[1]);
2000  if(matcpntr) {
2001  strcpy(matcpntr0, matcpntr);
2002  if(0) printf("B: %s\n%s\n",matcpntr0,matcpntr);
2003  }
2004  else {
2005  if(0) printf("B0: %s\n",matcpntr0);
2006  goto newline;
2007  }
2008  }
2009  }
2010 #endif
2011 
2012  j = 0;
2013  for(i=0;i<MAXLINESIZE;i++) {
2014  if(line0[i] == '=') {
2015  j = i;
2016  break;
2017  }
2018  line1[i] = toupper(line0[i]);
2019  }
2020 
2021  /* After these commands there will be no nextline even though there is no equality sign */
2022  if(strstr(line1,"END")) return(0);
2023  if(strstr(line1,"NEW MESH")) return(0);
2024 
2025 
2026  if(j) {
2027  for(i=j+1;i<MAXLINESIZE;i++)
2028  line2[i-j-1] = line0[i];
2029  }
2030  else {
2031  newline2:
2032  charend = fgets(line2,MAXLINESIZE,io);
2033  isend = (charend == NULL);
2034  if(isend) return(2);
2035  if(line2[0] == '#' || line2[0] == '%' || line2[0] == '!') goto newline2;
2036  if(!matcactive && line2[0] == '*') goto newline2;
2037 
2038 #if HAVE_MATC
2039  if(matcactive) {
2040  matcpntr0 = strchr(line2,'$');
2041  if(matcpntr0) {
2042  matcpntr = mtc_domath(&matcpntr0[1]);
2043  if(matcpntr) {
2044  strcpy(matcpntr0, matcpntr);
2045  if(0) printf("C: %s\n%s\n",matcpntr0,matcpntr);
2046  }
2047  }
2048  }
2049 #endif
2050  }
2051 
2052  return(0);
2053 }
2054 
2055 
2056 
2057 
2058 
2059 int SaveElmergrid(struct GridType *grid,int nogrids,char *prefix,int info)
2060 {
2061  int sameline,maxsameline;
2062  int i,j,dim;
2063  FILE *out;
2064  char filename[MAXFILESIZE];
2065 
2066  AddExtension(prefix,filename,"grd");
2067  out = fopen(filename,"w");
2068  dim = grid->dimension;
2069  if(grid->coordsystem == COORD_CART1) dim = 1;
2070 
2071  j = 0;
2072  sameline = TRUE;
2073  maxsameline = 6;
2074  if(grid->xcells > maxsameline) sameline = FALSE;
2075  if(dim >= 2 && grid->ycells > maxsameline) sameline = FALSE;
2076  if(dim >= 3 && grid->zcells > maxsameline) sameline = FALSE;
2077 
2078  fprintf(out,"##### ElmerGrid input file for structured grid generation ######\n");
2079  fprintf(out,"Version = 210903\n");
2080 
2081  fprintf(out,"Coordinate System = ");
2082  if(grid->coordsystem == COORD_AXIS)
2083  fprintf(out,"2D Axisymmetric\n");
2084  else if(grid->coordsystem == COORD_POLAR)
2085  fprintf(out,"2D Polar\n");
2086  else
2087  fprintf(out,"Cartesian %dD\n",dim);
2088 
2089  fprintf(out,"Subcell Divisions in %dD = ",dim);
2090  if(dim >= 1) fprintf(out,"%d ",grid->xcells);
2091  if(dim >= 2) fprintf(out,"%d ",grid->ycells);
2092  if(dim >= 3) fprintf(out,"%d ",grid->zcells);
2093  fprintf(out,"\n");
2094 
2095  fprintf(out,"Subcell Limits 1 %s",sameline ? "= ":"\n ");
2096  for(i=0;i <= grid->xcells;i++)
2097  fprintf(out,"%.5lg ",grid->x[i]);
2098  fprintf(out,"\n");
2099 
2100  if(dim >= 2) {
2101  fprintf(out,"Subcell Limits 2 %s",sameline ? "= ":"\n ");
2102  for(i=0;i <= grid->ycells;i++)
2103  fprintf(out,"%.5lg ",grid->y[i]);
2104  fprintf(out,"\n");
2105  }
2106 
2107  if(dim >= 3) {
2108  fprintf(out,"Subcell Limits 3 %s",sameline ? "= ":"\n ");
2109  for(i=0;i <= grid->zcells;i++)
2110  fprintf(out,"%.5lg ",grid->z[i]);
2111  fprintf(out,"\n");
2112  }
2113 
2114  fprintf(out,"Material Structure in %dD\n",dim==1 ? 1:2);
2115  for(j=grid->ycells;j>=1;j--) {
2116  fprintf(out," ");
2117  for(i=1;i<=grid->xcells;i++)
2118  fprintf(out,"%-5d",grid->structure[j][i]);
2119  fprintf(out,"\n");
2120  }
2121  fprintf(out,"End\n");
2122 
2123  if(grid->mappings > 0) {
2124  fprintf(out,"Geometry Mappings\n");
2125  fprintf(out,"# mode line limits(2) Np params(Np)\n");
2126  for(i=0;i<grid->mappings;i++) {
2127  fprintf(out," %-5d %-5d %-7.5lg %-7.5lg %-3d ",
2128  grid->mappingtype[i],grid->mappingline[i],
2129  grid->mappinglimits[2*i],grid->mappinglimits[2*i+1],
2130  grid->mappingpoints[i]);
2131  for(j=0;j<grid->mappingpoints[i];j++)
2132  fprintf(out,"%.4lg ",grid->mappingparams[i][j]);
2133  fprintf(out,"\n");
2134  }
2135  fprintf(out,"End\n");
2136  }
2137 
2138  j = 0;
2139  if(grid[j].rotate) {
2140  fprintf(out,"Revolve Blocks = %d\n",grid[j].rotateblocks);
2141  fprintf(out,"Revolve Radius = %-8.3lg\n",grid[j].rotateradius2);
2142  if(fabs(grid[j].rotateimprove-1.0) > 1.0e-10)
2143  fprintf(out,"Revolve Improve = %-8.3lg\n",grid[j].rotateimprove);
2144 
2145  }
2146  if(grid[j].rotatecurve) {
2147  fprintf(out,"Revolve Curve Direct = %-8.3lg\n",grid[j].curvezet);
2148  fprintf(out,"Revolve Curve Radius = %-8.3lg\n",grid[j].curverad);
2149  fprintf(out,"Revolve Curve Angle = %-8.3lg\n",grid[j].curveangle);
2150  }
2151 
2152  if(grid[j].coordsystem == COORD_POLAR) {
2153  fprintf(out,"Polar Radius = %.3lg\n",grid[j].polarradius);
2154  }
2155 
2156  for(j=0;j<nogrids;j++) {
2157 
2158  if(j>0) fprintf(out,"\nStart New Mesh\n");
2159 
2160  fprintf(out,"Materials Interval = %d %d\n",
2161  grid[j].firstmaterial,grid[j].lastmaterial);
2162 
2163  if(dim == 3) {
2164  fprintf(out,"Extruded Structure\n");
2165  fprintf(out,"# %-8s %-8s %-8s\n","1stmat", "lastmat","newmat");
2166  for(i=1;i<=grid[j].zcells;i++)
2167  fprintf(out," %-8d %-8d %-8d\n",
2168  grid[j].zfirstmaterial[i],grid[j].zlastmaterial[i],
2169  grid[j].zmaterial[i]);
2170  fprintf(out,"End\n");
2171  }
2172 
2173  if(grid[j].noboundaries > 0) {
2174  fprintf(out,"Boundary Definitions\n");
2175  fprintf(out,"# %-8s %-8s %-8s\n","type","out","int");
2176  for(i=0;i<grid[j].noboundaries;i++)
2177  fprintf(out," %-8d %-8d %-8d %-8d\n",
2178  grid[j].boundtype[i],grid[j].boundext[i],
2179  grid[j].boundint[i], grid[j].boundsolid[i]);
2180  fprintf(out,"End\n");
2181  }
2182 
2183  if(grid->numbering == NUMBER_XY)
2184  fprintf(out,"Numbering = Horizontal\n");
2185  if(grid->numbering == NUMBER_YX)
2186  fprintf(out,"Numbering = Vertical\n");
2187 
2188  fprintf(out,"Element Degree = %d\n",grid[j].elemorder);
2189  fprintf(out,"Element Innernodes = %s\n",grid[j].elemmidpoints ? "True" : "False");
2190  fprintf(out,"Triangles = %s\n",grid[j].triangles ? "True" : "False");
2191  if(grid[j].autoratio)
2192  fprintf(out,"Surface Elements = %d\n",grid[j].wantedelems);
2193  if(dim == 2)
2194  fprintf(out,"Coordinate Ratios = %-8.3lg\n",grid[j].xyratio);
2195  if(dim == 3)
2196  fprintf(out,"Coordinate Ratios = %-8.3lg %-8.3lg\n",
2197  grid[j].xyratio,grid[j].xzratio);
2198 
2199  fprintf(out,"Minimum Element Divisions = %d",grid[j].minxelems);
2200  if(dim >= 2) fprintf(out," %d",grid[j].minyelems);
2201  if(dim >= 3) fprintf(out," %d",grid[j].minzelems);
2202  fprintf(out,"\n");
2203 
2204  fprintf(out,"Element Ratios 1 %s",sameline ? "= ":"\n ");
2205  for(i=1;i<=grid[j].xcells;i++)
2206  fprintf(out,"%.3lg ",grid[j].xexpand[i]);
2207  fprintf(out,"\n");
2208  if(dim >= 2) {
2209  fprintf(out,"Element Ratios 2 %s",sameline ? "= ":"\n ");
2210  for(i=1;i<=grid[j].ycells;i++)
2211  fprintf(out,"%.3lg ",grid[j].yexpand[i]);
2212  fprintf(out,"\n");
2213  }
2214  if(dim >= 3) {
2215  fprintf(out,"Element Ratios 3 %s",sameline ? "= ":"\n ");
2216  for(i=1;i<=grid[j].zcells;i++)
2217  fprintf(out,"%.3lg ",grid[j].zexpand[i]);
2218  fprintf(out,"\n");
2219  }
2220 
2221  if(grid[j].autoratio) {
2222  fprintf(out,"Element Densities 1 %s",sameline ? "= ":"\n ");
2223  for(i=1;i<=grid[j].xcells;i++)
2224  fprintf(out,"%.3lg ",grid[j].xdens[i]);
2225  fprintf(out,"\n");
2226  if(dim >= 2) {
2227  fprintf(out,"Element Densities 2 %s",sameline ? "= ":"\n ");
2228  for(i=1;i<=grid[j].ycells;i++)
2229  fprintf(out,"%.3lg ",grid[j].ydens[i]);
2230  fprintf(out,"\n");
2231  }
2232  if(dim >= 3) {
2233  fprintf(out,"Element Densities 3 %s",sameline ? "= ":"\n ");
2234  for(i=1;i<=grid[j].zcells;i++)
2235  fprintf(out,"%.3lg ",grid[j].zdens[i]);
2236  fprintf(out,"\n");
2237  }
2238  }
2239  else {
2240  fprintf(out,"Element Divisions 1 %s",sameline ? "= ":"\n ");
2241  for(i=1;i<=grid[j].xcells;i++)
2242  fprintf(out,"%d ",grid[j].xelems[i]);
2243  fprintf(out,"\n");
2244  if(dim >= 2) {
2245  fprintf(out,"Element Divisions 2 %s",sameline ? "= ":"\n ");
2246  for(i=1;i<=grid[j].ycells;i++)
2247  fprintf(out,"%d ",grid[j].yelems[i]);
2248  fprintf(out,"\n");
2249  }
2250  if(dim >= 3) {
2251  fprintf(out,"Element Divisions 3 %s",sameline ? "= ":"\n ");
2252  for(i=1;i<=grid[j].zcells;i++)
2253  fprintf(out,"%d ",grid[j].zelems[i]);
2254  fprintf(out,"\n");
2255  }
2256  }
2257 
2258 
2259  }
2260 
2261  if(info) printf("The Elmergrid input was saved to file %s.\n",filename);
2262  fclose(out);
2263 
2264  return(0);
2265 }
2266 
2267 
2268 
2269 
2270 
2271 int LoadElmergrid(struct GridType **grid,int *nogrids,char *prefix,int info)
2272 {
2273  char filename[MAXFILESIZE];
2274  char command[MAXLINESIZE],params[MAXLINESIZE];
2275  FILE *in;
2276  int i,j,k,error=0;
2277  char *cp;
2278  int noknots,noelements,dim,axisymmetric;
2279  int elemcode,maxnodes,totelems,nogrids0,minmat,maxmat;
2280  long code;
2281  Real raid;
2282 
2283  AddExtension(prefix,filename,"grd");
2284  if ((in = fopen(filename,"r")) == NULL) {
2285  printf("LoadElmergrid: opening of the file '%s' wasn't succesfull !\n",filename);
2286  return(1);
2287  }
2288 
2289  if(info) printf("Loading the geometry from file '%s'.\n",filename);
2290 
2291  InitGrid(grid[*nogrids]);
2292  k = *nogrids;
2293  nogrids0 = *nogrids;
2294 
2295  noknots = 0;
2296  noelements = 0;
2297  dim = 0;
2298  axisymmetric = FALSE;
2299  elemcode = 0;
2300  maxnodes = 4;
2301  totelems = 0;
2302 
2303  matcactive = FALSE;
2304 
2305  for(;;) {
2306  if(GetCommand(command,params,in)) {
2307  if(0) printf("Reached the end of command file\n");
2308  goto end;
2309  }
2310 
2311  /* Control information */
2312  if(strstr(command,"VERSION")) {
2313  sscanf(params,"%ld",&code);
2314  if(code == 210903) {
2315  if(info) printf("Loading ElmerGrid file version: %d\n", (int)code);
2316  }
2317  else {
2318  printf("Unknown ElmerGrid file version: %d\n", (int)code);
2319  return(2);
2320  }
2321  *nogrids += 1;
2322  }
2323 
2324  else if(strstr(command,"MATC")) {
2325  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2326  if(strstr(params,"FALSE"))
2327  matcactive = FALSE;
2328  else {
2329 #if HAVE_MATC
2330  matcactive = TRUE;
2331  mtc_init(NULL, stdout, stderr);
2332  strcpy(command, "format( 12 )");
2333  mtc_domath(command);
2334  if(info) printf("MATC language activated with 12 digit accuracy.\n");
2335 #else
2336  printf("This version was compiled without MATC library.\n");
2337 #endif
2338  }
2339  }
2340 
2341 
2342  else if(strstr(command,"COORDINATE SYSTEM")) {
2343  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2344  grid[k]->dimension = 2;
2345  if(strstr(params,"CARTESIAN 1D")) {
2346  grid[k]->coordsystem = COORD_CART1;
2347  grid[k]->dimension = 1;
2348  }
2349  else if(strstr(params,"CARTESIAN 2D"))
2350  grid[k]->coordsystem = COORD_CART2;
2351  else if(strstr(params,"AXISYMMETRIC"))
2352  grid[k]->coordsystem = COORD_AXIS;
2353  else if(strstr(params,"POLAR"))
2354  grid[k]->coordsystem = COORD_POLAR;
2355  else if(strstr(params,"CARTESIAN 3D")) {
2356  grid[k]->coordsystem = COORD_CART3;
2357  grid[k]->dimension = 3;
2358  }
2359  else printf("Unknown coordinate system: %s\n",params);
2360  if(0) printf("Defining the coordinate system (%d-DIM).\n",grid[k]->dimension);
2361  }
2362 
2363  else if(strstr(command,"SUBCELL DIVISIONS")) {
2364  if(grid[k]->dimension == 1) {
2365  sscanf(params,"%d",&(*grid)[k].xcells);
2366  grid[k]->ycells = 1;
2367  }
2368  else if(grid[k]->dimension == 2)
2369  sscanf(params,"%d %d",&(*grid)[k].xcells,&(*grid)[k].ycells);
2370  else if(grid[k]->dimension == 3)
2371  sscanf(params,"%d %d %d",&(*grid)[k].xcells,&(*grid)[k].ycells,&(*grid)[k].zcells);
2372  if(grid[k]->xcells >= MAXCELLS || grid[k]->ycells >= MAXCELLS || grid[k]->zcells >= MAXCELLS) {
2373  printf("LoadElmergrid: Too many subcells [%d %d %d] vs. %d:\n",
2374  grid[k]->xcells,grid[k]->ycells,grid[k]->zcells,MAXCELLS);
2375  }
2376 
2377  /* Initialize the default stucture with ones */
2378  for(j=grid[k]->ycells;j>=1;j--)
2379  for(i=1;i<=grid[k]->xcells;i++)
2380  grid[k]->structure[j][i] = 1;
2381  }
2382 
2383  else if(strstr(command,"MINIMUM ELEMENT DIVISION")) {
2384  if(0) printf("Loading minimum number of elements\n");
2385  if((*grid)[k].dimension == 1)
2386  sscanf(params,"%d",&(*grid)[k].minxelems);
2387  if((*grid)[k].dimension == 2)
2388  sscanf(params,"%d %d",&(*grid)[k].minxelems,&(*grid)[k].minyelems);
2389  if((*grid)[k].dimension == 3)
2390  sscanf(params,"%d %d %d",&(*grid)[k].minxelems,&(*grid)[k].minyelems,&(*grid)[k].minzelems);
2391  }
2392 
2393  else if(strstr(command,"SUBCELL LIMITS 1")) {
2394  if(0) printf("Loading [%d] subcell limits in X-direction\n",grid[k]->xcells+1);
2395  cp = params;
2396  for(i=0;i<=grid[k]->xcells;i++) grid[k]->x[i] = next_real(&cp);
2397  }
2398  else if(strstr(command,"SUBCELL LIMITS 2")) {
2399  if(0) printf("Loading [%d] subcell limits in Y-direction\n",grid[k]->ycells+1);
2400  cp = params;
2401  for(i=0;i<=grid[k]->ycells;i++) grid[k]->y[i] = next_real(&cp);
2402  }
2403  else if(strstr(command,"SUBCELL LIMITS 3")) {
2404  if(0) printf("Loading [%d] subcell limits in Z-direction\n",grid[k]->zcells+1);
2405  cp = params;
2406  for(i=0;i<=grid[k]->zcells;i++) grid[k]->z[i] = next_real(&cp);
2407  }
2408 
2409  else if(strstr(command,"SUBCELL SIZES 1")) {
2410  if(0) printf("Loading [%d] subcell sizes in X-direction\n",grid[k]->xcells);
2411  cp = params;
2412  for(i=1;i<=grid[k]->xcells;i++) grid[k]->x[i] = next_real(&cp);
2413  for(i=1;i<=grid[k]->xcells;i++) grid[k]->x[i] = grid[k]->x[i-1] + grid[k]->x[i];
2414  }
2415  else if(strstr(command,"SUBCELL SIZES 2")) {
2416  if(0) printf("Loading [%d] subcell sizes in Y-direction\n",grid[k]->ycells);
2417  cp = params;
2418  for(i=1;i<=grid[k]->ycells;i++) grid[k]->y[i] = next_real(&cp);
2419  for(i=1;i<=grid[k]->ycells;i++) grid[k]->y[i] = grid[k]->y[i-1] + grid[k]->y[i];
2420  }
2421  else if(strstr(command,"SUBCELL SIZES 3")) {
2422  if(0) printf("Loading [%d] subcell sizes in Z-direction\n",grid[k]->zcells);
2423  cp = params;
2424  for(i=1;i<=grid[k]->zcells;i++) grid[k]->z[i] = next_real(&cp);
2425  for(i=1;i<=grid[k]->zcells;i++) grid[k]->z[i] = grid[k]->z[i-1] + grid[k]->z[i];
2426  }
2427 
2428  else if(strstr(command,"SUBCELL ORIGIN 1")) {
2429  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2430  if(strstr(params,"CENTER")) {
2431  raid = 0.5 * (grid[k]->x[0] + grid[k]->x[grid[k]->xcells]);
2432  }
2433  else if(strstr(params,"LEFT") || strstr(params,"MIN") ) {
2434  raid = grid[k]->x[0];
2435  }
2436  else if(strstr(params,"RIGHT") || strstr(params,"MAX") ) {
2437  raid = grid[k]->x[grid[k]->xcells];
2438  }
2439  else {
2440  cp = params;
2441  raid = next_real(&cp);
2442  }
2443  for(i=0;i<=grid[k]->xcells;i++) grid[k]->x[i] -= raid;
2444  }
2445  else if(strstr(command,"SUBCELL ORIGIN 2")) {
2446  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2447  if(strstr(params,"CENTER")) {
2448  raid = 0.5 * (grid[k]->y[0] + grid[k]->y[grid[k]->ycells]);
2449  }
2450  else if(strstr(params,"LEFT")) {
2451  raid = grid[k]->y[0];
2452  }
2453  else if(strstr(params,"RIGHT")) {
2454  raid = grid[k]->y[grid[k]->ycells];
2455  }
2456  else {
2457  cp = params;
2458  raid = next_real(&cp);
2459  }
2460  for(i=0;i<=grid[k]->ycells;i++) grid[k]->y[i] -= raid;
2461  }
2462  else if(strstr(command,"SUBCELL ORIGIN 3")) {
2463  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2464  if(strstr(params,"CENTER")) {
2465  raid = 0.5 * (grid[k]->z[0] + grid[k]->z[grid[k]->zcells]);
2466  }
2467  else if(strstr(params,"LEFT")) {
2468  raid = grid[k]->z[0];
2469  }
2470  else if(strstr(params,"RIGHT")) {
2471  raid = grid[k]->z[grid[k]->zcells];
2472  }
2473  else {
2474  cp = params;
2475  raid = next_real(&cp);
2476  }
2477  for(i=0;i<=grid[k]->zcells;i++) grid[k]->z[i] -= raid;
2478  }
2479 
2480  else if(strstr(command,"MATERIAL STRUCTURE")) {
2481  if(0) printf("Loading material structure\n");
2482 
2483  /* Initialize the default stucture with zeros */
2484  for(j=grid[k]->ycells;j>=1;j--)
2485  for(i=1;i<=grid[k]->xcells;i++)
2486  grid[k]->structure[j][i] = 0;
2487 
2488  for(j=grid[k]->ycells;j>=1;j--) {
2489  if(j < grid[k]->ycells) Getline(params,in);
2490  cp=params;
2491  for(i=1;i<=grid[k]->xcells;i++)
2492  grid[k]->structure[j][i] = next_int(&cp);
2493  }
2494  minmat = maxmat = grid[k]->structure[1][1];
2495  for(j=grid[k]->ycells;j>=1;j--)
2496  for(i=1;i<=grid[k]->xcells;i++) {
2497  if(minmat > grid[k]->structure[j][i])
2498  minmat = grid[k]->structure[j][i];
2499  if(maxmat < grid[k]->structure[j][i])
2500  maxmat = grid[k]->structure[j][i];
2501  }
2502  if(minmat < 0)
2503  printf("LoadElmergrid: please use positive material indices.\n");
2504  if(maxmat > MAXMATERIALS)
2505  printf("LoadElmergrid: material indices larger to %d may create problems.\n",
2506  MAXMATERIALS);
2507  }
2508  else if(strstr(command,"MATERIALS INTERVAL")) {
2509  sscanf(params,"%d %d",&(*grid)[k].firstmaterial,&(*grid)[k].lastmaterial);
2510  }
2511 
2512  else if(strstr(command,"REVOLVE")) {
2513  if(strstr(command,"REVOLVE RADIUS")) {
2514  (*grid)[k].rotate = TRUE;
2515  sscanf(params,"%le",&(*grid)[k].rotateradius2);
2516  }
2517  else if(strstr(command,"REVOLVE BLOCKS")) {
2518  (*grid)[k].rotate = TRUE;
2519  sscanf(params,"%d",&(*grid)[k].rotateblocks);
2520  }
2521  else if(strstr(command,"REVOLVE IMPROVE")) {
2522  (*grid)[k].rotate = TRUE;
2523  sscanf(params,"%le",&(*grid)[k].rotateimprove);
2524  }
2525  else if(strstr(command,"REVOLVE RADIUS")) {
2526  sscanf(params,"%le",&(*grid)[k].polarradius);
2527  }
2528  else if(strstr(command,"REVOLVE CURVE DIRECT")) {
2529  (*grid)[k].rotatecurve = TRUE;
2530  sscanf(params,"%le",&(*grid)[k].curvezet);
2531  }
2532  else if(strstr(command,"REVOLVE CURVE RADIUS")) {
2533  (*grid)[k].rotatecurve = TRUE;
2534  sscanf(params,"%le",&(*grid)[k].curverad);
2535  }
2536  else if(strstr(command,"REVOLVE CURVE ANGLE")) {
2537  (*grid)[k].rotatecurve = TRUE;
2538  sscanf(params,"%le",&(*grid)[k].curveangle);
2539  }
2540  }
2541 
2542  else if(strstr(command,"REDUCE ORDER INTERVAL")) {
2543  sscanf(params,"%d%d",&(*grid)[k].reduceordermatmin,
2544  &(*grid)[k].reduceordermatmax);
2545  }
2546 
2547  else if(strstr(command,"BOUNDARY DEFINITION")) {
2548  if(0) printf("Loading boundary conditions\n");
2549 
2550  for(i=0;i<MAXBOUNDARIES;i++) {
2551  if(i>0) Getline(params,in);
2552  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2553  if(strstr(params,"END")) break;
2554  sscanf(params,"%d %d %d %d",
2555  &(*grid)[k].boundtype[i],&(*grid)[k].boundext[i],
2556  &(*grid)[k].boundint[i],&(*grid)[k].boundsolid[i]);
2557  }
2558  if(0) printf("Found %d boundaries\n",i);
2559  (*grid)[k].noboundaries = i;
2560  }
2561 
2562  else if(strstr(command,"LAYERED BOUNDARIES")) {
2563  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2564  if(strstr(params,"TRUE")) (*grid)[k].layeredbc = 1;
2565  if(strstr(params,"FALSE")) (*grid)[k].layeredbc = 0;
2566  }
2567 
2568  else if(strstr(command,"NUMBERING")) {
2569  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2570  if(strstr(params,"HORIZONATAL")) (*grid)[k].numbering = NUMBER_XY;
2571  if(strstr(params,"VERTICAL")) (*grid)[k].numbering = NUMBER_YX;
2572  }
2573 
2574  else if(strstr(command,"ELEMENT DEGREE")) {
2575  sscanf(params,"%d",&(*grid)[k].elemorder);
2576  }
2577 
2578  else if(strstr(command,"ELEMENT INNERNODES")) {
2579  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2580  if(strstr(params,"TRUE")) (*grid)[k].elemmidpoints = TRUE;
2581  if(strstr(params,"FALSE")) (*grid)[k].elemmidpoints = FALSE;
2582  }
2583  else if(strstr(command,"ELEMENTTYPE") || strstr(command,"ELEMENTCODE")) {
2584  sscanf(params,"%d",&elemcode);
2585  }
2586 
2587  else if(strstr(command,"TRIANGLES CRITICAL ANGLE")) {
2588  sscanf(params,"%le",&(*grid)[k].triangleangle);
2589  }
2590  else if(strstr(command,"TRIANGLES")) {
2591  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2592  if(strstr(params,"TRUE")) (*grid)[k].triangles = TRUE;
2593  if(strstr(params,"FALSE")) (*grid)[k].triangles = FALSE;
2594  }
2595 
2596  else if(strstr(command,"PLANE ELEMENTS")) {
2597  sscanf(params,"%d",&(*grid)[k].wantedelems);
2598  }
2599  else if(strstr(command,"SURFACE ELEMENTS")) {
2600  sscanf(params,"%d",&(*grid)[k].wantedelems);
2601  }
2602  else if(strstr(command,"REFERENCE DENSITY")) {
2603  sscanf(params,"%le",&(*grid)[k].limitdx);
2604  (*grid)[k].autoratio = 3;
2605  }
2606  else if(strstr(command,"VERIFY DENSITY")) {
2607  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2608  if(strstr(params,"TRUE")) (*grid)[k].limitdxverify = TRUE;
2609  if(strstr(params,"FALSE")) (*grid)[k].limitdxverify = FALSE;
2610  }
2611  else if(strstr(command,"COORDINATE RATIO")) {
2612  if((*grid)[k].dimension == 2)
2613  sscanf(params,"%le",&(*grid)[k].xyratio);
2614  if((*grid)[k].dimension == 3)
2615  sscanf(params,"%le %le",&(*grid)[k].xyratio,&(*grid)[k].xzratio);
2616  }
2617 
2618  else if(strstr(command,"ELEMENT RATIOS 1")) {
2619  cp = params;
2620  for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xexpand[i] = next_real(&cp);
2621  }
2622  else if(strstr(command,"ELEMENT RATIOS 2")) {
2623  cp = params;
2624  for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yexpand[i] = next_real(&cp);
2625  }
2626  else if(strstr(command,"ELEMENT RATIOS 3")) {
2627  cp = params;
2628  for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zexpand[i] = next_real(&cp);
2629  }
2630 
2631  else if(strstr(command,"ELEMENT DENSITIES 1")) {
2632  cp = params;
2633  for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xdens[i] = next_real(&cp);
2634  }
2635  else if(strstr(command,"ELEMENT DENSITIES 2")) {
2636  cp = params;
2637  for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].ydens[i] = next_real(&cp);
2638  }
2639  else if(strstr(command,"ELEMENT DENSITIES 3")) {
2640  cp = params;
2641  for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zdens[i] = next_real(&cp);
2642  }
2643 
2644  else if(strstr(command,"ELEMENT DIVISIONS 1")) {
2645  cp = params;
2646  for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xelems[i] = next_int(&cp);
2647  (*grid)[k].autoratio = 0;
2648  }
2649  else if(strstr(command,"ELEMENT DIVISIONS 2")) {
2650  cp = params;
2651  for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yelems[i] = next_int(&cp);
2652  (*grid)[k].autoratio = 0;
2653  }
2654  else if(strstr(command,"ELEMENT DIVISIONS 3")) {
2655  cp = params;
2656  for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zelems[i] = next_int(&cp);
2657  (*grid)[k].autoratio = 0;
2658  }
2659 
2660  else if(strstr(command,"EXTRUDED STRUCTURE")) {
2661  for(i=1;i<=(*grid)[k].zcells;i++) {
2662  if(i>1) Getline(params,in);
2663  sscanf(params,"%d %d %d\n",
2664  &(*grid)[k].zfirstmaterial[i],&(*grid)[k].zlastmaterial[i],&(*grid)[k].zmaterial[i]);
2665  }
2666  }
2667 
2668  else if(strstr(command,"GEOMETRY MAPPINGS")) {
2669  if(k > 0) (*grid)[k].mappings = 0;
2670 
2671  for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);
2672  for(i=(*grid)[k].mappings;i<MAXMAPPINGS;i++) {
2673  if(i>(*grid)[k].mappings) Getline(params,in);
2674 
2675  if(strstr(params,"END")) break;
2676  cp=params;
2677  (*grid)[k].mappingtype[i] = next_int(&cp);
2678 #if 0
2679  (*grid)[k].mappingtype[i] += 50*SGN((*grid)[k].mappingtype[i]);
2680 #endif
2681  (*grid)[k].mappingline[i] = next_int(&cp);
2682  (*grid)[k].mappinglimits[2*i] = next_real(&cp);
2683  (*grid)[k].mappinglimits[2*i+1] = next_real(&cp);
2684  (*grid)[k].mappingpoints[i] = next_int(&cp);
2685  (*grid)[k].mappingparams[i] = Rvector(0,(*grid)[k].mappingpoints[i]);
2686  for(j=0;j<(*grid)[k].mappingpoints[i];j++)
2687  (*grid)[k].mappingparams[i][j] = next_real(&cp);
2688  }
2689  if(0) printf("Loaded %d geometry mappings\n",i);
2690  (*grid)[k].mappings = i;
2691  }
2692 
2693  else if(strstr(command,"END") ) {
2694  if(0) printf("End of field\n");
2695  }
2696 
2697  else if(strstr(command,"START NEW MESH")) {
2698  if((*nogrids) >= MAXCASES) {
2699  printf("There are more grids than was allocated for!\n");
2700  printf("Ignoring meshes starting from %d\n.",(*nogrids)+1);
2701  goto end;
2702  }
2703  (*nogrids)++;
2704  if(0) printf("\nLoading element meshing no %d\n",*nogrids);
2705  k = *nogrids - 1;
2706  if(k > nogrids0) (*grid)[k] = (*grid)[k-1];
2707  }
2708 
2709  else {
2710  if(1) printf("Unknown command: %s",command);
2711  }
2712  }
2713 
2714 end:
2715 
2716  if(0) printf("Found %d divisions for grid\n",*nogrids);
2717 
2718  for(k=nogrids0;k < (*nogrids) && k<MAXCASES;k++) {
2719 
2720  if(elemcode == 0) {
2721  if((*grid)[k].dimension == 1) {
2722  (*grid)[k].nonodes = (*grid)[k].elemorder + 1;
2723  }
2724  else if((*grid)[k].elemmidpoints == FALSE) {
2725  (*grid)[k].nonodes = 4 * (*grid)[k].elemorder;
2726  }
2727  else {
2728  if((*grid)[k].elemorder == 2) (*grid)[k].nonodes = 9;
2729  if((*grid)[k].elemorder == 3) (*grid)[k].nonodes = 16;
2730  }
2731  }
2732  else if(elemcode/100 == 2) {
2733  (*grid)[k].triangles = FALSE;
2734  (*grid)[k].nonodes = elemcode%100;
2735  }
2736  else if(elemcode/100 == 4) {
2737  (*grid)[k].triangles = FALSE;
2738  (*grid)[k].nonodes = elemcode%100;
2739  }
2740  else if(elemcode/100 == 3) {
2741  (*grid)[k].triangles = TRUE;
2742  if(elemcode%100 == 3) (*grid)[k].nonodes = 4;
2743  else if(elemcode%100 == 6) (*grid)[k].nonodes = 9;
2744  else if(elemcode%100 == 10) (*grid)[k].nonodes = 16;
2745  }
2746  }
2747 
2748  fclose(in);
2749  return(error);
2750 }
2751 
2752 
2753 
2755 {
2756  int i;
2757 
2758  eg->relh = 1.0;
2759  eg->inmethod = 0;
2760  eg->outmethod = 0;
2761  eg->silent = FALSE;
2762  eg->nofilesin = 1;
2763  eg->unitemeshes = FALSE;
2764  eg->triangles = FALSE;
2765  eg->triangleangle = 0.0;
2766  eg->rotate = FALSE;
2767  eg->polar = FALSE;
2768  eg->cylinder = FALSE;
2769  eg->usenames = FALSE;
2770  eg->layers = 0;
2771  eg->layereps = 0.0;
2772  eg->layermove = 0;
2773  eg->partitions = 0;
2774  eg->elements3d = 0;
2775  eg->nodes3d = 0;
2776  eg->metis = 0;
2777  eg->partitionhalo = FALSE;
2778  eg->partitionindirect = FALSE;
2779  eg->reduce = FALSE;
2780  eg->increase = FALSE;
2781  eg->translate = FALSE;
2782  eg->isoparam = FALSE;
2783  eg->removelowdim = FALSE;
2784  eg->removeunused = FALSE;
2785  eg->dim = 3;
2786  eg->center = FALSE;
2787  eg->scale = FALSE;
2788  eg->order = FALSE;
2789  eg->boundbounds = 0;
2790  eg->saveinterval[0] = eg->saveinterval[1] = eg->saveinterval[2] = 0;
2791  eg->bulkbounds = 0;
2792  eg->partorder = FALSE;
2793  eg->findsides = FALSE;
2794  eg->pelems = 0;
2795  eg->belems = 0;
2796  eg->saveboundaries = TRUE;
2797  eg->merge = FALSE;
2798  eg->bcoffset = FALSE;
2799  eg->periodic = 0;
2800  eg->periodicdim[0] = 0;
2801  eg->periodicdim[1] = 0;
2802  eg->periodicdim[2] = 0;
2803  eg->bulkorder = FALSE;
2804  eg->boundorder = FALSE;
2805  eg->sidemappings = 0;
2806  eg->bulkmappings = 0;
2807  eg->clone[0] = eg->clone[1] = eg->clone[2] = 0;
2808  eg->decimals = 12;
2809  eg->discont = 0;
2810  eg->connect = 0;
2811  eg->advancedmat = 0;
2812 
2813  for(i=0;i<MAXSIDEBULK;i++)
2814  eg->sidebulk[i] = 0;
2815 }
2816 
2817 
2818 
2819 
2820 
2821 
2822 int LoadCommands(char *prefix,struct ElmergridType *eg,
2823  struct GridType *grid, int mode,const char *IOmethods[],
2824  int info)
2825 {
2826  char filename[MAXFILESIZE],command[MAXLINESIZE],params[MAXLINESIZE],*cp;
2827 
2828  FILE *in = NULL;
2829  int i,j;
2830 
2831  if( mode == 0) {
2832  if (in = fopen("ELMERGRID_STARTINFO","r")) {
2833  fscanf(in,"%s",filename);
2834  fclose(in);
2835  printf("Using the file %s defined in ELMERGRID_STARTINFO\n",filename);
2836  if ((in = fopen(filename,"r")) == NULL) {
2837  printf("LoadCommands: opening of the file '%s' wasn't succesfull!\n",filename);
2838  return(1);
2839  }
2840  else printf("Loading ElmerGrid commands from file '%s'.\n",filename);
2841  }
2842  else
2843  return(2);
2844  }
2845  if(mode == 1) {
2846  AddExtension(prefix,filename,"eg");
2847  if ((in = fopen(filename,"r")) == NULL) {
2848  printf("LoadCommands: opening of the file '%s' wasn't succesfull!\n",filename);
2849  return(3);
2850  }
2851  if(info) printf("Loading ElmerGrid commands from file '%s'.\n",filename);
2852  }
2853  else if(mode == 2) {
2854  AddExtension(prefix,filename,"grd");
2855  if ((in = fopen(filename,"r")) == NULL) {
2856  printf("LoadCommands: opening of the file '%s' wasn't succesfull!\n",filename);
2857  return(4);
2858  }
2859  if(info) printf("Loading ElmerGrid commands from file '%s'.\n",filename);
2860  }
2861 
2862 
2863 
2864  for(;;) {
2865 
2866  if(GetCommand(command,params,in)) {
2867  if(0) printf("Reached the end of command file\n");
2868  goto end;
2869  }
2870 
2871  /* If the mode is the command file mode read also the file information from the command file. */
2872 
2873  if(mode <= 1) {
2874  if(strstr(command,"INPUT FILE")) {
2875  sscanf(params,"%s", &(eg->filesin[0]));
2876  }
2877 
2878  else if(strstr(command,"OUTPUT FILE")) {
2879  sscanf(params,"%s",&(eg->filesout[0]));
2880  }
2881 
2882  else if(strstr(command,"INPUT MODE")) {
2883  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2884 
2885  for(i=0;i<=MAXFORMATS;i++) {
2886  if(strstr(params,IOmethods[i])) {
2887  eg->inmethod = i;
2888  break;
2889  }
2890  }
2891  if(i>MAXFORMATS) sscanf(params,"%d",&eg->inmethod);
2892  }
2893 
2894  else if(strstr(command,"OUTPUT MODE")) {
2895  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2896 
2897  /* Type of output file (fewer options) */
2898  for(i=1;i<=MAXFORMATS;i++) {
2899  if(strstr(params,IOmethods[i])) {
2900  eg->outmethod = i;
2901  break;
2902  }
2903  }
2904  if(i>MAXFORMATS) sscanf(params,"%d",&eg->outmethod);
2905  }
2906  }
2907  /* End of command file specific part */
2908 
2909 
2910  if(strstr(command,"DECIMALS")) {
2911  sscanf(params,"%d",&eg->decimals);
2912  }
2913  else if(strstr(command,"TRIANGLES CRITICAL ANGLE")) {
2914  sscanf(params,"%le",&eg->triangleangle);
2915  }
2916  else if(strstr(command,"TRIANGLES")) {
2917  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2918  if(strstr(params,"TRUE")) eg->triangles = TRUE;
2919  }
2920  else if(strstr(command,"MERGE NODES")) {
2921  eg->merge = TRUE;
2922  sscanf(params,"%le",&eg->cmerge);
2923  }
2924  else if(strstr(command,"UNITE")) {
2925  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2926  if(strstr(params,"TRUE")) eg->unitemeshes = TRUE;
2927  }
2928  else if(strstr(command,"ORDER NODES")) {
2929  eg->order = TRUE;
2930  if(eg->dim == 1)
2931  sscanf(params,"%le",&eg->corder[0]);
2932  else if(eg->dim == 2)
2933  sscanf(params,"%le%le",&eg->corder[0],&eg->corder[1]);
2934  else if(eg->dim == 3)
2935  sscanf(params,"%le%le%le",&eg->corder[0],&eg->corder[1],&eg->corder[2]);
2936  }
2937  else if(strstr(command,"SCALE")) {
2938  eg->scale = TRUE;
2939  if(eg->dim == 1)
2940  sscanf(params,"%le",&eg->cscale[0]);
2941  else if(eg->dim == 2)
2942  sscanf(params,"%le%le",&eg->cscale[0],&eg->cscale[1]);
2943  else if(eg->dim == 3)
2944  sscanf(params,"%le%le%le",&eg->cscale[0],&eg->cscale[1],&eg->cscale[2]);
2945  }
2946  else if(strstr(command,"CENTRALIZE")) {
2947  eg->center = TRUE;
2948  }
2949  else if(strstr(command,"TRANSLATE")) {
2950  eg->translate = TRUE;
2951  if(eg->dim == 1)
2952  sscanf(params,"%le",&eg->ctranslate[0]);
2953  else if(eg->dim == 2)
2954  sscanf(params,"%le%le",&eg->ctranslate[0],&eg->ctranslate[1]);
2955  else if(eg->dim == 3)
2956  sscanf(params,"%le%le%le",&eg->ctranslate[0],&eg->ctranslate[1],&eg->ctranslate[2]);
2957  }
2958  else if(strstr(command,"ROTATE MESH")) {
2959  eg->rotate = TRUE;
2960  sscanf(params,"%le%le%le",&eg->crotate[0],&eg->crotate[1],&eg->crotate[2]);
2961  }
2962  else if(strstr(command,"CLONE")) {
2963  if(strstr(command,"CLONE SIZE")) {
2964  if(eg->dim == 1)
2965  sscanf(params,"%le",&eg->clonesize[0]);
2966  else if(eg->dim == 2)
2967  sscanf(params,"%le%le",&eg->clonesize[0],&eg->clonesize[1]);
2968  else if(eg->dim == 3)
2969  sscanf(params,"%le%le%le",&eg->clonesize[0],&eg->clonesize[1],&eg->clonesize[2]);
2970  }
2971  else {
2972  if(eg->dim == 1)
2973  sscanf(params,"%d",&eg->clone[0]);
2974  else if(eg->dim == 2)
2975  sscanf(params,"%d%d",&eg->clone[0],&eg->clone[1]);
2976  else if(eg->dim == 3)
2977  sscanf(params,"%d%d%d",&eg->clone[0],&eg->clone[1],&eg->clone[2]);
2978  }
2979  }
2980 
2981  else if(strstr(command,"POLAR RADIUS")) {
2982  eg->polar = TRUE;
2983  sscanf(params,"%le",&eg->polarradius);
2984  }
2985  else if(strstr(command,"CYLINDER")) {
2986  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2987  if(strstr(params,"TRUE")) eg->cylinder = TRUE;
2988  }
2989  else if(strstr(command,"REDUCE DEGREE")) {
2990  eg->reduce = TRUE;
2991  sscanf(params,"%d%d",&eg->reducemat1,&eg->reducemat2);
2992  }
2993  else if(strstr(command,"INCREASE DEGREE")) {
2994  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
2995  if(strstr(params,"TRUE")) eg->increase = TRUE;
2996  }
2997  else if(strstr(command,"ADVANCED ELEMENTS")) {
2998  printf("Loading advanced element definitions\n");
2999 
3000  for(i=0;i<MAXMATERIALS;i++) {
3001  if(i>0) Getline(params,in);
3002  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3003  if(strstr(params,"END")) break;
3004 
3005  sscanf(params,"%d%d%d%d%d%d%d",
3006  &eg->advancedelem[7*i],&eg->advancedelem[7*i+1],&eg->advancedelem[7*i+2],
3007  &eg->advancedelem[7*i+3],&eg->advancedelem[7*i+4],&eg->advancedelem[7*i+5],
3008  &eg->advancedelem[7*i+6]);
3009  }
3010  eg->advancedmat = i;
3011  printf("Found %d definitions for advanced elements.\n",i);
3012  }
3013  else if(strstr(command,"POWER ELEMENTS")) {
3014  printf("Loading p-type element definitions\n");
3015 
3016  for(i=0;i<MAXMATERIALS;i++) {
3017  if(i>0) Getline(params,in);
3018  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3019  if(strstr(params,"END")) break;
3020  sscanf(params,"%d%d%d",
3021  &eg->pelemmap[3*i],&eg->pelemmap[3*i+1],&eg->pelemmap[3*i+2]);
3022  }
3023  eg->pelems = i;
3024  printf("Found %d definitions for p-elements.\n",i);
3025  }
3026  else if(strstr(command,"BUBBLE ELEMENTS")) {
3027  printf("Loading bubble element definitions\n");
3028 
3029  for(i=0;i<MAXMATERIALS;i++) {
3030  if(i>0) Getline(params,in);
3031  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3032  if(strstr(params,"END")) break;
3033  sscanf(params,"%d%d%d",
3034  &eg->belemmap[3*i],&eg->belemmap[3*i+1],&eg->belemmap[3*i+2]);
3035  }
3036  eg->belems = i;
3037  printf("Found %d definitions for bubble elements.\n",i);
3038  }
3039  else if(strstr(command,"METIS OPTION")) {
3040 #if HAVE_METIS
3041  sscanf(params,"%d",&eg->partopt);
3042 #else
3043  printf("This version of ElmerGrid was compiled without Metis library!\n");
3044 #endif
3045  }
3046  else if(strstr(command,"METIS")) {
3047 #if HAVE_METIS
3048  sscanf(params,"%d",&eg->metis);
3049 #else
3050  printf("This version of ElmerGrid was compiled without Metis library!\n");
3051 #endif
3052  }
3053  else if(strstr(command,"PARTITION ORDER")) {
3054  eg->partorder = 1;
3055  if(eg->dim == 2) sscanf(params,"%le%le",&eg->partcorder[0],&eg->partcorder[1]);
3056  if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->partcorder[0],
3057  &eg->partcorder[1],&eg->partcorder[2]);
3058  }
3059  else if(strstr(command,"PARTITION")) {
3060  if(eg->dim == 2) sscanf(params,"%d%d",&eg->partdim[0],&eg->partdim[1]);
3061  if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->partdim[0],&eg->partdim[1],&eg->partdim[2]);
3062  eg->partitions = 1;
3063  for(i=0;i<eg->dim;i++) {
3064  if(eg->partdim[i] < 1) eg->partdim[i] = 1;
3065  eg->partitions *= eg->partdim[i];
3066  }
3067  }
3068  else if(strstr(command,"PERIODIC")) {
3069  if(eg->dim == 2) sscanf(params,"%d%d",&eg->periodicdim[0],&eg->periodicdim[1]);
3070  if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->periodicdim[0],
3071  &eg->periodicdim[1],&eg->periodicdim[2]);
3072  }
3073  else if(strstr(command,"HALO")) {
3074  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3075  if(strstr(params,"TRUE")) eg->partitionhalo = TRUE;
3076  }
3077  else if(strstr(command,"INDIRECT")) {
3078  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3079  if(strstr(params,"TRUE")) eg->partitionindirect = TRUE;
3080  }
3081  else if(strstr(command,"BOUNDARY TYPE MAPPINGS")) {
3082  for(i=0;i<MAXMATERIALS;i++) {
3083  if(i>0) Getline(params,in);
3084  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3085  if(strstr(params,"END")) break;
3086  cp = params;
3087  sscanf(params,"%d%d%d",&eg->sidemap[3*i],&eg->sidemap[3*i+1],&eg->sidemap[3*i+2]);
3088  }
3089  printf("Found %d boundary type mappings\n",i);
3090  eg->sidemappings = i;
3091  }
3092  else if(strstr(command,"BULK TYPE MAPPINGS")) {
3093  for(i=0;i<MAXMATERIALS;i++) {
3094  if(i>0) Getline(params,in);
3095  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3096  if(strstr(params,"END")) break;
3097  cp = params;
3098  sscanf(params,"%d%d%d",&eg->bulkmap[3*i],&eg->bulkmap[3*i+1],&eg->bulkmap[3*i+2]);
3099  }
3100  printf("Found %d bulk type mappings\n",i);
3101  eg->bulkmappings = i;
3102  }
3103  else if(strstr(command,"BOUNDARY BOUNDARY")) {
3104  for(i=0;i<MAXBOUNDARIES;i++) {
3105  if(i>0) Getline(params,in);
3106  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3107  if(strstr(params,"END")) break;
3108  cp = params;
3109  sscanf(params,"%d%d%d",&eg->boundbound[3*i+2],&eg->boundbound[3*i],&eg->boundbound[3*i+1]);
3110  }
3111  printf("Found %d boundary boundary definitions\n",i);
3112  eg->boundbounds = i;
3113  }
3114  else if(strstr(command,"MATERIAL BOUNDARY")) {
3115  for(i=0;i<MAXBOUNDARIES;i++) {
3116  if(i>0) Getline(params,in);
3117  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3118  if(strstr(params,"END")) break;
3119  cp = params;
3120  sscanf(params,"%d%d%d",&eg->bulkbound[3*i+2],&eg->bulkbound[3*i],&eg->bulkbound[3*i+1]);
3121  }
3122  printf("Found %d material boundary definitions\n",i);
3123  eg->bulkbounds = i;
3124  }
3125 
3126  else if(strstr(command,"RENUMBER BOUNDARY")) {
3127  for(i=0;i<MAXBOUNDARIES;i++) {
3128  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3129  if(strstr(params,"END")) break;
3130  cp = params;
3131  sscanf(params,"%d%d%d",&eg->sidemap[3*i],&eg->sidemap[3*i+1],&eg->sidemap[3*i+2]);
3132  }
3133  printf("Found %d boundary mappings\n",i);
3134  eg->sidemappings = i;
3135  }
3136  else if(strstr(command,"RENUMBER MATERIAL")) {
3137  for(i=0;i<MAXBOUNDARIES;i++) {
3138  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3139  if(strstr(params,"END")) break;
3140  cp = params;
3141  sscanf(params,"%d%d%d",&eg->bulkmap[3*i],&eg->bulkmap[3*i+1],&eg->bulkmap[3*i+2]);
3142  }
3143  printf("Found %d material mappings\n",i);
3144  eg->bulkmappings = i;
3145  }
3146 
3147  else if(strstr(command,"BOUNDARY LAYER")) {
3148  if(strstr(command,"BOUNDARY LAYER MOVE")) {
3149  sscanf(params,"%d",&eg->layermove);
3150  }
3151  else if(strstr(command,"BOUNDARY LAYER EPSILON")) {
3152  sscanf(params,"%le",&eg->layereps);
3153  }
3154  else {
3155  for(i=0;i<MAXBOUNDARIES;i++) {
3156  if(i>0) Getline(params,in);
3157  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3158  cp = params;
3159 
3160  if(strstr(params,"END") || strstr(params,"End") ) break;
3161  eg->layerbounds[i] = next_int(&cp);
3162  eg->layernumber[i] = next_int(&cp);
3163  eg->layerthickness[i] = next_real(&cp);
3164  eg->layerratios[i] = next_real(&cp);
3165  eg->layerparents[i] = next_int(&cp);
3166  }
3167  printf("Found %d boundary layers\n",i);
3168  eg->layers = i;
3169  }
3170  }
3171  else if(strstr(command,"REMOVE LOWER DIMENSIONAL BOUNDARIES")) {
3172  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3173  if(strstr(params,"TRUE")) eg->removelowdim = TRUE;
3174  }
3175  else if(strstr(command,"REMOVE UNUSED NODES")) {
3176  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3177  if(strstr(params,"TRUE")) eg->removeunused = TRUE;
3178  }
3179  else if(strstr(command,"REORDER MATERIAL")) {
3180  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3181  if(strstr(params,"TRUE")) eg->bulkorder = TRUE;
3182  }
3183  else if(strstr(command,"REORDER BOUNDARY")) {
3184  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3185  if(strstr(params,"TRUE")) eg->boundorder = TRUE;
3186  }
3187  else if(strstr(command,"DIMENSION")) {
3188  sscanf(params,"%d",&eg->dim);
3189  }
3190  else if(strstr(command,"ISOPARAMETRIC")) {
3191  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3192  if(strstr(params,"TRUE")) eg->isoparam = TRUE;
3193  }
3194  else if(strstr(command,"NO BOUNDARY")) {
3195  for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);
3196  if(strstr(params,"TRUE")) eg->saveboundaries = FALSE;
3197  }
3198  else if(strstr(command,"EXTRUDED")) {
3199  grid->dimension = 3;
3200 
3201  if(strstr(command,"EXTRUDED DIVISIONS")) {
3202  sscanf(params,"%d",&grid->zcells);
3203  }
3204  else if(strstr(command,"EXTRUDED LIMITS")) {
3205  cp = params;
3206  for(i=0;i<=grid->zcells;i++) grid->z[i] = next_real(&cp);
3207  }
3208  else if(strstr(command,"EXTRUDED ELEMENTS")) {
3209  cp = params;
3210  for(i=1;i<=grid->zcells;i++) grid->zelems[i] = next_int(&cp);
3211  grid->autoratio = FALSE;
3212  }
3213  else if(strstr(command,"EXTRUDED RATIOS")) {
3214  cp = params;
3215  for(i=1;i<=grid->zcells;i++) grid->zexpand[i] = next_real(&cp);
3216  }
3217  else if(strstr(command,"EXTRUDED DENSITIES")) {
3218  cp = params;
3219  for(i=1;i<=grid->zcells;i++) grid->zdens[i] = next_real(&cp);
3220  }
3221  else if(strstr(command,"EXTRUDED STRUCTURE")) {
3222  for(i=1;i<= grid->zcells;i++) {
3223  if(i>1) Getline(params,in);
3224  sscanf(params,"%d %d %d\n",
3225  &grid->zfirstmaterial[i],&grid->zlastmaterial[i],&grid->zmaterial[i]);
3226  }
3227  }
3228 
3229  }
3230  }
3231 
3232 end:
3233  if(0) printf("Read commands from a file\n");
3234 
3235  return(0);
3236 }
3237 
3238 
3240  struct FemType *data,struct BoundaryType *boundaries,
3241  Real relh,int info) {
3242  int j;
3243  struct CellType *cell;
3244 
3245  for(j=0;j<MAXBOUNDARIES;j++) {
3246  boundaries[j].created = FALSE;
3247  boundaries[j].nosides = FALSE;
3248  }
3249 
3250  SetElementDivision(grid,relh,info);
3251 
3252  cell = (struct CellType*)
3253  malloc((size_t) (grid->nocells+1)*sizeof(struct CellType));
3254  SetCellData(grid,cell,info);
3255 
3256  if(grid->dimension == 1)
3257  SetCellKnots1D(grid,cell,info);
3258  else
3259  SetCellKnots(grid,cell,info);
3260 
3261  CreateKnots(grid,cell,data,0,0);
3262 
3263  if(grid->noboundaries > 0) {
3264  for(j=0;j<grid->noboundaries;j++) {
3265  if(grid->boundsolid[j] < 4) {
3266  CreateBoundary(cell,data,&(boundaries[j]),grid->boundext[j],grid->boundint[j],
3267  1,grid->boundtype[j],info);
3268  }
3269  else {
3270  CreatePoints(cell,data,&(boundaries[j]),grid->boundext[j],grid->boundint[j],
3271  grid->boundsolid[j],grid->boundtype[j],info);
3272  }
3273  }
3274  }
3275 #if 0
3276  else {
3277  CreateAllBoundaries(cell,data,boundaries,info);
3278  }
3279 #endif
3280 
3281  free(cell);
3282 
3283  return 0;
3284 }