Path: blob/devel/ElmerGUI/Application/plugins/egnative.cpp
3203 views
/*1ElmerGrid - A simple mesh generation and manipulation utility2Copyright (C) 1995- , CSC - IT Center for Science Ltd.34Author: Peter Raback5Email: [email protected]6Address: CSC - IT Center for Science Ltd.7Keilaranta 14802101 Espoo, Finland910This program is free software; you can redistribute it and/or11modify it under the terms of the GNU General Public License12as published by the Free Software Foundation; either version 213of the License, or (at your option) any later version.1415This program is distributed in the hope that it will be useful,16but WITHOUT ANY WARRANTY; without even the implied warranty of17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the18GNU General Public License for more details.1920You should have received a copy of the GNU General Public License21along with this program; if not, write to the Free Software22Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.23*/2425/* -------------------------------: egnative.c :----------------------------26This module includes routines for I/O of native formats of Elmer.27*/2829#include <stdio.h>30#include <unistd.h>31#include <stddef.h>32#include <stdlib.h>33#include <string.h>34#include <math.h>3536#if HAVE_UNISTD_H37#include <unistd.h>38#endif3940#include <stdarg.h>41#include <stdio.h>42#include <limits.h>43#include <ctype.h>44#include <sys/stat.h>45#include <sys/types.h>4647#include "egutils.h"48#include "egdef.h"49#include "egtypes.h"50#include "egmesh.h"51/* #include "egparallel.h" */52#include "egnative.h"53/*#include "../config.h"*/5455#define GETLINE ioptr=fgets(line,MAXLINESIZE,in)56static char *ioptr;575859#define DEBUG 0606162int matcactive=FALSE, iodebug=FALSE;6364#define MAXINMETHODS 2165const char *InMethods[] = {66/*0*/ "EG",67/*1*/ "ELMERGRID",68/*2*/ "ELMERSOLVER",69/*3*/ "ELMERPOST",70/*4*/ "ANSYS",71/*5*/ "IDEAS",72/*6*/ "ABAQUS",73/*7*/ "FIDAP",74/*8*/ "UNV",75/*9*/ "COMSOL",76/*10*/ "FIELDVIEW",77/*11*/ "TRIANGLE",78/*12*/ "MEDIT",79/*13*/ "GID",80/*14*/ "GMSH",81/*15*/ "PARTITIONED",82/*16*/ "FVCOM",83/*17*/ "NASTRAN",84/*18*/ "CGSIM",85/*19*/ "GEO",86/*20*/ "FLUX2D",87/*21*/ "FLUX3D",88};899091#define MAXOUTMETHODS 592const char *OutMethods[] = {93/*0*/ "EG",94/*1*/ "ELMERGRID",95/*2*/ "ELMERSOLVER",96/*3*/ "ELMERPOST",97/*4*/ "GMSH",98/*5*/ "VTU",99};100101102void Instructions()103{104printf("****************** Elmergrid ************************\n");105printf("This program can create simple 2D structured meshes consisting of\n");106printf("linear, quadratic or cubic rectangles or triangles. The meshes may\n");107printf("also be extruded and revolved to create 3D forms. In addition many\n");108printf("mesh formats may be imported into Elmer software. Some options have\n");109printf("not been properly tested. Contact the author if you face problems.\n\n");110111printf("The program has two operation modes\n");112printf("A) Command file mode which has the command file as the only argument\n");113printf(" 'ElmerGrid commandfile.eg'\n\n");114115printf("B) Inline mode which expects at least three input parameters\n");116printf(" 'ElmerGrid 1 3 test'\n\n");117printf("The first parameter defines the input file format:\n");118printf("1) .grd : ElmerGrid file format\n");119printf("2) .mesh.* : Elmer input format\n");120printf("3) .ep : Elmer output format\n");121printf("4) .ansys : Ansys input format\n");122printf("5) .inp : Abaqus input format by Ideas\n");123printf("6) .fil : Abaqus output format\n");124printf("7) .FDNEUT : Gambit (Fidap) neutral file\n");125printf("8) .unv : Universal mesh file format\n");126printf("9) .mphtxt : Comsol Multiphysics mesh format\n");127printf("10) .dat : Fieldview format\n");128printf("11) .node,.ele: Triangle 2D mesh format\n");129printf("12) .mesh : Medit mesh format\n");130printf("13) .msh : GID mesh format\n");131printf("14) .msh : Gmsh mesh format\n");132printf("15) .ep.i : Partitioned ElmerPost format\n");133printf("16) .2dm : 2D triangular FVCOM format\n");134#if 0135printf("17) .msh : Nastran format\n");136printf("18) .msh : CGsim format\n");137printf("19) .geo : Geo format\n");138printf("20) .tra : Cedrat Flux 2D format\n");139printf("21) .pf3 : Cedrat Flux 3D format\n");140#endif141142printf("\nThe second parameter defines the output file format:\n");143printf("1) .grd : ElmerGrid file format\n");144printf("2) .mesh.* : ElmerSolver format (also partitioned .part format)\n");145printf("3) .ep : ElmerPost format\n");146printf("4) .msh : Gmsh mesh format\n");147printf("5) .vtu : VTK ascii XML format\n");148#if 0149printf("5) .inp : Abaqus input format\n");150printf("7) .fidap : Fidap format\n");151printf("18) .ep : Fastcap input format.\n");152#endif153154printf("\nThe third parameter is the name of the input file.\n");155printf("If the file does not exist, an example with the same name is created.\n");156printf("The default output file name is the same with a different suffix.\n\n");157158printf("There are several additional in-line parameters that are\n");159printf("taken into account only when applicable to the given format.\n");160161printf("-out str : name of the output file\n");162printf("-in str : name of a secondary input file\n");163printf("-decimals : number of decimals in the saved mesh (eg. 8)\n");164printf("-relh real : give relative mesh density parameter for ElmerGrid meshing\n");165printf("-triangles : rectangles will be divided to triangles\n");166printf("-merge real : merges nodes that are close to each other\n");167printf("-order real[3] : reorder elements and nodes using c1*x+c2*y+c3*z\n");168printf("-centralize : set the center of the mesh to origin\n");169printf("-scale real[3] : scale the coordinates with vector real[3]\n");170printf("-translate real[3] : translate the nodes with vector real[3]\n");171printf("-rotate real[3] : rotate around the main axis with angles real[3]\n");172printf("-clone int[3] : make identical copies of the mesh\n");173printf("-clonesize real[3] : the size of the mesh to be cloned if larger to the original\n");174printf("-mirror int[3] : copy the mesh around the origin in coordinate directions\n");175printf("-cloneinds : when performing cloning should cloned entities be given new indexes\n");176printf("-unite : the meshes will be united\n");177printf("-unitenooverlap : the meshes will be united without overlap in entity numbering\n");178printf("-polar real : map 2D mesh to a cylindrical shell with given radius\n");179printf("-cylinder : map 2D/3D cylindrical mesh to a cartesian mesh\n");180printf("-reduce int[2] : reduce element order at material interval [int1 int2]\n");181printf("-increase : increase element order from linear to quadratic\n");182printf("-bcoffset int : add an offset to the boundary conditions\n");183printf("-discont int : make the boundary to have secondary nodes\n");184printf("-connect int : make the boundary to have internal connection among its elements\n");185printf("-removeintbcs : remove internal boundaries if they are not needed\n");186printf("-removelowdim : remove boundaries that are two ranks lower than highest dim\n");187printf("-removeunused : remove nodes that are not used in any element\n");188printf("-bulkorder : renumber materials types from 1 so that every number is used\n");189printf("-boundorder : renumber boundary types from 1 so that every number is used\n");190printf("-autoclean : this performs the united action of the four above\n");191printf("-multidim : keep lower order entities even if they are not boundaries\n");192printf("-bulkbound int[3] : set the intersection of materials [int1 int2] to be boundary int3\n");193printf("-boundbound int[3] : set the intersection of boundaries [int1 int2] to be boundary int3\n");194printf("-bulktype int[3] : set material types in interval [int1 int2] to type int3\n");195printf("-boundtype int[3] : set sidetypes in interval [int1 int2] to type int3\n");196printf("-layer int[2] real[2]: make a boundary layer for given boundary\n");197printf("-layermove int : apply Jacobi filter int times to move the layered mesh\n");198printf("-divlayer int[2] real[2]: make a boundary layer for given boundary\n");199printf("-3d / -2d / -1d : mesh is 3, 2 or 1-dimensional (applies to examples)\n");200printf("-isoparam : ensure that higher order elements are convex\n");201printf("-nonames : disable use of mesh.names even if it would be supported by the format\n");202printf("-nosave : disable saving part altogether\n");203printf("-nooverwrite : if mesh already exists don't overwrite it\n");204printf("-vtuone : start real node indexes in vtu file from one\n");205printf("-timer : show timer information\n");206printf("-infofile str : file for saving the timer and size information\n");207208printf("\nKeywords are related to mesh partitioning for parallel ElmerSolver runs:\n");209printf("-partition int[3] : the mesh will be partitioned in cartesian main directions\n");210printf("-partorder real[3] : in the 'partition' method set the direction of the ordering\n");211printf("-parttol real : in the 'partition' method set the tolerance for ordering\n");212printf("-partcell int[3] : the mesh will be partitioned in cells of fixed sizes\n");213printf("-partcyl int[3] : the mesh will be partitioned in cylindrical main directions\n");214#if USE_METIS215printf("-metiskway int : mesh will be partitioned with Metis using graph Kway routine\n");216printf("-metisrec int : mesh will be partitioned with Metis using graph Recursive routine\n");217printf("-metiscontig : enforce that the metis partitions are contiguous\n");218printf("-metisvol : minimize total communication volume in Metis\n");219printf("-metisminconn : minimize the maximum connectivity count in Metis\n");220printf("-metisseed int : random number generator seed for Metis algorithms\n");221printf("-metisncuts int : number of competing partitions to generate\n");222#endif223printf("-partdual : use the dual graph in partition method (when available)\n");224printf("-halo : create halo for the partitioning for DG\n");225printf("-halobc : create halo for the partitioning at boundaries only\n");226printf("-haloz / -halor : create halo for the the special z- or r-partitioning\n");227printf("-halogreedy : create halo being greedy over the partition interfaces\n");228printf("-indirect : create indirect connections (102 elements) in the partitioning\n");229printf("-periodic int[3] : periodic coordinate directions for parallel & conforming meshes\n");230printf("-partoptim : apply aggressive optimization to node sharing\n");231printf("-partnobcoptim : do not apply optimization to bc ownership sharing\n");232printf("-partbw : minimize the bandwidth of partition-partition couplings\n");233printf("-parthypre : number the nodes continuously partitionwise\n");234printf("-partzbc : partition connected BCs separately to partitions in Z-direction\n");235printf("-partrbc : partition connected BCs separately to partitions in R-direction\n");236#if USE_METIS237printf("-metisbc : partition connected BCs separately to partitions by Metis\n");238#endif239printf("-partlayers int : extend boundary partitioning by element layers\n");240241printf("\nKeywords are related to (nearly obsolete) ElmerPost format:\n");242printf("-partjoin int : number of ElmerPost partitions in the data to be joined\n");243printf("-saveinterval int[3] : the first, last and step for fusing parallel data\n");244printf("-nobound : disable saving of boundary elements in ElmerPost format\n");245246if(0) printf("-names : conserve name information where applicable\n");247}248249250void Goodbye()251{252printf("\nThank you for using Elmergrid!\n");253printf("Send bug reports and feature wishes to [email protected]\n");254exit(0);255}256257258259#if USE_MATC260char *mtc_domath(const char *);261void mtc_init(FILE * input, FILE * output, FILE * error);262#endif263264265static int Getline(char *line1,FILE *io)266{267int i,isend;268char line0[MAXLINESIZE],*charend,*matcpntr,*matcpntr0;269270for(i=0;i<MAXLINESIZE;i++)271line0[i] = 0x00;272273newline:274275charend = fgets(line0,MAXLINESIZE,io);276isend = (charend == NULL);277278if(isend) return(1);279280if(line0[0] == '#' || line0[0] == '%' || line0[0] == '!') goto newline;281if(!matcactive && line0[0] == '*') goto newline;282283if(!matcactive && strchr(line0,'$') ) {284#if USE_MATC285printf("\n a $ found and MATC has been compiled but not activated,\n");286printf("either remove the $ or add 'MATC = True' to grd input file.\n");287#else288printf("\n a $ found and MATC has not been compiled into ElmerGrid,\n");289printf("either remove the $ or compile ElmerGrid with MATC\n");290#endif // USE_MATC291bigerror("Error: $ found in command and MATC is not active");292}293294#if USE_MATC295if(matcactive) {296matcpntr0 = strchr(line0,'$');297if(matcpntr0) {298matcpntr = mtc_domath(&matcpntr0[1]);299if(matcpntr) {300strcpy(matcpntr0, matcpntr);301if(0) printf("A: %s\n%s\n",matcpntr0,matcpntr);302}303}304}305#endif306307if(strstr(line0,"subcell boundaries")) goto newline;308if(strstr(line0,"material structure")) goto newline;309if(strstr(line0,"mode")) goto newline;310if(strstr(line0,"type")) goto newline;311312for(i=0;i<MAXLINESIZE;i++)313line1[i] = toupper(line0[i]);314315if(iodebug) printf("line: %s\n",line1);316317return(0);318}319320321322void InitGrid(struct GridType *grid)323/* Initializes the grid of a specific mesh. A grid can differ324between various differential equations.325*/326#define MAXBODYID 1000327{328int i,j;329330grid->layered = FALSE;331grid->layeredbc = TRUE;332grid->layerbcoffset = 0;333grid->triangles = FALSE;334grid->triangleangle = 0.0;335grid->partitions = FALSE;336grid->wantedelems = 0;337grid->wantedelems3d = 0;338grid->wantednodes3d = 0;339grid->limitdx = 0.0;340grid->limitdxverify = FALSE;341342grid->dimension = 2;343grid->xcells = grid->ycells = grid->zcells = 0;344grid->nocells = 0;345grid->noknots = grid->noelements = 0;346grid->totxelems = grid->totyelems = grid->totzelems = 0;347grid->minxelems = grid->minyelems = 1;348grid->minzelems = 2;349grid->firstmaterial = 1;350grid->lastmaterial = MAXBODYID;351grid->autoratio = 1;352grid->xyratio = 1.0;353grid->xzratio = 1.0;354grid->nonodes = 4;355grid->numbering = NUMBER_XY;356grid->rotate = FALSE;357grid->rotateradius1 = 0.0;358grid->rotateradius2 = 0.0;359grid->rotateimprove = 1.0;360grid->rotateblocks = 4;361grid->rotatecartesian = FALSE;362grid->reduceordermatmin = 0;363grid->reduceordermatmax = 0;364grid->polarradius = 1.0;365grid->elemorder = 1;366grid->elemmidpoints = FALSE;367368grid->rotatecurve = FALSE;369grid->curverad = 0.5;370grid->curveangle = 90.0;371grid->curvezet = 1.0;372373for(i=0;i<=MAXCELLS;i++) {374grid->xelems[i] = 0;375grid->xlinear[i] = TRUE;376grid->xratios[i] = 1.;377grid->xexpand[i] = 1.;378grid->xdens[i] = 1.;379grid->x[i] = 0.;380}381for(i=0;i<=MAXCELLS;i++) {382grid->yelems[i] = 0;383grid->ylinear[i] = TRUE;384grid->yratios[i] = 1.0;385grid->yexpand[i] = 1.0;386grid->ydens[i] = 1.0;387grid->y[i] = 0.;388}389for(i=0;i<=MAXCELLS;i++) {390grid->zelems[i] = 0;391grid->zlinear[i] = TRUE;392grid->zratios[i] = 1.0;393grid->zexpand[i] = 1.0;394grid->zdens[i] = 1.0;395grid->z[i] = 0.;396grid->zfirstmaterial[i] = 1;397grid->zlastmaterial[i] = MAXBODYID;398grid->zmaterial[i] = 0;399}400401grid->zmaterialmapexists = FALSE;402grid->zhelicityexists = FALSE;403grid->zhelicity = 0.0;404405/* Initializes the numbering of the cells. */406for(j=0;j<=MAXCELLS+1;j++)407for(i=0;i<=MAXCELLS+1;i++)408grid->structure[j][i] = MAT_NOTHING;409410for(j=0;j<=MAXCELLS+1;j++)411for(i=0;i<=MAXCELLS+1;i++)412grid->numbered[j][i] = 0;413414grid->noboundaries = 0;415for(i=0;i<MAXBOUNDARIES;i++) {416grid->boundint[i] = 0;417grid->boundext[i] = 0;418grid->boundsolid[i] = 0;419grid->boundtype[i] = 0;420}421422grid->mappings = 0;423for(i=0;i<MAXMAPPINGS;i++) {424grid->mappingtype[i] = 0;425grid->mappingline[i] = 0;426grid->mappinglimits[2*i] = 0;427grid->mappinglimits[2*i+1] = 0;428grid->mappingpoints[i] = 0;429}430}431432433static void ExampleGrid1D(struct GridType **grids,int *nogrids,int info)434/* Creates an example grid that might be used to analyze435flow through a step. */436{437int j;438struct GridType *grid;439440(*nogrids) = 1;441(*grids) = (struct GridType*)442malloc((size_t) (*nogrids)*sizeof(struct GridType));443444grid = grids[0];445446InitGrid(grid);447448grid->nonodes = 2;449grid->xcells = 3;450grid->ycells = 1;451grid->wantedelems = 40;452grid->firstmaterial = 1;453grid->lastmaterial = 1;454grid->autoratio = 1;455grid->coordsystem = COORD_CART1;456grid->numbering = NUMBER_1D;457458grid->x[0] = 0.0;459grid->x[1] = 1.0;460grid->x[2] = 3.0;461grid->x[3] = 4.0;462463grid->xexpand[1] = 2.0;464grid->xexpand[3] = 0.5;465grid->xdens[2] = 0.5;466467for(j=1;j<=3;j++)468grid->structure[1][j] = 1;469470grid->noboundaries = 2;471grid->boundint[0] = 1;472grid->boundint[1] = 1;473474grid->boundext[0] = -1;475grid->boundext[1] = -2;476477grid->boundtype[0] = 1;478grid->boundtype[1] = 2;479480grid->boundsolid[0] = 1;481grid->boundsolid[1] = 1;482483grid->mappings = 0;484485if(info) printf("A simple 1D example mesh was created\n");486}487488489static void ExampleGrid2D(struct GridType **grids,int *nogrids,int info)490/* Creates an example grid that might be used to analyze491flow through a step. */492{493int j;494struct GridType *grid;495496(*nogrids) = 1;497(*grids) = (struct GridType*)498malloc((size_t) (*nogrids)*sizeof(struct GridType));499500grid = grids[0];501502InitGrid(grid);503504grid->xcells = 4;505grid->ycells = 3;506grid->wantedelems = 100;507grid->totxelems = grid->totyelems = grid->totzelems = 10;508grid->firstmaterial = 1;509grid->lastmaterial = 1;510grid->autoratio = 1;511grid->coordsystem = COORD_CART2;512grid->numbering = NUMBER_XY;513514grid->x[0] = -1.0;515grid->x[1] = 0.0;516grid->x[2] = 2.0;517grid->x[3] = 6.0;518grid->x[4] = 7.0;519520grid->y[0] = 0.0;521grid->y[1] = 0.5;522grid->y[2] = 0.75;523grid->y[3] = 1.0;524525grid->xexpand[2] = 0.4;526grid->xexpand[3] = 5.0;527528grid->yexpand[2] = 2.0;529grid->yexpand[3] = 0.5;530531for(j=1;j<=3;j++)532grid->structure[j][1] = 2;533for(j=1;j<=3;j++)534grid->structure[j][2] = 1;535grid->structure[1][2] = 0;536for(j=1;j<=3;j++)537grid->structure[j][3] = 1;538for(j=1;j<=3;j++)539grid->structure[j][4] = 3;540541grid->noboundaries = 3;542grid->boundint[0] = 1;543grid->boundint[1] = 1;544grid->boundint[2] = 1;545546grid->boundext[0] = 2;547grid->boundext[1] = 3;548grid->boundext[2] = 0;549550grid->boundtype[0] = 1;551grid->boundtype[1] = 2;552grid->boundtype[2] = 3;553554grid->boundsolid[0] = 1;555grid->boundsolid[1] = 1;556grid->boundsolid[2] = 1;557558grid->mappings = 2;559grid->mappingtype[0] = 1;560grid->mappingtype[1] = 1;561grid->mappingline[0] = 0;562grid->mappingline[1] = 3;563grid->mappinglimits[0] = grid->mappinglimits[1] = 0.5;564grid->mappinglimits[2] = grid->mappinglimits[3] = 0.5;565grid->mappingpoints[0] = grid->mappingpoints[1] = 4;566grid->mappingparams[0] = Rvector(0,grid->mappingpoints[0]);567grid->mappingparams[1] = Rvector(0,grid->mappingpoints[1]);568grid->mappingparams[0][0] = 2.0;569grid->mappingparams[0][1] = 0.0;570grid->mappingparams[0][2] = 6.0;571grid->mappingparams[0][3] = -0.2;572grid->mappingparams[1][0] = 0.0;573grid->mappingparams[1][1] = 0.0;574grid->mappingparams[1][2] = 6.0;575grid->mappingparams[1][3] = 0.3;576577if(info) printf("A simple 2D example mesh was created\n");578}579580581static void ExampleGrid3D(struct GridType **grids,int *nogrids,int info)582/* Creates an example grid that might be used to analyze583a simple acceleration sensor. */584{585int i,j;586struct GridType *grid;587588(*nogrids) = 1;589(*grids) = (struct GridType*)590malloc((size_t) (*nogrids)*sizeof(struct GridType));591592grid = grids[0];593594InitGrid(grid);595596grid->dimension = 3;597grid->coordsystem = COORD_CART3;598grid->layered = TRUE;599600grid->xcells = 4;601grid->ycells = 5;602grid->zcells = 5;603604grid->wantedelems = 1000;605grid->firstmaterial = 1;606grid->lastmaterial = 3;607grid->autoratio = 1;608grid->coordsystem = COORD_CART3;609grid->numbering = NUMBER_XY;610611grid->x[0] = 0.0;612grid->x[1] = 0.1;613grid->x[2] = 0.4;614grid->x[3] = 0.5;615grid->x[4] = 0.6;616617grid->y[0] = 0.0;618grid->y[1] = 0.1;619grid->y[2] = 0.2;620grid->y[3] = 0.4;621grid->y[4] = 0.5;622grid->y[5] = 0.6;623624grid->z[0] = 0.0;625grid->z[1] = 0.1;626grid->z[2] = 0.2;627grid->z[3] = 0.4;628grid->z[4] = 0.5;629grid->z[5] = 0.6;630631for(j=1;j<=5;j++)632for(i=1;i<=4;i++)633grid->structure[j][i] = 1;634635grid->structure[2][2] = 3;636grid->structure[2][3] = 3;637grid->structure[3][3] = 3;638grid->structure[4][3] = 3;639grid->structure[4][2] = 3;640641grid->structure[3][2] = 2;642643grid->zlastmaterial[5] = 3;644grid->zlastmaterial[2] = 1;645grid->zlastmaterial[3] = 2;646grid->zlastmaterial[4] = 1;647grid->zlastmaterial[5] = 3;648649grid->zmaterial[1] = 1;650grid->zmaterial[2] = 2;651grid->zmaterial[3] = 3;652grid->zmaterial[4] = 4;653grid->zmaterial[5] = 5;654655grid->noboundaries = 4;656grid->boundint[0] = 1;657grid->boundint[1] = 1;658grid->boundint[2] = 1;659grid->boundint[2] = 2;660661grid->boundext[0] = 0;662grid->boundext[1] = 2;663grid->boundext[2] = 3;664grid->boundext[3] = 3;665666grid->boundtype[0] = 1;667grid->boundtype[1] = 2;668grid->boundtype[2] = 3;669grid->boundtype[3] = 4;670671grid->boundsolid[0] = 1;672grid->boundsolid[1] = 1;673grid->boundsolid[2] = 1;674grid->boundsolid[3] = 1;675676if(info) printf("A simple 3D example mesh was created\n");677}678679680void CreateExampleGrid(int dim,struct GridType **grids,int *nogrids,int info)681{682switch (dim) {683684case 1:685ExampleGrid1D(grids,nogrids,info);686break;687688case 2:689ExampleGrid2D(grids,nogrids,info);690break;691692case 3:693ExampleGrid3D(grids,nogrids,info);694break;695}696}697698699700701void SetElementDivision(struct GridType *grid,Real relh,int info)702/* Given the densities and ratios in each cell finds the703optimum way to divide the mesh into elements.704The procedure is the following:705For each subcell set the minimum number of elements706then add one element at a time till the number of707elements is the desired one. The added element708is always set to the subcell having the sparsest mesh.709Also numbers the cells taking into consideration only710materials that have indices in interval [firstmat,lastmat].711*/712{713int i,j,nx,ny,nxmax = 0,nymax = 0;714int sumxelems,sumyelems,sumxyelems;715int wantedelems,wantedelemsx,wantedelemsy;716Real ratio,linearlimit;717Real dxmax = 0,dymax = 0,dx = 0,dy = 0,dxlimit = 0;718719if(0) printf("SetElementDivision\n");720721if(grid->dimension == 1)722grid->numbering = NUMBER_1D;723724nx = grid->xcells;725ny = grid->ycells;726linearlimit = 0.001;727728/* Lets number the cells from left to right and up to down. */729grid->nocells = 0;730for(j=1;j<=ny;j++)731for(i=1;i<=nx;i++) {732if (grid->structure[j][i] >= grid->firstmaterial &&733grid->structure[j][i] <= grid->lastmaterial)734grid->numbered[j][i] = ++grid->nocells;735}736if(0) printf("The mesh is divided into %d separate subcells.\n",grid->nocells);737738/* Put the linearity flags. */739for(i=1; i<= nx ;i++) {740if (fabs(1.-grid->xexpand[i]) < linearlimit)741grid->xlinear[i] = TRUE;742else if (fabs(1.+grid->xexpand[i]) < linearlimit)743grid->xlinear[i] = TRUE;744else745grid->xlinear[i] = FALSE;746}747748for(i=1; i <= ny ;i++) {749if(fabs(1.-grid->yexpand[i]) < linearlimit)750grid->ylinear[i] = TRUE;751else if(fabs(1.+grid->yexpand[i]) < linearlimit)752grid->ylinear[i] = TRUE;753else754grid->ylinear[i] = FALSE;755}756757758/* If there are no materials no elements either.759Otherwise at least grid->minelems elements760If you want to number elements even if they are761not there change this initialization to minelems. */762if(grid->autoratio) {763for(i=1;i<=nx;i++)764grid->xelems[i] = grid->minxelems;765for(i=1;i<=ny;i++)766grid->yelems[i] = grid->minyelems;767}768else {769for(i=1;i<=nx;i++)770if(grid->xelems[i] < grid->minxelems) grid->xelems[i] = grid->minxelems;771for(i=1;i<=ny;i++)772if(grid->yelems[i] < grid->minyelems) grid->yelems[i] = grid->minyelems;773}774775sumxelems = 0;776for(i=1;i<=nx;i++) {777if(grid->dimension == 1 && !grid->numbered[1][i]) continue;778sumxelems += grid->xelems[i];779}780sumyelems = 0;781for(i=1;i<=ny;i++)782sumyelems += grid->yelems[i];783784if(grid->dimension == 1) {785grid->autoratio = 2;786grid->totxelems = grid->wantedelems;787grid->totyelems = 1;788}789790/* Allocate elements for both axis separately */791if(grid->autoratio == 2) {792793wantedelemsx = (int) (1.0*grid->totxelems / relh);794wantedelemsy = (int) (1.0*grid->totyelems / relh);795796if(sumxelems > wantedelemsx) {797printf("SetElementDivision: %d is too few elements in x-direction\n",grid->totxelems);798wantedelemsx = sumxelems+1;799}800if(sumyelems > wantedelemsy ) {801printf("SetElementDivision: %d is too few elements in y-direction\n",grid->totyelems);802wantedelemsy = sumyelems+1;803}804805for(;sumxelems < wantedelemsx;) {806dxmax = 0.0;807for(i=1;i<=nx;i++) {808if(grid->xelems[i] == 0) continue;809810/* Don't put elements to passive subcells */811if(grid->dimension == 1 && !grid->numbered[1][i]) continue;812813if(grid->xlinear[i] == TRUE || grid->xelems[i]==1)814dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];815else {816if(grid->xexpand[i] > 0.0) {817ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));818dx = (grid->x[i] - grid->x[i-1]) *819(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));820if(ratio < 1.)821dx *= grid->xexpand[i];822}823else {824if(grid->xelems[i]==2) {825dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];826}827else if(grid->xelems[i]%2 == 0) {828ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));829dx = 0.5 * (grid->x[i] - grid->x[i-1]) *830(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));831}832else if(grid->xelems[i]%2 == 1) {833ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));834dx = (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}840dx *= grid->xdens[i];841if(dx > dxmax) {842dxmax = dx;843nxmax = i;844}845}846grid->xelems[nxmax] += 1;847sumxelems++;848}849850851if(grid->dimension > 1) {852for(;sumyelems < wantedelemsy;) {853dymax = 0.0;854for(i=1;i<=ny;i++) {855if(grid->yelems[i] == 0) continue;856if(grid->ylinear[i] || grid->yelems[i]==1)857dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];858else {859ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1));860dy = (grid->y[i] - grid->y[i-1]) *861(1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));862if(ratio < 1.)863dy *= grid->yexpand[i];864}865dy *= grid->ydens[i];866if(dy > dymax) {867dymax = dy;868nymax = i;869}870}871grid->yelems[nymax] += 1;872sumyelems++;873}874}875}876877878/* Both axis dependently */879if(grid->autoratio == 1) {880881wantedelems = (int) (1.0*grid->wantedelems / (relh*relh));882883sumxyelems = 0;884for(;;) {885dxmax = 0.0;886887for(i=1;i<=nx;i++) {888889if(grid->xelems[i] == 0) continue;890if(grid->xlinear[i] || grid->xelems[i]==1)891dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];892else {893if(grid->xexpand[i] > 0.0) {894ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));895dx = (grid->x[i] - grid->x[i-1]) *896(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));897if(ratio < 1.)898dx *= grid->xexpand[i];899}900else if(grid->xelems[i]==2) {901dx = (grid->x[i] - grid->x[i-1])/grid->xelems[i];902}903else if(grid->xelems[i]%2 == 0) {904ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));905dx = 0.5 * (grid->x[i] - grid->x[i-1]) *906(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));907}908else if(grid->xelems[i]%2 == 1) {909ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));910dx = (grid->x[i] - grid->x[i-1]) /911(2.0*(1.-pow(ratio,(Real)(grid->xelems[i]/2)))/912(1-ratio) + pow(ratio,(Real)(grid->xelems[i]/2+0.5)));913}914}915916dx *= grid->xdens[i];917if(dx > dxmax) {918dxmax = dx;919nxmax = i;920}921}922923924dymax = 0.0;925for(i=1;i<=ny;i++) {926927if(grid->yelems[i] == 0) continue;928if(grid->ylinear[i] || grid->yelems[i]==1)929dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];930else {931if(grid->yexpand[i] > 0.0) {932ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1));933dy = (grid->y[i] - grid->y[i-1]) *934(1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));935if(ratio < 1.)936dy *= grid->yexpand[i];937}938else if(grid->yelems[i]==2) {939dy = (grid->y[i] - grid->y[i-1])/grid->yelems[i];940}941else if(grid->yelems[i]%2 == 0) {942ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2-1.));943dy = 0.5 * (grid->y[i] - grid->y[i-1]) *944(1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2)));945}946else if(grid->yelems[i]%2 == 1) {947ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));948dy = (grid->y[i] - grid->y[i-1]) /949(2.0*(1.-pow(ratio,(Real)(grid->yelems[i]/2)))/950(1-ratio) + pow(ratio,(Real)(grid->yelems[i]/2+0.5)));951}952}953dy *= grid->ydens[i];954if(dy > dymax) {955dymax = dy;956nymax = i;957}958}959dymax /= grid->xyratio;960961if(dxmax > dymax) {962grid->xelems[nxmax] += 1;963sumxelems++;964dxlimit = dxmax;965}966else {967grid->yelems[nymax] += 1;968sumyelems++;969dxlimit = dymax;970}971972sumxyelems = 0;973for(j=1;j<=grid->ycells;j++)974for(i=1;i<=grid->xcells;i++)975if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];976977if(wantedelems <= sumxyelems) break;978}979}980981982983if(grid->autoratio == 3 || grid->limitdxverify) {984985if(grid->autoratio == 3) {986dxlimit = relh * grid->limitdx;987dxmax = dymax = dxlimit;988}989990for(i=1;i<=nx;i++) {991992for(;;) {993if(grid->xlinear[i] || grid->xelems[i]==0)994dx = (grid->x[i] - grid->x[i-1])/(grid->xelems[i]+1);995else {996if(grid->xexpand[i] > 0.0) {997ratio = pow(grid->xexpand[i],1./grid->xelems[i]);998dx = (grid->x[i] - grid->x[i-1]) *999(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]+1)));1000if(ratio < 1.)1001dx *= grid->xexpand[i];1002}1003else if(grid->xelems[i]==1) {1004dx = (grid->x[i] - grid->x[i-1])/(grid->xelems[i]+1);1005}1006else if((grid->xelems[i]+1)%2 == 0) {1007ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));1008dx = 0.5 * (grid->x[i] - grid->x[i-1]) *1009(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2+1)));1010}1011else if((grid->xelems[i]+1)%2 == 1) {1012ratio = pow(-grid->xexpand[i],1./((grid->xelems[i]+1)/2));1013dx = (grid->x[i] - grid->x[i-1]) /1014(2.0*(1.-pow(ratio,(Real)((grid->xelems[i]+1)/2)))/1015(1-ratio) + pow(ratio,(Real)((grid->xelems[i]+1)/2+0.5)));1016}1017}1018dx *= grid->xdens[i];10191020/* choose the best fit for desired density */1021if(fabs(dx-dxlimit) < fabs( dx*(1+1.0/grid->xelems[i]) -dxlimit) )1022grid->xelems[i] += 1;1023else1024break;1025}1026sumxelems += grid->xelems[i];1027}102810291030for(i=1;i<=ny;i++) {10311032for(;;) {1033if(grid->ylinear[i] || grid->yelems[i]==0)1034dy = (grid->y[i] - grid->y[i-1])/(grid->yelems[i]+1);1035else {1036if(grid->yexpand[i] > 0.0) {1037ratio = pow(grid->yexpand[i],1./grid->yelems[i]);1038dy = (grid->y[i] - grid->y[i-1]) *1039(1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]+1)));1040if(ratio < 1.)1041dy *= grid->yexpand[i];1042}1043else if(grid->yelems[i]==1) {1044dy = (grid->y[i] - grid->y[i-1])/(grid->yelems[i]+1);1045}1046else if((grid->yelems[i]+1)%2 == 0) {1047ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));1048dy = 0.5 * (grid->y[i] - grid->y[i-1]) *1049(1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2+1)));1050}1051else if((grid->yelems[i]+1)%2 == 1) {1052ratio = pow(-grid->yexpand[i],1./((grid->yelems[i]+1)/2));1053dy = (grid->y[i] - grid->y[i-1]) /1054(2.0*(1.-pow(ratio,(Real)((grid->yelems[i]+1)/2)))/1055(1-ratio) + pow(ratio,(Real)((grid->yelems[i]+1)/2+0.5)));1056}1057}10581059dy *= grid->ydens[i] / grid->xyratio;1060/* choose the best fit for desired density */1061if(fabs(dy-dxlimit) < fabs( dy*(1+1.0/grid->yelems[i]) -dxlimit) )1062grid->yelems[i] += 1;1063else1064break;1065}1066sumyelems += grid->yelems[i];1067}10681069sumxyelems = 0;1070for(j=1;j<=grid->ycells;j++)1071for(i=1;i<=grid->xcells;i++)1072if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];1073}107410751076/* Put the linearity flags if there is only one division. */1077for(i=1; i<= nx ;i++)1078if (grid->xelems[i] == 1)1079grid->xlinear[i] = TRUE;1080for(i=1; i <= ny ;i++)1081if(grid->yelems[i] == 1)1082grid->ylinear[i] = TRUE;108310841085/* Set the size of the first element within each subcell */1086for(i=1;i<=nx;i++) {10871088if(grid->xlinear[i] == TRUE)1089grid->dx[i] = (grid->x[i] - grid->x[i-1])/grid->xelems[i];1090else {1091if(grid->xexpand[i] > 0.0) {1092ratio = pow(grid->xexpand[i],1./(grid->xelems[i]-1.));1093grid->xratios[i] = ratio;1094grid->dx[i] = (grid->x[i] - grid->x[i-1]) *1095(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i])));1096}1097else if(grid->xelems[i] == 2) {1098grid->dx[i] = (grid->x[i] - grid->x[i-1])/grid->xelems[i];1099}1100else if(grid->xelems[i]%2 == 0) {1101ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2-1.));1102grid->xratios[i] = ratio;1103grid->dx[i] = 0.5 * (grid->x[i] - grid->x[i-1]) *1104(1.-ratio) / (1.-pow(ratio,(Real)(grid->xelems[i]/2)));1105}1106else if(grid->xelems[i]%2 == 1) {1107ratio = pow(-grid->xexpand[i],1./(grid->xelems[i]/2));1108grid->xratios[i] = ratio;1109grid->dx[i] = (grid->x[i] - grid->x[i-1]) /1110(2.0*(1.-pow(ratio,(Real)(grid->xelems[i]/2)))/1111(1-ratio) + pow(ratio,(Real)(grid->xelems[i]/2+0.5)));1112}1113}1114}11151116for(i=1;i<=ny;i++) {11171118if(grid->ylinear[i] == TRUE)1119grid->dy[i] = (grid->y[i] - grid->y[i-1])/grid->yelems[i];1120else {1121if(grid->yexpand[i] > 0.0) {1122ratio = pow(grid->yexpand[i],1./(grid->yelems[i]-1.));1123grid->yratios[i] = ratio;1124grid->dy[i] = (grid->y[i] - grid->y[i-1]) *1125(1.-ratio)/(1.-pow(ratio,(Real)(grid->yelems[i])));1126}1127else if(grid->yelems[i] == 2) {1128grid->dy[i] = (grid->y[i] - grid->y[i-1])/grid->yelems[i];1129}1130else if(grid->yelems[i]%2 == 0) {1131ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2-1.));1132grid->yratios[i] = ratio;1133grid->dy[i] = 0.5 * (grid->y[i] - grid->y[i-1]) *1134(1.-ratio) / (1.-pow(ratio,(Real)(grid->yelems[i]/2)));1135}1136else if(grid->yelems[i]%2 == 1) {1137ratio = pow(-grid->yexpand[i],1./(grid->yelems[i]/2));1138grid->yratios[i] = ratio;1139grid->dy[i] = (grid->y[i] - grid->y[i-1]) /1140(2.0*(1.-pow(ratio,(Real)(grid->yelems[i]/2)))/1141(1-ratio) + pow(ratio,(Real)(grid->yelems[i]/2+0.5)));1142}1143}1144}11451146/* Calculate the total number of elements */1147sumxyelems = 0;1148for(j=1;j<=grid->ycells;j++)1149for(i=1;i<=grid->xcells;i++)1150if(grid->numbered[j][i]) sumxyelems += grid->xelems[i] * grid->yelems[j];11511152grid->noelements = sumxyelems;11531154if(0) printf("Created a total of %d elements\n",sumxyelems);11551156grid->dx0 = dxmax;1157grid->dy0 = dymax;1158}11591160116111621163void SetCellData(struct GridType *grid,struct CellType *cell,int info)1164/* Sets the data that can directly be derived from type GridType.1165*/1166{1167int i,j,cnew=0;11681169for(j=1;j<= grid->ycells ;j++) /* cells direction up */1170for(i=1;i<= grid->xcells; i++) /* cells direction right */1171if( (cnew = grid->numbered[j][i]) ) { /* if cell is occupied */11721173/* Initialize the numbering to zero */1174cell[cnew].left1st = 0;1175cell[cnew].left2nd = 0;1176cell[cnew].leftlast = 0;1177cell[cnew].levelwidth = 0;1178cell[cnew].levelwidthcenter = 0;1179cell[cnew].leftcenter = 0;1180cell[cnew].elemwidth = 0;1181cell[cnew].elem1st = 0;11821183/* Set the element type */1184cell[cnew].nonodes = grid->nonodes;1185cell[cnew].numbering = grid->numbering;11861187/* Set the cell coordinates */1188cell[cnew].xcorner[TOPLEFT] = cell[cnew].xcorner[BOTLEFT] = grid->x[i-1];1189cell[cnew].xcorner[TOPRIGHT] = cell[cnew].xcorner[BOTRIGHT] = grid->x[i];1190cell[cnew].ycorner[BOTRIGHT] = cell[cnew].ycorner[BOTLEFT] = grid->y[j-1];1191cell[cnew].ycorner[TOPRIGHT] = cell[cnew].ycorner[TOPLEFT] = grid->y[j];11921193/* Set the cell width in both directions */1194cell[cnew].xwidth = grid->x[i] - grid->x[i-1];1195cell[cnew].ywidth = grid->y[j] - grid->y[j-1];11961197/* Set the number of elements in a subcell */1198cell[cnew].xelem = grid->xelems[i];1199cell[cnew].yelem = grid->yelems[j];12001201/* Set the the ratio of elements when going left to right and down to up */1202cell[cnew].xratio = grid->xratios[i];1203cell[cnew].yratio = grid->yratios[j];1204cell[cnew].xlinear = grid->xlinear[i];1205cell[cnew].ylinear = grid->ylinear[j];1206cell[cnew].xlinear = grid->xlinear[i];1207cell[cnew].ylinear = grid->ylinear[j];1208if(grid->xexpand[i] < 0.0 && grid->xlinear[i] == FALSE) {1209if(grid->xelems[i] == 2) cell[cnew].xlinear = 1;1210else cell[cnew].xlinear = 2;1211}1212if(grid->yexpand[j] < 0.0 && grid->ylinear[j] == FALSE) {1213if(grid->yelems[j] == 2) cell[cnew].ylinear = 1;1214else cell[cnew].ylinear = 2;1215}12161217/* Set the length of the first element in both directions */1218cell[cnew].dx1 = grid->dx[i];1219cell[cnew].dy1 = grid->dy[j];12201221/* Set the material in question */1222cell[cnew].material = grid->structure[j][i];12231224/* Set the boundary types for sides and corners */1225cell[cnew].boundary[LEFT] = grid->structure[j][i-1];1226cell[cnew].boundary[DOWN] = grid->structure[j-1][i];1227cell[cnew].boundary[RIGHT]= grid->structure[j][i+1];1228cell[cnew].boundary[UP] = grid->structure[j+1][i];1229cell[cnew].boundary[4] = grid->structure[j-1][i-1];1230cell[cnew].boundary[5] = grid->structure[j-1][i+1];1231cell[cnew].boundary[6] = grid->structure[j+1][i+1];1232cell[cnew].boundary[7] = grid->structure[j+1][i-1];12331234/* Set the neighbour cell indices for sides and corners */1235cell[cnew].neighbour[LEFT] = grid->numbered[j][i-1];1236cell[cnew].neighbour[DOWN] = grid->numbered[j-1][i];1237cell[cnew].neighbour[RIGHT]= grid->numbered[j][i+1];1238cell[cnew].neighbour[UP] = grid->numbered[j+1][i];1239cell[cnew].neighbour[4] = grid->numbered[j-1][i-1];1240cell[cnew].neighbour[5] = grid->numbered[j-1][i+1];1241cell[cnew].neighbour[6] = grid->numbered[j+1][i+1];1242cell[cnew].neighbour[7] = grid->numbered[j+1][i-1];1243}12441245if(info) printf("%d cells were created.\n",grid->nocells);1246}1247124812491250static int SetCellKnots(struct GridType *grid, struct CellType *cell,int info)1251/* Uses given mesh to number the knots present in the cells.1252The knots are numbered independently of the cells from left1253to right and up to down. Only the numbers of four knots at the1254left side of each cell are saved for later use. The number of1255each knot can later be easily recalled using simple functions.1256The subroutine was initially written for ordering the knots1257from left to right and down to up. However, this does not always1258produce reasonably small bandwidth and therefore a numbering1259scheme for the other order was later added. Therefore the algorithm1260may not be that clear for this other scheme.1261Numbers the knots in rectangular elements. There may be12624, 5, 8, 9, 12 or 16 nodes in each elements.1263*/1264{1265int i,j,level,center;1266int degree,centernodes,sidenodes,nonodes;1267int cnew=0,cup=0,cleft=0,cleftup=0;1268int elemno,knotno;1269int maxwidth,width,numbering;1270int xcells,ycells,*yelems=NULL,*xelems=NULL;12711272numbering = grid->numbering;1273nonodes = grid->nonodes;1274knotno = 0;1275elemno = 0;12761277if(numbering == NUMBER_XY) {1278xcells = grid->xcells;1279ycells = grid->ycells;1280xelems = grid->xelems;1281yelems = grid->yelems;1282}1283else if(numbering == NUMBER_YX) {1284xcells = grid->ycells;1285ycells = grid->xcells;1286xelems = grid->yelems;1287yelems = grid->xelems;1288}1289else {1290printf("No %d numbering scheme exists!\n",numbering);1291return(1);1292}12931294switch (nonodes) {1295case 4:1296centernodes = FALSE;1297sidenodes = FALSE;1298degree = 1;1299break;1300case 5:1301centernodes = TRUE;1302sidenodes = FALSE;1303degree = 2;1304break;1305case 8:1306centernodes = FALSE;1307sidenodes = TRUE;1308degree = 2;1309break;1310case 9:1311centernodes = TRUE;1312sidenodes = TRUE;1313degree = 2;1314break;1315case 12:1316centernodes = FALSE;1317sidenodes = TRUE;1318degree = 3;1319break;1320case 16:1321centernodes = TRUE;1322sidenodes = TRUE;1323degree = 3;1324break;1325default:1326printf("SetCellKnots: No numbering scheme for %d-node elements.\n",1327grid->nonodes);1328return(2);1329}13301331for(j=1;j<= ycells ;j++) /* cells direction up */1332for(level=0; level <= yelems[j] ;level++) /* lines inside cells */1333for(center=0; center < degree; center++)1334for(i=1;i<= xcells; i++) /* cells direction right */1335{1336if(numbering == NUMBER_XY) {1337cnew = grid->numbered[j][i];1338cleft= grid->numbered[j][i-1];1339cup = grid->numbered[j+1][i];1340cleftup = grid->numbered[j+1][i-1];1341if(cnew) {1342cell[cnew].xind = i;1343cell[cnew].yind = j;1344}1345}1346else if(numbering == NUMBER_YX) {1347cnew = grid->numbered[i][j];1348cleft= grid->numbered[i-1][j];1349cup = grid->numbered[i][j+1];1350cleftup = grid->numbered[i-1][j+1];1351if(cnew) {1352cell[cnew].xind = j;1353cell[cnew].yind = i;1354}1355}13561357if(center == 0) {1358/* the first line of an occupied cell is unnumbered,1359this happens only in the bottom */1360if (cnew && level==0 && !cell[cnew].left1st) {1361if(!cleft) knotno++;1362cell[cnew].left1st = knotno;1363if(sidenodes)1364knotno += degree * xelems[i];1365else1366knotno += xelems[i];1367} /* level=0 */13681369/* the n:th line of an occupied cell */1370else if (cnew && level > 0 && level < yelems[j]) {1371if(!cleft) knotno++;1372if(level==1)1373cell[cnew].left2nd = knotno;1374if(level==2)1375cell[cnew].levelwidth = knotno - cell[cnew].left2nd;1376if(sidenodes)1377knotno += degree * xelems[i];1378else1379knotno += xelems[i];1380} /* 1 <= level < n */13811382/* last line of this cell or first line of upper cell */1383else if ((cnew || cup) && level == yelems[j]) {1384if(!cleft && !cleftup)1385knotno++;1386if(cnew)1387cell[cnew].leftlast = knotno;1388if(level==2)1389cell[cnew].levelwidth = knotno - cell[cnew].left2nd;1390if(yelems[j] == 1)1391cell[cnew].left2nd = cell[cnew].leftlast;1392if(cup)1393cell[cup].left1st = knotno;1394if(sidenodes)1395knotno += degree * xelems[i];1396else1397knotno += xelems[i];1398} /* level=n */13991400/* Number the elements */1401if(cnew && level > 0) {1402if(level==1)1403cell[cnew].elem1st = elemno+1;1404if(level==2)1405cell[cnew].elemwidth = (elemno+1) - cell[cnew].elem1st;1406elemno += xelems[i];1407}1408}14091410if(center && level < yelems[j]) {1411if (cnew) {1412if(!cleft && sidenodes)1413knotno++;1414if(level==0 && center==1)1415cell[cnew].leftcenter = knotno;1416if(level==0 && center==2)1417cell[cnew].left2center = knotno;1418if(level==1 && center==1)1419cell[cnew].levelwidthcenter = knotno - cell[cnew].leftcenter;1420if(centernodes && sidenodes)1421knotno += degree * xelems[i];1422else1423knotno += xelems[i];1424}1425}14261427} /* x-cell loop */142814291430maxwidth = 0;1431for(j=1;j<= ycells ;j++)1432for(i=1;i<= xcells; i++) {1433if(numbering == NUMBER_XY)1434cnew = grid->numbered[j][i];1435else if(numbering == NUMBER_YX)1436cnew = grid->numbered[i][j];1437if(cnew) {1438width = cell[cnew].left2nd - cell[cnew].left1st;1439if(width > maxwidth)1440maxwidth = width;1441width = cell[cnew].levelwidth;1442if(width > maxwidth)1443maxwidth = width;1444width = cell[cnew].leftlast-cell[cnew].left2nd1445-(yelems[j]-2)*cell[cnew].levelwidth;1446if(width > maxwidth)1447maxwidth = width;1448}1449}1450maxwidth += 2;14511452grid->maxwidth = maxwidth;1453grid->noknots = knotno;1454grid->noelements = elemno;14551456if(info) {1457printf("Numbered %d knots in %d %d-node elements.\n",knotno,elemno,nonodes);1458if(numbering == NUMBER_XY)1459printf("Numbering order was <x><y> and max levelwidth %d.\n",1460maxwidth);1461else if(numbering == NUMBER_YX)1462printf("Numbering order was <y><x> and max levelwidth %d.\n",1463maxwidth);1464}14651466return(0);1467}1468146914701471static int SetCellKnots1D(struct GridType *grid, struct CellType *cell,int info)1472{1473int i;1474int degree,nonodes;1475int cnew,cleft;1476int elemno,knotno;1477int maxwidth;1478int xcells,*xelems;14791480nonodes = grid->nonodes;1481knotno = 0;1482elemno = 0;14831484xcells = grid->xcells;1485xelems = grid->xelems;14861487switch (nonodes) {1488case 2:1489degree = 1;1490break;1491case 3:1492degree = 2;1493break;1494case 4:1495degree = 3;1496break;14971498default:1499printf("SetCellKnots1D: No numbering scheme for %d-node elements.\n",1500grid->nonodes);1501return(2);1502}15031504for(i=1;i<= xcells; i++) {15051506cnew = grid->numbered[1][i];1507cleft= grid->numbered[1][i-1];1508if(cnew) cell[cnew].xind = i;15091510if (cnew) {1511/* Number the nodes */1512if(!cleft) knotno++;1513cell[cnew].left1st = knotno;1514knotno += degree * xelems[i];15151516/* Number the elements */1517cell[cnew].elem1st = elemno+1;1518elemno += xelems[i];1519}1520} /* x-cell loop */15211522maxwidth = degree;15231524grid->maxwidth = maxwidth;1525grid->noknots = knotno;1526grid->noelements = elemno;15271528if(info) {1529printf("Numbered %d knots in %d %d-node elements.\n",knotno,elemno,nonodes);1530}15311532return(0);1533}1534153515361537void CreateCells(struct GridType *grid,struct CellType **cell,int info)1538{1539(*cell) = (struct CellType*)1540malloc((size_t) (grid->nocells+1)*sizeof(struct CellType));15411542SetCellData(grid,*cell,info);15431544if(grid->dimension == 1)1545SetCellKnots1D(grid,*cell,info);1546else1547SetCellKnots(grid,*cell,info);1548}154915501551void DestroyCells(struct CellType **cell)1552{1553free(cell);1554}1555155615571558int GetKnotIndex(struct CellType *cell,int i,int j)1559/* Given the cell and knot indices gives the corresponding1560global knot index. The indices are expected to be in the1561range [0..n] and [0..m]. Requires only the structure CellType.1562*/1563{1564int ind=0,aid=0,maxj=0;15651566if(cell->numbering == NUMBER_1D) {1567ind = cell->left1st;1568if(cell->nonodes == 2)1569ind += i;1570else if(cell->nonodes == 3)1571ind += 2*i;1572else if(cell->nonodes == 4)1573ind += 3*i;1574return(ind);1575}15761577if(cell->numbering == NUMBER_XY)1578maxj = cell->yelem;1579else if(cell->numbering == NUMBER_YX) {1580aid = j; j = i; i = aid;1581maxj = cell->xelem;1582}1583else {1584maxj = 0;1585bigerror("GetKnotIndex: Unknown numbering scheme!");1586}15871588if(j == 0)1589ind = cell->left1st;1590else if (j == maxj)1591ind = cell->leftlast;1592else1593ind = cell->left2nd + (j-1) * cell->levelwidth;15941595if(cell->nonodes == 4)1596ind += i;1597else if(cell->nonodes == 5)1598ind += i;1599else if(cell->nonodes == 8 || cell->nonodes == 9)1600ind += 2*i;1601else if(cell->nonodes == 12 || cell->nonodes == 16)1602ind += 3*i;16031604return(ind);1605}160616071608int GetKnotCoordinate(struct CellType *cell,int i,int j,Real *x,Real *y)1609/* Given the cell and element indices inside the cell gives the1610corresponding global knot numbers. The indices are expected1611to be in the range [0..n] and [0..m]. Requires only the1612structure CellType.1613*/1614{1615int ind;16161617if(cell->xlinear == 1)1618(*x) = cell->xcorner[BOTLEFT] + cell->dx1 * i;1619else if(cell->xlinear == 0)1620(*x) = cell->xcorner[BOTLEFT] + cell->dx1 *1621(1.- pow(cell->xratio,(Real)(i))) / (1.-cell->xratio);1622else if(cell->xlinear == 2) {1623if(i<=cell->xelem/2) {1624(*x) = cell->xcorner[BOTLEFT] + cell->dx1 *1625(1.- pow(cell->xratio,(Real)(i))) / (1.-cell->xratio);1626}1627else {1628(*x) = cell->xcorner[BOTRIGHT] - cell->dx1 *1629(1.- pow(cell->xratio,(Real)(cell->xelem-i))) / (1.-cell->xratio);1630}1631}16321633if(cell->ylinear == 1)1634(*y) = cell->ycorner[BOTLEFT] + cell->dy1 * j;1635else if(cell->ylinear == 0)1636(*y) = cell->ycorner[BOTLEFT] + cell->dy1 *1637(1.- pow(cell->yratio,(Real)(j))) / (1.-cell->yratio);1638else if(cell->ylinear == 2) {1639if(j<=cell->yelem/2) {1640(*y) = cell->ycorner[BOTLEFT] + cell->dy1 *1641(1.- pow(cell->yratio,(Real)(j))) / (1.-cell->yratio);1642}1643else {1644(*y) = cell->ycorner[TOPLEFT] - cell->dy1 *1645(1.- pow(cell->yratio,(Real)(cell->yelem-j))) / (1.-cell->yratio);1646}1647}16481649ind = GetKnotIndex(cell,i,j);16501651return(ind);1652}1653165416551656int GetElementIndices(struct CellType *cell,int i,int j,int *ind)1657/* For given element gives the coordinates and index for each knot.1658The indices i and j are expected to range from [1..n] and [1..m].1659requires only the structure CellType.1660*/1661{1662int nonodes,numbering,elemind=0;16631664nonodes = cell->nonodes;1665numbering = cell->numbering;16661667if(numbering != NUMBER_1D) {1668ind[TOPRIGHT] = GetKnotIndex(cell,i,j);1669ind[BOTRIGHT] = GetKnotIndex(cell,i,j-1);1670ind[TOPLEFT] = GetKnotIndex(cell,i-1,j);1671ind[BOTLEFT] = GetKnotIndex(cell,i-1,j-1);1672}16731674if(numbering == NUMBER_XY) {1675elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;1676if(nonodes == 4) return(elemind);16771678if(nonodes == 5) {1679ind[4] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;1680}1681else if(nonodes == 8) {1682ind[4] = ind[0]+1;1683ind[6] = ind[3]+1;1684ind[5] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;1685ind[7] = ind[5]-1;1686}1687else if(nonodes == 9) {1688ind[4] = ind[0]+1;1689ind[6] = ind[3]+1;1690ind[5] = cell->leftcenter + (j-1) * cell->levelwidthcenter + 2*i;1691ind[7] = ind[5]-2;1692ind[8] = ind[5]-1;1693}1694else if(nonodes == 12) {1695ind[4] = ind[0]+1;1696ind[5] = ind[0]+2;1697ind[9] = ind[3]+1;1698ind[8] = ind[3]+2;1699ind[6] = cell->leftcenter + (j-1) * cell->levelwidthcenter + i;1700ind[11] = ind[6]-1;1701ind[7] = cell->left2center + (j-1) * cell->levelwidthcenter + i;1702ind[10] = ind[7]-1;1703}1704else if(nonodes == 16) {1705ind[4] = ind[0]+1;1706ind[5] = ind[0]+2;1707ind[9] = ind[3]+1;1708ind[8] = ind[3]+2;1709ind[6] = cell->leftcenter + (j-1) * cell->levelwidthcenter + 3*i;1710ind[11] = ind[6]-3;1711ind[7] = cell->left2center + (j-1) * cell->levelwidthcenter + 3*i;1712ind[10] = ind[7]-3;1713ind[13] = ind[6]-1;1714ind[12] = ind[6]-2;1715ind[14] = ind[7]-1;1716ind[15] = ind[7]-2;1717}1718else1719printf("GetElementIndices: not implemented for %d nodes.\n",nonodes);1720}17211722else if(numbering == NUMBER_YX) {1723elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;17241725if(nonodes == 4) return(elemind);17261727if(nonodes == 5) {1728ind[4] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;1729}1730else if (nonodes==8) {1731ind[7] = ind[0]+1;1732ind[5] = ind[1]+1;1733ind[6] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;1734ind[4] = ind[6]-1;1735}1736else if(nonodes == 9) {1737ind[7] = ind[0]+1;1738ind[5] = ind[1]+1;1739ind[6] = cell->leftcenter + (i-1) * cell->levelwidthcenter + 2*j;1740ind[4] = ind[6]-2;1741ind[8] = ind[6]-1;1742}1743else if(nonodes == 12) {1744ind[11]= ind[0]+1;1745ind[10]= ind[0]+2;1746ind[6] = ind[1]+1;1747ind[7] = ind[1]+2;1748ind[9] = cell->leftcenter + (i-1) * cell->levelwidthcenter + j;1749ind[4] = ind[9]-1;1750ind[8] = cell->left2center + (i-1) * cell->levelwidthcenter + j;1751ind[5] = ind[8]-1;1752}1753else if(nonodes == 16) {1754ind[11]= ind[0]+1;1755ind[10]= ind[0]+2;1756ind[6] = ind[1]+1;1757ind[7] = ind[1]+2;1758ind[9] = cell->leftcenter + (i-1) * cell->levelwidthcenter + 3*j;1759ind[4] = ind[9]-3;1760ind[15]= ind[9]-1;1761ind[12]= ind[9]-2;1762ind[8] = cell->left2center + (i-1) * cell->levelwidthcenter + 3*j;1763ind[5] = ind[8]-3;1764ind[14]= ind[8]-1;1765ind[13]= ind[8]-2;1766}1767else1768printf("GetElementIndices: not implemented for %d nodes.\n",nonodes);1769}17701771else if(numbering == NUMBER_1D) {1772elemind = cell->elem1st+(i-1);1773ind[0] = GetKnotIndex(cell,i-1,1);1774if(nonodes == 2) {1775ind[1] = ind[0] + 1;1776}1777else if(nonodes == 3) {1778ind[2] = ind[0] + 1;1779ind[1] = ind[0] + 2;1780}1781else if(nonodes == 4) {1782ind[2] = ind[0] + 1;1783ind[3] = ind[0] + 2;1784ind[1] = ind[0] + 3;1785}1786}1787return(elemind);1788}178917901791int GetElementIndex(struct CellType *cell,int i,int j)1792/* For given element gives the element index.1793The indices i and j are expected to range from [1..n] and [1..m].1794requires only the structure CellType.1795*/1796{1797int elemind=0;17981799if(cell->numbering == NUMBER_XY)1800elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;1801else if(cell->numbering == NUMBER_YX)1802elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;18031804return(elemind);1805}1806180718081809int GetElementCoordinates(struct CellType *cell,int i,int j,1810Real *globalcoord,int *ind)1811/* For given element gives the coordinates and index for each knot.1812The indices i and j are expected to range from [1..n] and [1..m].1813requires only the structure CellType1814Note that this subroutine assumes that the elements are1815rectangular.1816*/1817{1818int k,nonodes,numbering,elemind=0;1819Real xrat,yrat;18201821k = nonodes = cell->nonodes;1822numbering = cell->numbering;18231824if(numbering == NUMBER_1D) {1825elemind = cell->elem1st+(i-1);1826ind[0] = GetKnotCoordinate(cell,i-1,j-1,&globalcoord[0],1827&globalcoord[nonodes]);1828ind[1] = GetKnotCoordinate(cell,i,j-1,&globalcoord[1],1829&globalcoord[nonodes+1]);18301831if(nonodes == 3) {1832globalcoord[2] = (globalcoord[0]+globalcoord[1])/2.0;1833globalcoord[5] = (globalcoord[3]+globalcoord[4])/2.0;1834ind[2] = ind[0] + 1;1835}1836else if(nonodes == 4) {1837globalcoord[2] = (2.0*globalcoord[0]+globalcoord[1])/3.0;1838globalcoord[6] = (2.0*globalcoord[4]+globalcoord[5])/3.0;1839ind[2] = ind[0] + 1;1840globalcoord[3] = (globalcoord[0]+2.0*globalcoord[1])/3.0;1841globalcoord[7] = (globalcoord[4]+2.0*globalcoord[5])/3.0;1842ind[3] = ind[0] + 2;1843}18441845return(elemind);1846}1847else if(numbering == NUMBER_XY)1848elemind = cell->elem1st+(i-1) + (j-1)*cell->elemwidth;1849else if(numbering == NUMBER_YX)1850elemind = cell->elem1st+(j-1) + (i-1)*cell->elemwidth;185118521853ind[TOPRIGHT] = GetKnotCoordinate(cell,i,j,&globalcoord[TOPRIGHT],1854&globalcoord[TOPRIGHT+nonodes]);1855ind[BOTRIGHT] = GetKnotCoordinate(cell,i,j-1,&globalcoord[BOTRIGHT],1856&globalcoord[BOTRIGHT+nonodes]);1857ind[TOPLEFT] = GetKnotCoordinate(cell,i-1,j,&globalcoord[TOPLEFT],1858&globalcoord[TOPLEFT+nonodes]);1859ind[BOTLEFT] = GetKnotCoordinate(cell,i-1,j-1,&globalcoord[BOTLEFT],1860&globalcoord[BOTLEFT+nonodes]);1861if(nonodes == 4) return(elemind);18621863GetElementIndices(cell,i,j,ind);18641865#if 01866if(cell->xlinear)1867xrat = 1.0;1868else1869xrat = sqrt(cell->xratio);18701871if(cell->ylinear)1872yrat = 1.0;1873else1874yrat = sqrt(cell->yratio);1875#endif1876xrat = yrat = 1.0;18771878if(nonodes == 5) {1879globalcoord[4] = 0.5*(globalcoord[0]+globalcoord[2]);1880globalcoord[4+k] = 0.5*(globalcoord[k]+globalcoord[2+k]);1881}1882else if(nonodes == 8 || nonodes == 9) {1883globalcoord[4] = (xrat*globalcoord[0]+globalcoord[1])/(1+xrat);1884globalcoord[4+k] = globalcoord[k];1885globalcoord[5] = globalcoord[1];1886globalcoord[5+k] =1887(yrat*globalcoord[1+k]+globalcoord[2+k])/(1+yrat);1888globalcoord[6] = globalcoord[4];1889globalcoord[6+k] = globalcoord[2+k];1890globalcoord[7] = globalcoord[3];1891globalcoord[7+k] = globalcoord[5+k];1892if(nonodes == 9) {1893globalcoord[8] = globalcoord[4];1894globalcoord[8+k] = globalcoord[5+k];1895}1896}1897else if(nonodes == 12 || nonodes == 16) {1898globalcoord[4] = (2.*globalcoord[0]+globalcoord[1])/3.0;1899globalcoord[4+k] = (2.*globalcoord[k]+globalcoord[1+k])/3.0;1900globalcoord[5] = (2.*globalcoord[1]+globalcoord[0])/3.0;1901globalcoord[5+k] = (2.*globalcoord[1+k]+globalcoord[k])/3.0;1902globalcoord[6] = (2.*globalcoord[1]+globalcoord[2])/3.0;1903globalcoord[6+k] = (2.*globalcoord[1+k]+globalcoord[2+k])/3.0;1904globalcoord[7] = (2.*globalcoord[2]+globalcoord[1])/3.0;1905globalcoord[7+k] = (2.*globalcoord[2+k]+globalcoord[1+k])/3.0;1906globalcoord[8] = (2.*globalcoord[2]+globalcoord[3])/3.0;1907globalcoord[8+k] = (2.*globalcoord[2+k]+globalcoord[3+k])/3.0;1908globalcoord[9] = (2.*globalcoord[3]+globalcoord[2])/3.0;1909globalcoord[9+k] = (2.*globalcoord[3+k]+globalcoord[2+k])/3.0;1910globalcoord[10] = (2.*globalcoord[3]+globalcoord[0])/3.0;1911globalcoord[10+k] = (2.*globalcoord[3+k]+globalcoord[k])/3.0;1912globalcoord[11] = (2.*globalcoord[0]+globalcoord[3])/3.0;1913globalcoord[11+k] = (2.*globalcoord[k]+globalcoord[3+k])/3.0;1914if(nonodes == 16) {1915globalcoord[12] = (2.*globalcoord[11]+globalcoord[6])/3.0;1916globalcoord[12+k] = (2.*globalcoord[11+k]+globalcoord[6+k])/3.0;1917globalcoord[13] = (2.*globalcoord[6]+globalcoord[11])/3.0;1918globalcoord[13+k] = (2.*globalcoord[6+k]+globalcoord[11+k])/3.0;1919globalcoord[14] = (2.*globalcoord[7]+globalcoord[10])/3.0;1920globalcoord[14+k] = (2.*globalcoord[7+k]+globalcoord[10+k])/3.0;1921globalcoord[15] = (2.*globalcoord[10]+globalcoord[7])/3.0;1922globalcoord[15+k] = (2.*globalcoord[10+k]+globalcoord[7+k])/3.0;1923}1924}19251926#if 01927for(i=0;i<k;i++)1928printf("ind[%d]=%d x=%.4lg y=%.4lg\n",i,ind[i],1929globalcoord[i],globalcoord[i+k]);1930#endif19311932return(elemind);1933}193419351936int GetSideInfo(struct CellType *cell,int cellno,int side,int element,1937int *elemind)1938/* Given the side and element numbers returns the indices of1939the side element. When the end of the side is reached the function1940returns FALSE, otherwise TRUE.1941*/1942{1943int more,sideno;1944int ind[MAXNODESD2];19451946more = TRUE;19471948if(cell[cellno].numbering == NUMBER_1D) {19491950switch(side) {1951case 0:1952more = FALSE;1953elemind[0] = GetElementIndices(&(cell[cellno]),1,element,&(ind[0]));1954if((sideno = cell[cellno].neighbour[LEFT]))1955elemind[1] = GetElementIndices(&(cell[sideno]),cell[sideno].xelem,element,&(ind[0]));1956else1957elemind[1] = 0;1958break;195919601961case 1:1962more = FALSE;1963elemind[0] = GetElementIndices(&(cell)[cellno],cell[cellno].xelem,element,&(ind[0]));1964if((sideno = cell[cellno].neighbour[RIGHT]))1965elemind[1] = GetElementIndices(&(cell[sideno]),1,element,&(ind[0]));1966else1967elemind[1] = 0;1968break;1969}19701971return(more);1972}197319741975switch(side) {19761977case LEFT:1978if(element == cell[cellno].yelem) more = FALSE;1979elemind[0] = GetElementIndices(&(cell[cellno]),1,element,&(ind[0]));1980if((sideno = cell[cellno].neighbour[LEFT]))1981elemind[1] = GetElementIndices(&(cell[sideno]),cell[sideno].xelem,element,&(ind[0]));1982else1983elemind[1] = 0;1984break;19851986case RIGHT:1987if(element == cell[cellno].yelem) more = FALSE;1988elemind[0] = GetElementIndices(&(cell)[cellno],cell[cellno].xelem,element,&(ind[0]));1989if((sideno = cell[cellno].neighbour[RIGHT]))1990elemind[1] = GetElementIndices(&(cell[sideno]),1,element,&(ind[0]));1991else1992elemind[1] = 0;1993break;19941995case DOWN:1996if(element == cell[cellno].xelem) more = FALSE;1997elemind[0] = GetElementIndices(&(cell)[cellno],element,1,&(ind[0]));1998if((sideno = cell[cellno].neighbour[DOWN]))1999elemind[1] = GetElementIndices(&(cell[sideno]),element,cell[sideno].yelem,&(ind[0]));2000else2001elemind[1] = 0;2002break;20032004case UP:2005if(element == cell[cellno].xelem) more = FALSE;2006elemind[0] = GetElementIndices(&(cell)[cellno],element,cell[cellno].yelem,&(ind[0]));2007if((sideno = cell[cellno].neighbour[UP]))2008elemind[1] = GetElementIndices(&(cell[sideno]),element,1,&(ind[0]));2009else2010elemind[1] = 0;2011break;20122013default:2014printf("Impossible option in GetSideInfo.\n");2015}20162017return(more);2018}2019202020212022void SetElementDivisionExtruded(struct GridType *grid,int info)2023{2024int i,nzmax = 0,sumzelems;2025Real ratio,linearlimit;2026Real dzmax = 0,dz = 0;20272028linearlimit = 0.001;20292030if(grid->autoratio) {2031for(i=1;i<=grid->zcells;i++)2032grid->zelems[i] = grid->minzelems;2033}2034else {2035for(i=1;i<=grid->zcells;i++)2036if(grid->zelems[i] < grid->minzelems) grid->zelems[i] = grid->minzelems;2037}20382039sumzelems = grid->zcells * grid->minzelems;2040if(sumzelems > grid->totzelems) {2041#if 02042printf("SetElementDivision: %d is too few elements in z-direction (min. %d)\n",2043grid->totzelems,sumzelems);2044#endif2045grid->totzelems = sumzelems;2046}20472048/* Put the linearity flags. */2049for(i=1; i<= grid->zcells ;i++) {2050if (fabs(1.-grid->zexpand[i]) < linearlimit)2051grid->zlinear[i] = TRUE;2052else2053grid->zlinear[i] = FALSE;2054}20552056if(grid->autoratio) {2057int active;2058for(;;) {2059dzmax = 0.0;2060active = FALSE;20612062for(i=1;i<=grid->zcells;i++) {2063if(grid->zelems[i] == 0) continue;2064if(grid->zlinear[i] == TRUE)2065dz = (grid->z[i] - grid->z[i-1])/(grid->zelems[i]+1);2066else {2067if(grid->zexpand[i] > 0.0) {2068ratio = pow(grid->zexpand[i],1./(1.*grid->zelems[i]));2069dz = (grid->z[i] - grid->z[i-1]) *2070(1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]+1)));2071if(ratio < 1.)2072dz *= grid->zexpand[i];2073}2074else if(grid->zelems[i]==1) {2075dz = (grid->z[i] - grid->z[i-1])/(grid->zelems[i]+1);2076}2077else if((grid->zelems[i]+1)%2 == 0) {2078ratio = pow(-grid->zexpand[i],1./((grid->zelems[i]+1)/2-1.));2079dz = 0.5 * (grid->z[i] - grid->z[i-1]) *2080(1.-ratio) / (1.-pow(ratio,(Real)((grid->zelems[i]+1)/2)));2081}2082else if((grid->zelems[i]+1)%2 == 1) {2083ratio = pow(-grid->zexpand[i],1./((grid->zelems[i]+1)/2));2084dz = (grid->z[i] - grid->z[i-1]) /2085(2.0*(1.-pow(ratio,(Real)((grid->zelems[i]+1)/2)))/2086(1-ratio) + pow(ratio,(Real)((grid->zelems[i]+1)/2+0.5)));2087}2088}2089dz *= grid->zdens[i] / grid->xzratio;20902091if(dz > dzmax) {2092dzmax = dz;2093nzmax = i;2094}20952096if(grid->autoratio) {2097if(fabs(dz - grid->dx0) < fabs( dz*(1.0/(1.0-1.0/grid->zelems[i])) - grid->dx0) ) {2098grid->zelems[i] += 1;2099sumzelems++;2100active = TRUE;2101}2102}2103}21042105if(grid->autoratio) {2106if(!active) break;2107}2108else {2109grid->zelems[nzmax] += 1;2110sumzelems++;2111if(sumzelems >= grid->totzelems) break;2112}2113}2114}21152116/* Set the size of the first element within each subcell */2117grid->totzelems = 0;2118for(i=1;i<=grid->zcells;i++) {2119grid->totzelems += grid->zelems[i];2120if(grid->zlinear[i] == TRUE || grid->zelems[i]==1)2121grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];2122else if(grid->zexpand[i] > 0.0) {2123ratio = pow(grid->zexpand[i],1./(grid->zelems[i]-1.));2124grid->zratios[i] = ratio;2125grid->dz[i] = (grid->z[i] - grid->z[i-1]) *2126(1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i])));2127}2128else if(grid->zelems[i] == 2) {2129grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];2130}2131else if(grid->zelems[i]%2 == 0) {2132ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2-1.));2133grid->zratios[i] = ratio;2134grid->dz[i] = 0.5 * (grid->z[i] - grid->z[i-1]) *2135(1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]/2)));2136}2137else if(grid->zelems[i]%2 == 1) {2138ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2));2139grid->zratios[i] = ratio;2140grid->dz[i] = (grid->z[i] - grid->z[i-1]) /2141(2.0*(1.-pow(ratio,(Real)(grid->zelems[i]/2)))/2142(1-ratio) + pow(ratio,(Real)(grid->zelems[i]/2+0.5)));2143}2144}21452146if(info) printf("Created %d extruded divisions.\n",2147grid->totzelems);2148grid->dz0 = dzmax;2149}2150215121522153void SetElementDivisionCylinder(struct GridType *grid,int info)2154{2155int i,k;2156Real ratio,eps;2157Real dzmax;21582159eps = 1.0e-8;21602161grid->zcells = 2*grid->rotateblocks;2162grid->z[0] = 0.0;2163for(i=0;grid->x[i]<eps;i++); k=i;2164grid->rotateradius1 = grid->x[k];21652166if(grid->rotateradius2 < 0.0) {2167grid->rotatecartesian = TRUE;2168grid->rotateradius2 = 1.0e6;2169}2170if(grid->rotateradius2 <= sqrt(2.0)*grid->rotateradius1) {2171if(k+1 <= grid->xcells)2172grid->rotateradius2 = grid->x[k+1];2173grid->rotateradius2 = MAX(sqrt(2.0)*grid->rotateradius1,2174grid->rotateradius2);2175}21762177if(!grid->xlinear[k])2178printf("SetElementDivisionCylinder: The division must be linear!\n");21792180for(i=1;i<=grid->zcells;i++) {2181grid->z[i] = i*(2.0*FM_PI)/8.0;2182grid->zelems[i] = grid->xelems[k];2183grid->zlinear[i] = grid->xlinear[k];2184grid->zratios[i] = grid->xratios[k];2185grid->zexpand[i] = grid->xexpand[k];2186grid->zmaterial[i] = 0;2187}21882189grid->totzelems = grid->zcells * grid->xelems[k];21902191dzmax = 0.0;2192for(i=1;i<=grid->zcells;i++) {2193if(grid->zlinear[i] == TRUE || grid->zelems[i]==1)2194grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];2195else if(grid->zexpand[i] > 0.0) {2196ratio = pow(grid->zexpand[i],1./(grid->zelems[i]-1.));2197grid->zratios[i] = ratio;2198grid->dz[i] = (grid->z[i] - grid->z[i-1]) *2199(1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i])));2200}2201else if(grid->zelems[i] == 2) {2202grid->dz[i] = (grid->z[i] - grid->z[i-1])/grid->zelems[i];2203}2204else if(grid->zelems[i]%2 == 0) {2205ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2-1.));2206grid->zratios[i] = ratio;2207grid->dz[i] = 0.5 * (grid->z[i] - grid->z[i-1]) *2208(1.-ratio) / (1.-pow(ratio,(Real)(grid->zelems[i]/2)));2209}2210else if(grid->zelems[i]%2 == 1) {2211ratio = pow(-grid->zexpand[i],1./(grid->zelems[i]/2));2212grid->zratios[i] = ratio;2213grid->dz[i] = (grid->z[i] - grid->z[i-1]) /2214(2.0*(1.-pow(ratio,(Real)(grid->zelems[i]/2)))/2215(1-ratio) + pow(ratio,(Real)(grid->zelems[i]/2+0.5)));2216}22172218if(dzmax < grid->dz[i]) dzmax = grid->dz[i];2219}22202221if(info) printf("Created %d divisions in %d cells for rotation [%.2lg %.2lg].\n",2222grid->totzelems,grid->zcells,2223grid->rotateradius1,grid->rotateradius2);2224grid->dz0 = dzmax;2225}2226222722282229static int GetCommand(char *line1,char *line2,FILE *io)2230/* Line1 for commands and line2 for arguments. */2231{2232int i,j,isend;2233char line0[MAXLINESIZE],*charend,*matcpntr0,*matcpntr;2234int gotlinefeed;22352236newline:22372238for(i=0;i<MAXLINESIZE;i++)2239line2[i] = line1[i] = line0[i] = 0x00;22402241charend = fgets(line0,MAXLINESIZE,io);2242isend = (charend == NULL);22432244if(isend) return(1);22452246if(strlen(line0)<=strspn(line0," \t\r\n")) goto newline;22472248if(line0[0] == '#' || line0[0] == '%' || line0[0] == '!' || line0[0] == '\n') goto newline;2249if(!matcactive && line0[0] == '*') goto newline;22502251if(!matcactive && strchr(line0,'$') ) {2252#if USE_MATC2253printf("\n a $ found and MATC has been compiled but not activated,\n");2254printf("either remove the $ or add 'MATC = True' to grd input file.\n");2255#else2256printf("\n a $ found and MATC has not been compiled into ElmerGrid,\n");2257printf("either remove the $ or compile ElmerGrid with MATC\n");2258#endif // USE_MATC2259bigerror("Error: $ found in command and MATC is not active");2260}22612262#if USE_MATC2263if(matcactive) {2264matcpntr0 = strchr(line0,'$');2265if(matcpntr0) {2266matcpntr = mtc_domath(&matcpntr0[1]);2267if(matcpntr) {2268strcpy(matcpntr0, matcpntr);2269if(0) printf("B: %s\n%s\n",matcpntr0,matcpntr);2270}2271else {2272if(0) printf("B0: %s\n",matcpntr0);2273goto newline;2274}2275}2276}2277#endif22782279gotlinefeed = FALSE;2280j = 0;2281for(i=0;i<MAXLINESIZE;i++) {2282if(line0[i] == '\n' || line0[i] == '\0' ) {2283gotlinefeed = TRUE;2284break;2285}2286if(line0[i] == '=') {2287j = i;2288break;2289}2290line1[i] = toupper(line0[i]);2291}22922293/* After these commands there will be no nextline even though there is no equality sign */2294if(strstr(line1,"END")) return(0);2295if(strstr(line1,"NEW MESH")) return(0);22962297if(j) { /* Arguments are actually on the same line after '=' */2298for(i=j+1;i<MAXLINESIZE;i++) {2299line2[i-j-1] = line0[i];2300if( line0[i] == '\n' || line0[i] == '\0' ) {2301gotlinefeed = TRUE;2302break;2303}2304}2305if(!gotlinefeed) {2306printf("There is a risk that somethings was missed in line:\n");2307printf("%s\n",line0);2308smallerror("Check your output line length!\n");2309}2310}2311else { /* Arguments are on the next line */2312newline2:2313charend = fgets(line2,MAXLINESIZE,io);2314isend = (charend == NULL);2315if(isend) return(2);2316if(line2[0] == '#' || line2[0] == '%' || line2[0] == '!') goto newline2;2317if(!matcactive && line2[0] == '*') goto newline2;23182319gotlinefeed = FALSE;2320for(i=0;i<MAXLINESIZE;i++) {2321if(line2[i] == '\n' || line2[i] == '\0' ) {2322gotlinefeed = TRUE;2323break;2324}2325}2326if(!gotlinefeed) {2327printf("There is a risk that somethings was missed in line:\n");2328printf("%s\n",line2);2329smallerror("Check your output line length!\n");2330}23312332if(!matcactive && strchr(line0,'$') ) {2333#if USE_MATC2334printf("\n a $ found and MATC has been compiled but not activated,\n");2335printf("either remove the $ or add 'MATC = True' to grd input file.\n");2336#else2337printf("\n a $ found and MATC has not been compiled into ElmerGrid,\n");2338printf("either remove the $ or compile ElmerGrid with MATC\n");2339#endif // USE_MATC2340bigerror("Error: $ found in command and MATC is not active");2341}23422343#if USE_MATC2344if(matcactive) {2345matcpntr0 = strchr(line2,'$');2346if(matcpntr0) {2347matcpntr = mtc_domath(&matcpntr0[1]);2348if(matcpntr) {2349strcpy(matcpntr0, matcpntr);2350if(0) printf("C: %s\n%s\n",matcpntr0,matcpntr);2351}2352}2353}2354#endif2355}23562357if(iodebug) {2358printf("command: %s\n",line1);2359printf("params: %s\n",line2);2360}23612362return(0);2363}2364236523662367int SaveElmergrid(struct GridType *grid,int nogrids,char *prefix,int info)2368{2369int sameline,maxsameline;2370int i,j,dim;2371FILE *out;2372char filename[MAXFILESIZE];23732374AddExtension(prefix,filename,"grd");2375out = fopen(filename,"w");2376dim = grid->dimension;2377if(grid->coordsystem == COORD_CART1) dim = 1;23782379j = 0;2380sameline = TRUE;2381maxsameline = 6;2382if(grid->xcells > maxsameline) sameline = FALSE;2383if(dim >= 2 && grid->ycells > maxsameline) sameline = FALSE;2384if(dim >= 3 && grid->zcells > maxsameline) sameline = FALSE;23852386fprintf(out,"##### ElmerGrid input file for structured grid generation ######\n");2387fprintf(out,"Version = 210903\n");23882389fprintf(out,"Coordinate System = ");2390if(grid->coordsystem == COORD_AXIS)2391fprintf(out,"2D Axisymmetric\n");2392else if(grid->coordsystem == COORD_POLAR)2393fprintf(out,"2D Polar\n");2394else2395fprintf(out,"Cartesian %dD\n",dim);23962397fprintf(out,"Subcell Divisions in %dD = ",dim);2398if(dim >= 1) fprintf(out,"%d ",grid->xcells);2399if(dim >= 2) fprintf(out,"%d ",grid->ycells);2400if(dim >= 3) fprintf(out,"%d ",grid->zcells);2401fprintf(out,"\n");24022403fprintf(out,"Subcell Limits 1 %s",sameline ? "= ":"\n ");2404for(i=0;i <= grid->xcells;i++)2405fprintf(out,"%.5lg ",grid->x[i]);2406fprintf(out,"\n");24072408if(dim >= 2) {2409fprintf(out,"Subcell Limits 2 %s",sameline ? "= ":"\n ");2410for(i=0;i <= grid->ycells;i++)2411fprintf(out,"%.5lg ",grid->y[i]);2412fprintf(out,"\n");2413}24142415if(dim >= 3) {2416fprintf(out,"Subcell Limits 3 %s",sameline ? "= ":"\n ");2417for(i=0;i <= grid->zcells;i++)2418fprintf(out,"%.5lg ",grid->z[i]);2419fprintf(out,"\n");2420}24212422fprintf(out,"Material Structure in %dD\n",dim==1 ? 1:2);2423for(j=grid->ycells;j>=1;j--) {2424fprintf(out," ");2425for(i=1;i<=grid->xcells;i++)2426fprintf(out,"%-5d",grid->structure[j][i]);2427fprintf(out,"\n");2428}2429fprintf(out,"End\n");24302431if(grid->mappings > 0) {2432fprintf(out,"Geometry Mappings\n");2433fprintf(out,"# mode line limits(2) Np params(Np)\n");2434for(i=0;i<grid->mappings;i++) {2435fprintf(out," %-5d %-5d %-7.5lg %-7.5lg %-3d ",2436grid->mappingtype[i],grid->mappingline[i],2437grid->mappinglimits[2*i],grid->mappinglimits[2*i+1],2438grid->mappingpoints[i]);2439for(j=0;j<grid->mappingpoints[i];j++)2440fprintf(out,"%.4lg ",grid->mappingparams[i][j]);2441fprintf(out,"\n");2442}2443fprintf(out,"End\n");2444}24452446j = 0;2447if(grid[j].rotate) {2448fprintf(out,"Revolve Blocks = %d\n",grid[j].rotateblocks);2449fprintf(out,"Revolve Radius = %-8.3lg\n",grid[j].rotateradius2);2450if(fabs(grid[j].rotateimprove-1.0) > 1.0e-10)2451fprintf(out,"Revolve Improve = %-8.3lg\n",grid[j].rotateimprove);24522453}2454if(grid[j].rotatecurve) {2455fprintf(out,"Revolve Curve Direct = %-8.3lg\n",grid[j].curvezet);2456fprintf(out,"Revolve Curve Radius = %-8.3lg\n",grid[j].curverad);2457fprintf(out,"Revolve Curve Angle = %-8.3lg\n",grid[j].curveangle);2458}24592460if(grid[j].coordsystem == COORD_POLAR) {2461fprintf(out,"Polar Radius = %.3lg\n",grid[j].polarradius);2462}24632464for(j=0;j<nogrids;j++) {24652466if(j>0) fprintf(out,"\nStart New Mesh\n");24672468fprintf(out,"Materials Interval = %d %d\n",2469grid[j].firstmaterial,grid[j].lastmaterial);24702471if(dim == 3) {2472fprintf(out,"Extruded Structure\n");2473fprintf(out,"# %-8s %-8s %-8s\n","1stmat", "lastmat","newmat");2474for(i=1;i<=grid[j].zcells;i++)2475fprintf(out," %-8d %-8d %-8d\n",2476grid[j].zfirstmaterial[i],grid[j].zlastmaterial[i],2477grid[j].zmaterial[i]);2478fprintf(out,"End\n");2479}24802481if(grid[j].noboundaries > 0) {2482fprintf(out,"Boundary Definitions\n");2483fprintf(out,"# %-8s %-8s %-8s\n","type","out","int");2484for(i=0;i<grid[j].noboundaries;i++)2485fprintf(out," %-8d %-8d %-8d %-8d\n",2486grid[j].boundtype[i],grid[j].boundext[i],2487grid[j].boundint[i], grid[j].boundsolid[i]);2488fprintf(out,"End\n");2489}24902491if(grid->numbering == NUMBER_XY)2492fprintf(out,"Numbering = Horizontal\n");2493if(grid->numbering == NUMBER_YX)2494fprintf(out,"Numbering = Vertical\n");24952496fprintf(out,"Element Degree = %d\n",grid[j].elemorder);2497fprintf(out,"Element Innernodes = %s\n",grid[j].elemmidpoints ? "True" : "False");2498fprintf(out,"Triangles = %s\n",grid[j].triangles ? "True" : "False");2499if(grid[j].autoratio)2500fprintf(out,"Surface Elements = %d\n",grid[j].wantedelems);2501if(dim == 3 && grid[j].wantedelems3d)2502fprintf(out,"Volume Elements = %d\n",grid[j].wantedelems3d);2503if(dim == 3 && grid[j].wantednodes3d)2504fprintf(out,"Volume Nodes = %d\n",grid[j].wantednodes3d);25052506if(dim == 2)2507fprintf(out,"Coordinate Ratios = %-8.3lg\n",grid[j].xyratio);2508if(dim == 3)2509fprintf(out,"Coordinate Ratios = %-8.3lg %-8.3lg\n",2510grid[j].xyratio,grid[j].xzratio);25112512fprintf(out,"Minimum Element Divisions = %d",grid[j].minxelems);2513if(dim >= 2) fprintf(out," %d",grid[j].minyelems);2514if(dim >= 3) fprintf(out," %d",grid[j].minzelems);2515fprintf(out,"\n");25162517fprintf(out,"Element Ratios 1 %s",sameline ? "= ":"\n ");2518for(i=1;i<=grid[j].xcells;i++)2519fprintf(out,"%.3lg ",grid[j].xexpand[i]);2520fprintf(out,"\n");2521if(dim >= 2) {2522fprintf(out,"Element Ratios 2 %s",sameline ? "= ":"\n ");2523for(i=1;i<=grid[j].ycells;i++)2524fprintf(out,"%.3lg ",grid[j].yexpand[i]);2525fprintf(out,"\n");2526}2527if(dim >= 3) {2528fprintf(out,"Element Ratios 3 %s",sameline ? "= ":"\n ");2529for(i=1;i<=grid[j].zcells;i++)2530fprintf(out,"%.3lg ",grid[j].zexpand[i]);2531fprintf(out,"\n");2532}25332534if(grid[j].autoratio) {2535fprintf(out,"Element Densities 1 %s",sameline ? "= ":"\n ");2536for(i=1;i<=grid[j].xcells;i++)2537fprintf(out,"%.3lg ",grid[j].xdens[i]);2538fprintf(out,"\n");2539if(dim >= 2) {2540fprintf(out,"Element Densities 2 %s",sameline ? "= ":"\n ");2541for(i=1;i<=grid[j].ycells;i++)2542fprintf(out,"%.3lg ",grid[j].ydens[i]);2543fprintf(out,"\n");2544}2545if(dim >= 3) {2546fprintf(out,"Element Densities 3 %s",sameline ? "= ":"\n ");2547for(i=1;i<=grid[j].zcells;i++)2548fprintf(out,"%.3lg ",grid[j].zdens[i]);2549fprintf(out,"\n");2550}2551}2552else {2553fprintf(out,"Element Divisions 1 %s",sameline ? "= ":"\n ");2554for(i=1;i<=grid[j].xcells;i++)2555fprintf(out,"%d ",grid[j].xelems[i]);2556fprintf(out,"\n");2557if(dim >= 2) {2558fprintf(out,"Element Divisions 2 %s",sameline ? "= ":"\n ");2559for(i=1;i<=grid[j].ycells;i++)2560fprintf(out,"%d ",grid[j].yelems[i]);2561fprintf(out,"\n");2562}2563if(dim >= 3) {2564fprintf(out,"Element Divisions 3 %s",sameline ? "= ":"\n ");2565for(i=1;i<=grid[j].zcells;i++)2566fprintf(out,"%d ",grid[j].zelems[i]);2567fprintf(out,"\n");2568}2569}257025712572}25732574if(info) printf("The Elmergrid input was saved to file %s.\n",filename);2575fclose(out);25762577return(0);2578}257925802581258225832584static int LoadElmergridOld(struct GridType **grid,int *nogrids,char *prefix,int info)2585{2586char filename[MAXFILESIZE];2587FILE *in;2588int i,j,k,l,error=0;2589Real scaling;2590char *cp;2591int mode,noknots,noelements,dim,axisymmetric;2592int elemcode,maxnodes,totelems,nogrids0;2593int minmat,maxmat;2594char line[MAXLINESIZE];259525962597AddExtension(prefix,filename,"grd");2598if ((in = fopen(filename,"r")) == NULL) {2599printf("LoadElmergrid: opening of the file '%s' wasn't successful !\n",filename);2600return(1);2601}26022603if(info) printf("Loading the geometry from file '%s'.\n",filename);26042605InitGrid(grid[*nogrids]);2606k = *nogrids;2607nogrids0 = *nogrids;26082609mode = 0;2610noknots = 0;2611noelements = 0;2612dim = 0;2613axisymmetric = FALSE;2614elemcode = 0;2615maxnodes = 4;2616totelems = 0;2617scaling = 1.0;2618261926202621Getline(line,in);2622for(;;) {2623if(Getline(line,in)) goto end;2624if(line[0]=='\0') goto end;26252626if(strstr(line,"END")) goto end;2627if(strstr(line,"RESULTS")) goto end;26282629/* Control information */2630if(strstr(line,"VERSION")) mode = 1;2631else if(strstr(line,"GEOMETRY")) mode = 2;2632else if(strstr(line,"MAPPINGS IN")) mode = 31;2633else if(strstr(line,"MAPPINGS OUT")) mode = 32;2634else if(strstr(line,"MAPPINGS")) mode = 3;2635else if(strstr(line,"NUMBERING")) mode = 4;2636else if(strstr(line,"MESHING")) mode = 5;2637else if(strstr(line,"ELEMENTS")) mode = 6;2638else if(strstr(line,"ELEMENT NUMBER")) mode = 29;2639else if(strstr(line,"NODES")) mode = 7;2640else if(strstr(line,"TRIANGLE")) mode = 8;2641else if(strstr(line,"SQUARE")) mode = 17;2642else if(strstr(line,"COORDINATE RATIO")) mode = 10;2643else if(strstr(line,"MATERIALS")) mode = 11;2644else if(strstr(line,"LAYERED ST")) mode = 12;2645else if(strstr(line,"ELEMENT RAT")) mode = 13;2646else if(strstr(line,"ELEMENT DENS")) mode = 14;2647else if(strstr(line,"ELEMENT MINIMUM")) mode = 27;2648else if(strstr(line,"BOUNDARY COND")) mode = 15;2649else if(strstr(line,"ELEMENTTYPE") || strstr(line,"ELEMENTCODE")) mode = 16;2650else if(strstr(line,"ROTATE")) mode = 20;2651else if(strstr(line,"ROTRAD")) mode = 21;2652else if(strstr(line,"ROTBLOCK")) mode = 22;2653else if(strstr(line,"ROTIMP")) mode = 24;2654else if(strstr(line,"ROTCURVE")) mode = 25;2655else if(strstr(line,"REDUCE ELEMENT")) mode = 26;2656else if(strstr(line,"SCALING")) mode = 23;2657else if(strstr(line,"LAYERED BO")) mode = 28;2658else if(strstr(line,"POLAR RADIUS")) mode = 30;265926602661switch (mode) {2662case 1:2663printf("Loading Elmergrid file: %s\n",line);2664mode = 0;2665break;26662667case 2:2668grid[k]->dimension = 2;2669if(strstr(line,"CARTES") && strstr(line,"1D")) {2670grid[k]->coordsystem = COORD_CART1;2671grid[k]->dimension = 1;2672}2673else if(strstr(line,"CARTES") && strstr(line,"2D"))2674grid[k]->coordsystem = COORD_CART2;2675else if(strstr(line,"AXIS") && strstr(line,"2D"))2676grid[k]->coordsystem = COORD_AXIS;2677else if(strstr(line,"POLAR") && strstr(line,"2D"))2678grid[k]->coordsystem = COORD_POLAR;2679else if(strstr(line,"CARTES") && strstr(line,"3D")) {2680grid[k]->coordsystem = COORD_CART3;2681grid[k]->dimension = 3;2682}2683else if(strstr(line,"CYLINDRICAL")) {2684grid[k]->coordsystem = COORD_CYL;2685grid[k]->dimension = 3;2686}2687else printf("Unknown coordinate system: %s\n",line);2688printf("Defining the coordinate system (%d-DIM).\n",grid[k]->dimension);26892690Getline(line,in);26912692if(grid[k]->dimension == 1) {2693sscanf(line,"%d",&(*grid)[k].xcells);2694grid[k]->ycells = 1;2695}2696if(grid[k]->dimension == 2)2697sscanf(line,"%d %d",&(*grid)[k].xcells,&(*grid)[k].ycells);2698if(grid[k]->dimension == 3)2699sscanf(line,"%d %d %d",&(*grid)[k].xcells,&(*grid)[k].ycells,&(*grid)[k].zcells);2700if(grid[k]->xcells >= MAXCELLS || grid[k]->ycells >= MAXCELLS ||2701grid[k]->zcells >= MAXCELLS) {2702printf("LoadGrid: Too many subcells [%d %d %d] vs. %d:\n",2703grid[k]->xcells,grid[k]->ycells,grid[k]->zcells,MAXCELLS);2704}27052706if(grid[k]->dimension == 1) {2707printf("Loading [%d] subcell intervals in 1D\n",2708grid[k]->xcells);2709}2710else if(grid[k]->dimension == 2) {2711printf("Loading [%d %d] subcell intervals in 2D\n",2712grid[k]->xcells,grid[k]->ycells);2713} else {2714printf("Loading [%d %d %d] subcell intervals in 3D\n",2715grid[k]->xcells,grid[k]->ycells,grid[k]->zcells);2716}271727182719for(j=1;j<=grid[k]->dimension;j++) {2720Getline(line,in);2721cp=line;27222723if(j==1) for(i=0;i<=grid[k]->xcells;i++) grid[k]->x[i] = next_real(&cp);2724if(j==2) for(i=0;i<=grid[k]->ycells;i++) grid[k]->y[i] = next_real(&cp);2725if(j==3) for(i=0;i<=grid[k]->zcells;i++) grid[k]->z[i] = next_real(&cp);2726}27272728printf("Loading material structure\n");27292730for(j=grid[k]->ycells;j>=1;j--) {27312732Getline(line,in);2733cp=line;27342735for(i=1;i<=grid[k]->xcells;i++)2736grid[k]->structure[j][i] = next_int(&cp);2737}27382739minmat = maxmat = grid[k]->structure[1][1];2740for(j=grid[k]->ycells;j>=1;j--)2741for(i=1;i<=grid[k]->xcells;i++) {2742if(minmat > grid[k]->structure[j][i])2743minmat = grid[k]->structure[j][i];2744if(maxmat < grid[k]->structure[j][i])2745maxmat = grid[k]->structure[j][i];2746}2747if(minmat < 0)2748printf("LoadElmergrid: please use positive material indices.\n");27492750mode = 0;2751break;27522753case 3:2754case 31:2755case 32:27562757/* I don't know how to set this, luckily this piece of code should be obsolete */2758l = 1;2759for(i=grid[k]->mappings;i<grid[k]->mappings+l;i++) {2760Getline(line,in);2761cp=line;27622763grid[k]->mappingtype[i] = next_int(&cp);2764if(mode == 32) grid[k]->mappingtype[i] += 50*SGN(grid[k]->mappingtype[i]);27652766grid[k]->mappingline[i] = next_int(&cp);2767grid[k]->mappinglimits[2*i] = next_real(&cp);2768grid[k]->mappinglimits[2*i+1] = next_real(&cp);2769grid[k]->mappingpoints[i] = next_int(&cp);2770grid[k]->mappingparams[i] = Rvector(0,grid[k]->mappingpoints[i]);2771for(j=0;j<grid[k]->mappingpoints[i];j++)2772grid[k]->mappingparams[i][j] = next_real(&cp);2773}27742775printf("Loaded %d geometry mappings\n",l);2776grid[k]->mappings += l;27772778mode = 0;2779break;27802781case 4: /* NUMBERING */2782if(strstr(line,"HORIZ")) grid[k]->numbering = NUMBER_XY;2783if(strstr(line,"VERTI")) grid[k]->numbering = NUMBER_YX;2784mode = 0;2785break;27862787case 5: /* MESHING */2788if((*nogrids) >= MAXCASES) {2789printf("There are more grids than was allocated for!\n");2790printf("Ignoring meshes starting from %d\n.",(*nogrids)+1);2791goto end;2792}2793(*nogrids)++;2794printf("Loading element meshing no %d\n",*nogrids);2795k = *nogrids - 1;2796if(k > nogrids0) (*grid)[k] = (*grid)[k-1];2797mode = 0;2798break;27992800case 6: /* ELEMENTS */2801sscanf(line,"%d",&(*grid)[k].wantedelems);2802mode = 0;2803break;28042805case 7: /* NODES */2806sscanf(line,"%d",&(*grid)[k].nonodes);28072808(*grid)[k].elemmidpoints = FALSE;2809if((*grid)[k].nonodes == 4)2810(*grid)[k].elemorder = 1;2811if((*grid)[k].nonodes == 8)2812(*grid)[k].elemorder = 2;2813if((*grid)[k].nonodes == 16)2814(*grid)[k].elemorder = 3;28152816if((*grid)[k].nonodes == 9) {2817(*grid)[k].elemorder = 2;2818(*grid)[k].elemmidpoints = TRUE;2819}2820if((*grid)[k].nonodes == 12) {2821(*grid)[k].elemorder = 3;2822(*grid)[k].elemmidpoints = TRUE;2823}282428252826mode = 0;2827break;28282829case 8: /* TRIANGLES */2830(*grid)[k].triangles = TRUE;2831mode = 0;2832break;28332834case 17: /* SQUARES */2835(*grid)[k].triangles = FALSE;2836mode = 0;2837break;28382839case 16: /* ELEMENTTYPE and ELEMENTCODE */2840sscanf(line,"%d",&elemcode);2841if(elemcode/100 == 2) {2842(*grid)[k].triangles = FALSE;2843(*grid)[k].nonodes = elemcode%100;2844}2845else if(elemcode/100 == 4) {2846(*grid)[k].triangles = FALSE;2847(*grid)[k].nonodes = elemcode%100;2848}2849else if(elemcode/100 == 3) {2850(*grid)[k].triangles = TRUE;2851if(elemcode%100 == 3) (*grid)[k].nonodes = 4;2852else if(elemcode%100 == 6) (*grid)[k].nonodes = 9;2853else if(elemcode%100 == 10) (*grid)[k].nonodes = 16;2854}28552856(*grid)[k].elemmidpoints = FALSE;2857if((*grid)[k].nonodes == 4)2858(*grid)[k].elemorder = 1;2859if((*grid)[k].nonodes == 8)2860(*grid)[k].elemorder = 2;2861if((*grid)[k].nonodes == 16)2862(*grid)[k].elemorder = 3;28632864if((*grid)[k].nonodes == 9) {2865(*grid)[k].elemorder = 2;2866(*grid)[k].elemmidpoints = TRUE;2867}2868if((*grid)[k].nonodes == 12) {2869(*grid)[k].elemorder = 3;2870(*grid)[k].elemmidpoints = TRUE;2871}28722873mode = 0;2874break;28752876case 10: /* COORDINATE RATIO */2877if((*grid)[k].dimension == 2)2878sscanf(line,"%le",&(*grid)[k].xyratio);2879if((*grid)[k].dimension == 3)2880sscanf(line,"%le %le",&(*grid)[k].xyratio,&(*grid)[k].xzratio);2881mode = 0;2882break;28832884case 11: /* MATERIALS */2885sscanf(line,"%d %d",&(*grid)[k].firstmaterial,&(*grid)[k].lastmaterial);2886mode = 0;2887break;28882889case 12: /* LAYERES */2890for(i=1;i<=(*grid)[k].zcells;i++) {2891Getline(line,in);2892sscanf(line,"%d %d %d\n",2893&(*grid)[k].zfirstmaterial[i],&(*grid)[k].zlastmaterial[i],&(*grid)[k].zmaterial[i]);2894}2895mode = 0;2896break;28972898case 13: /* ELEMENT RATIOS */2899printf("Loading element ratios\n");29002901for (j=1;j<=(*grid)[k].dimension;j++) {2902Getline(line,in);2903cp = line;29042905if(j==1) for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xexpand[i] = next_real(&cp);2906if(j==2) for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yexpand[i] = next_real(&cp);2907if(j==3) for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zexpand[i] = next_real(&cp);2908}2909mode = 0;2910break;29112912case 29: /* ELEMENT NUMBER */2913printf("Loading element numbers\n");29142915for (j=1;j<=(*grid)[k].dimension;j++) {2916Getline(line,in);2917cp = line;2918if(j==1) for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xelems[i] = next_int(&cp);2919if(j==2) for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yelems[i] = next_int(&cp);2920if(j==3) for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zelems[i] = next_int(&cp);2921}2922(*grid)[k].autoratio = 0;2923mode = 0;2924break;29252926case 27: /* ELEMENT MINIMUM */2927printf("Loading minimum number of elements\n");2928if((*grid)[k].dimension == 1)2929sscanf(line,"%d",&(*grid)[k].minxelems);2930if((*grid)[k].dimension == 2)2931sscanf(line,"%d %d",&(*grid)[k].minxelems,&(*grid)[k].minyelems);2932if((*grid)[k].dimension == 3)2933sscanf(line,"%d %d %d",&(*grid)[k].minxelems,&(*grid)[k].minyelems,&(*grid)[k].minzelems);2934mode = 0;2935break;29362937case 14: /* ELEMENT DENSITIES */2938printf("Loading element densities\n");2939for (j=1;j<=(*grid)[k].dimension;j++) {2940Getline(line,in);2941cp = line;29422943if(j==1) for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xdens[i] = next_real(&cp);2944if(j==2) for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].ydens[i] = next_real(&cp);2945if(j==3) for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zdens[i] = next_real(&cp);2946}2947mode = 0;2948break;29492950case 15: /* BOUNDARY CONDITIONS */2951sscanf(line,"%d",&(*grid)[k].noboundaries);2952printf("Loading %d boundary conditions\n",(*grid)[k].noboundaries);29532954for(i=0;i<(*grid)[k].noboundaries;i++) {2955Getline(line,in);2956sscanf(line,"%d %d %d %d",2957&(*grid)[k].boundtype[i],&(*grid)[k].boundext[i],2958&(*grid)[k].boundint[i],&(*grid)[k].boundsolid[i]);2959}2960mode = 0;2961break;29622963case 20: /* ROTATE */2964(*grid)[k].rotate = TRUE;2965mode = 0;2966break;29672968case 21: /* ROTRAD */2969sscanf(line,"%le",&(*grid)[k].rotateradius2);2970mode = 0;2971break;29722973case 22: /* ROTBLOCK */2974sscanf(line,"%d",&(*grid)[k].rotateblocks);2975if(0) printf("Reading blocks %d\n",(*grid)[k].rotateblocks);2976mode = 0;2977break;29782979case 24: /* ROTIMP */2980sscanf(line,"%le",&(*grid)[k].rotateimprove);2981mode = 0;2982break;29832984case 30: /* POLAR RADIUS */2985sscanf(line,"%le",&(*grid)[k].polarradius);2986mode = 0;2987break;29882989case 25: /* ROTCURVE */2990(*grid)[k].rotatecurve = TRUE;2991sscanf(line,"%le%le%le",&(*grid)[k].curvezet,2992&(*grid)[k].curverad,&(*grid)[k].curveangle);2993mode = 0;2994break;29952996case 26: /* REDUCE ELEMENT */2997sscanf(line,"%d%d",&(*grid)[k].reduceordermatmin,2998&(*grid)[k].reduceordermatmax);2999mode = 0;3000break;30013002case 28: /* LAYERED BO */3003sscanf(line,"%d",&(*grid)[k].layeredbc);3004mode = 0;3005break;30063007case 23: /* SCALING */3008sscanf(line,"%le",&scaling);3009for(i=0;i<=(*grid)[k].xcells;i++) (*grid)[k].x[i] *= scaling;3010if((*grid)[k].dimension > 1)3011for(i=0;i<=(*grid)[k].ycells;i++) (*grid)[k].y[i] *= scaling;3012if((*grid)[k].dimension == 3)3013for(i=0;i<=(*grid)[k].ycells;i++) (*grid)[k].z[i] *= scaling;30143015(*grid)[k].rotateradius2 *= scaling;3016(*grid)[k].curverad *= scaling;3017(*grid)[k].curvezet *= scaling;3018mode = 0;3019break;30203021default:3022if(0) printf("Unknown case: %s",line);3023}30243025}30263027end:30283029if(info) printf("Found %d divisions for grid\n",*nogrids);30303031for(k=nogrids0;k < (*nogrids) && k<MAXCASES;k++) {3032SetElementDivision(&(*grid)[k],1.0,info);3033}303430353036fclose(in);3037return(error);3038}3039304030413042int LoadElmergrid(struct GridType **grid,int *nogrids,char *prefix,int info)3043{3044char filename[MAXFILESIZE];3045char command[MAXLINESIZE],params[MAXLINESIZE];3046FILE *in;3047int i,j,k;3048char *cp;3049int noknots,noelements,dim,axisymmetric;3050int elemcode,maxnodes,totelems,nogrids0,minmat,maxmat;3051long code;3052Real raid;30533054AddExtension(prefix,filename,"grd");3055if ((in = fopen(filename,"r")) == NULL) {3056printf("LoadElmergrid: opening of the file '%s' wasn't successful !\n",filename);3057return(1);3058}30593060if(info) printf("Loading the geometry from file '%s'.\n",filename);30613062InitGrid(grid[*nogrids]);3063k = *nogrids;3064nogrids0 = *nogrids;30653066iodebug = FALSE;30673068noknots = 0;3069noelements = 0;3070dim = 0;3071axisymmetric = FALSE;3072elemcode = 0;3073maxnodes = 4;3074totelems = 0;30753076matcactive = FALSE;30773078for(;;) {3079if(GetCommand(command,params,in)) {3080if(info) printf("Reached the end of command file\n");3081goto end;3082}30833084/* Control information */3085if(strstr(command,"VERSION")) {3086if(strstr(command,"080500")) {3087if(info) printf("Loading old version of Elmergrid file.\n");3088i = LoadElmergridOld(grid,nogrids,prefix,info);3089return(i);3090}3091else {3092sscanf(params,"%ld",&code);3093if(code == 210903)3094if(info) printf("Loading ElmerGrid file version: %ld\n",code);3095else {3096printf("Unknown ElmerGrid file version: %ld\n",code);3097return(2);3098}3099}3100*nogrids += 1;3101}31023103else if(strstr(command,"DEBUG IO")) {3104for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3105if(strstr(params,"FALSE"))3106iodebug = FALSE;3107else {3108iodebug = TRUE;3109printf("IO debugging activated\n");3110}3111}31123113else if(strstr(command,"MATC")) {3114for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3115if(strstr(params,"FALSE"))3116matcactive = FALSE;3117else {3118#if USE_MATC3119matcactive = TRUE;3120mtc_init(NULL, stdout, stderr);3121strcpy(command, "format( 12 )");3122mtc_domath(command);3123printf("MATC language activated with 12 digit accuracy.\n");3124#else3125matcactive = FALSE;3126printf("Unable to enable MATC, as it is not even compiled.\n");3127bigerror("Unable to enable MATC, as it is not even compiled.");3128#endif3129}3130}31313132else if(strstr(command,"COORDINATE SYSTEM")) {3133for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3134grid[k]->dimension = 2;3135if(strstr(params,"CARTESIAN 1D")) {3136grid[k]->coordsystem = COORD_CART1;3137grid[k]->dimension = 1;3138}3139else if(strstr(params,"CARTESIAN 2D"))3140grid[k]->coordsystem = COORD_CART2;3141else if(strstr(params,"AXISYMMETRIC"))3142grid[k]->coordsystem = COORD_AXIS;3143else if(strstr(params,"POLAR"))3144grid[k]->coordsystem = COORD_POLAR;3145else if(strstr(params,"CARTESIAN 3D")) {3146grid[k]->coordsystem = COORD_CART3;3147grid[k]->dimension = 3;3148}3149else printf("Unknown coordinate system: %s\n",params);3150if(info) printf("Defining the coordinate system (%d-DIM).\n",grid[k]->dimension);3151}31523153else if(strstr(command,"SUBCELL DIVISIONS")) {3154if(grid[k]->dimension == 1) {3155sscanf(params,"%d",&(*grid)[k].xcells);3156grid[k]->ycells = 1;3157}3158else if(grid[k]->dimension == 2)3159sscanf(params,"%d %d",&(*grid)[k].xcells,&(*grid)[k].ycells);3160else if(grid[k]->dimension == 3)3161sscanf(params,"%d %d %d",&(*grid)[k].xcells,&(*grid)[k].ycells,&(*grid)[k].zcells);31623163if(grid[k]->xcells >= MAXCELLS || grid[k]->ycells >= MAXCELLS || grid[k]->zcells >= MAXCELLS) {3164printf("LoadElmergrid: Too many subcells [%d %d %d] vs. %d:\n",3165grid[k]->xcells,grid[k]->ycells,grid[k]->zcells,MAXCELLS);3166}31673168/* Initialize the default structure with ones */3169for(j=grid[k]->ycells;j>=1;j--)3170for(i=1;i<=grid[k]->xcells;i++)3171grid[k]->structure[j][i] = 1;3172}31733174else if(strstr(command,"MINIMUM ELEMENT DIVISION")) {3175if(info) printf("Loading minimum number of elements\n");31763177if((*grid)[k].dimension == 1)3178sscanf(params,"%d",&(*grid)[k].minxelems);31793180if((*grid)[k].dimension == 2)3181sscanf(params,"%d %d",&(*grid)[k].minxelems,&(*grid)[k].minyelems);31823183if((*grid)[k].dimension == 3)3184sscanf(params,"%d %d %d",&(*grid)[k].minxelems,3185&(*grid)[k].minyelems,&(*grid)[k].minzelems);3186}31873188else if(strstr(command,"SUBCELL LIMITS 1")) {3189if(info) printf("Loading %d subcell limits in X-direction\n",grid[k]->xcells+1);3190cp = params;3191for(i=0;i<=grid[k]->xcells;i++) {3192grid[k]->x[i] = next_real(&cp);3193if(i > 0 && grid[k]->x[i] < grid[k]->x[i-1]) {3194printf("Subcell limits 1(%d): %12.6le %12.6le\n",i,grid[k]->x[i],grid[k]->x[i-1]);3195bigerror("Values for limits 1 should be a growing series, existing\n");3196}3197}3198}3199else if(strstr(command,"SUBCELL LIMITS 2")) {3200if(info) printf("Loading %d subcell limits in Y-direction\n",grid[k]->ycells+1);3201cp = params;3202for(i=0;i<=grid[k]->ycells;i++) {3203grid[k]->y[i] = next_real(&cp);3204if(i > 0 && grid[k]->y[i] < grid[k]->y[i-1]) {3205printf("Subcell limits 2(%d): %12.6le %12.6le\n",i,grid[k]->y[i],grid[k]->y[i-1]);3206bigerror("Values for limits should be a growing series, existing\n");3207}3208}3209}3210else if(strstr(command,"SUBCELL LIMITS 3")) {3211if(info) printf("Loading %d subcell limits in Z-direction\n",grid[k]->zcells+1);3212cp = params;3213for(i=0;i<=grid[k]->zcells;i++) {3214grid[k]->z[i] = next_real(&cp);3215if(i > 0 && grid[k]->z[i] < grid[k]->z[i-1]) {3216printf("Subcell limits 3(%d): %12.6le %12.6le\n",i,grid[k]->z[i],grid[k]->z[i-1]);3217bigerror("Values for limits should be a growing series, existing\n");3218}3219}3220}32213222else if(strstr(command,"SUBCELL SIZES 1")) {3223if(info) printf("Loading %d subcell sizes in X-direction\n",grid[k]->xcells);3224cp = params;3225for(i=1;i<=grid[k]->xcells;i++) grid[k]->x[i] = next_real(&cp);3226for(i=1;i<=grid[k]->xcells;i++) grid[k]->x[i] = grid[k]->x[i-1] + grid[k]->x[i];3227}3228else if(strstr(command,"SUBCELL SIZES 2")) {3229if(info) printf("Loading %d subcell sizes in Y-direction\n",grid[k]->ycells);3230cp = params;3231for(i=1;i<=grid[k]->ycells;i++) grid[k]->y[i] = next_real(&cp);3232for(i=1;i<=grid[k]->ycells;i++) grid[k]->y[i] = grid[k]->y[i-1] + grid[k]->y[i];3233}3234else if(strstr(command,"SUBCELL SIZES 3")) {3235if(info) printf("Loading %d subcell sizes in Z-direction\n",grid[k]->zcells);3236cp = params;3237for(i=1;i<=grid[k]->zcells;i++) grid[k]->z[i] = next_real(&cp);3238for(i=1;i<=grid[k]->zcells;i++) grid[k]->z[i] = grid[k]->z[i-1] + grid[k]->z[i];3239}32403241else if(strstr(command,"SUBCELL ORIGIN 1")) {3242for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3243if(strstr(params,"CENTER")) {3244raid = 0.5 * (grid[k]->x[0] + grid[k]->x[grid[k]->xcells]);3245}3246else if(strstr(params,"LEFT") || strstr(params,"MIN") ) {3247raid = grid[k]->x[0];3248}3249else if(strstr(params,"RIGHT") || strstr(params,"MAX") ) {3250raid = grid[k]->x[grid[k]->xcells];3251}3252else {3253cp = params;3254raid = next_real(&cp);3255}3256for(i=0;i<=grid[k]->xcells;i++) grid[k]->x[i] -= raid;3257}3258else if(strstr(command,"SUBCELL ORIGIN 2")) {3259for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3260if(strstr(params,"CENTER")) {3261raid = 0.5 * (grid[k]->y[0] + grid[k]->y[grid[k]->ycells]);3262}3263else if(strstr(params,"LEFT")) {3264raid = grid[k]->y[0];3265}3266else if(strstr(params,"RIGHT")) {3267raid = grid[k]->y[grid[k]->ycells];3268}3269else {3270cp = params;3271raid = next_real(&cp);3272}3273for(i=0;i<=grid[k]->ycells;i++) grid[k]->y[i] -= raid;3274}3275else if(strstr(command,"SUBCELL ORIGIN 3")) {3276for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3277if(strstr(params,"CENTER")) {3278raid = 0.5 * (grid[k]->z[0] + grid[k]->z[grid[k]->zcells]);3279}3280else if(strstr(params,"LEFT")) {3281raid = grid[k]->z[0];3282}3283else if(strstr(params,"RIGHT")) {3284raid = grid[k]->z[grid[k]->zcells];3285}3286else {3287cp = params;3288raid = next_real(&cp);3289}3290for(i=0;i<=grid[k]->zcells;i++) grid[k]->z[i] -= raid;3291}32923293else if(strstr(command,"MATERIAL STRUCTURE")) {3294if(info) printf("Loading material structure\n");32953296/* Initialize the default structure with zeros */3297for(j=grid[k]->ycells;j>=1;j--)3298for(i=1;i<=grid[k]->xcells;i++)3299grid[k]->structure[j][i] = 0;33003301for(j=grid[k]->ycells;j>=1;j--) {3302if(j < grid[k]->ycells) Getline(params,in);3303cp=params;3304for(i=1;i<=grid[k]->xcells;i++)3305grid[k]->structure[j][i] = next_int(&cp);3306}3307minmat = maxmat = grid[k]->structure[1][1];3308for(j=grid[k]->ycells;j>=1;j--)3309for(i=1;i<=grid[k]->xcells;i++) {3310if(minmat > grid[k]->structure[j][i])3311minmat = grid[k]->structure[j][i];3312if(maxmat < grid[k]->structure[j][i])3313maxmat = grid[k]->structure[j][i];3314}3315if(minmat < 0)3316printf("LoadElmergrid: please use positive material indices.\n");3317if(maxmat > MAXBODYID)3318printf("LoadElmergrid: material indices larger to %d may create problems.\n",3319MAXBODYID);3320printf("LoadElmergrid: materials interval is [%d,%d]\n",minmat,maxmat);33213322grid[k]->maxmaterial = maxmat;3323}3324else if(strstr(command,"MATERIALS INTERVAL")) {3325sscanf(params,"%d %d",&(*grid)[k].firstmaterial,&(*grid)[k].lastmaterial);3326}33273328else if(strstr(command,"REVOLVE")) {3329if(0) printf("revolve: %s %s\n",command,params);33303331if(strstr(command,"REVOLVE RADIUS")) {3332(*grid)[k].rotate = TRUE;3333sscanf(params,"%le",&(*grid)[k].rotateradius2);3334}3335else if(strstr(command,"REVOLVE BLOCKS")) {3336(*grid)[k].rotate = TRUE;3337sscanf(params,"%d",&(*grid)[k].rotateblocks);3338}3339else if(strstr(command,"REVOLVE IMPROVE")) {3340(*grid)[k].rotate = TRUE;3341sscanf(params,"%le",&(*grid)[k].rotateimprove);3342}3343else if(strstr(command,"REVOLVE RADIUS")) {3344sscanf(params,"%le",&(*grid)[k].polarradius);3345}3346else if(strstr(command,"REVOLVE CURVE DIRECT")) {3347(*grid)[k].rotatecurve = TRUE;3348sscanf(params,"%le",&(*grid)[k].curvezet);3349}3350else if(strstr(command,"REVOLVE CURVE RADIUS")) {3351(*grid)[k].rotatecurve = TRUE;3352sscanf(params,"%le",&(*grid)[k].curverad);3353}3354else if(strstr(command,"REVOLVE CURVE ANGLE")) {3355(*grid)[k].rotatecurve = TRUE;3356sscanf(params,"%le",&(*grid)[k].curveangle);3357}3358}33593360else if(strstr(command,"REDUCE ORDER INTERVAL")) {3361sscanf(params,"%d%d",&(*grid)[k].reduceordermatmin,3362&(*grid)[k].reduceordermatmax);3363}33643365else if(strstr(command,"BOUNDARY DEFINITION")) {3366printf("Loading boundary conditions\n");33673368for(i=0;i<MAXBOUNDARIES;i++) {3369if(i>0) Getline(params,in);3370for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);3371if(strstr(params,"END")) break;3372sscanf(params,"%d %d %d %d",3373&(*grid)[k].boundtype[i],&(*grid)[k].boundext[i],3374&(*grid)[k].boundint[i],&(*grid)[k].boundsolid[i]);3375}3376printf("Found %d boundaries\n",i);3377(*grid)[k].noboundaries = i;3378}33793380/* else if(strstr(command,"LAYERED BOUNDARIES")) {3381for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3382if(strstr(params,"TRUE")) (*grid)[k].layeredbc = 1;3383if(strstr(params,"FALSE")) (*grid)[k].layeredbc = 0;3384} */33853386else if(strstr(command,"NUMBERING")) {3387for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3388if(strstr(params,"HORIZONTAL")) (*grid)[k].numbering = NUMBER_XY;3389if(strstr(params,"VERTICAL")) (*grid)[k].numbering = NUMBER_YX;3390}33913392else if(strstr(command,"ELEMENT DEGREE")) {3393sscanf(params,"%d",&(*grid)[k].elemorder);3394}33953396else if(strstr(command,"ELEMENT INNERNODES")) {3397for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3398if(strstr(params,"TRUE")) (*grid)[k].elemmidpoints = TRUE;3399if(strstr(params,"FALSE")) (*grid)[k].elemmidpoints = FALSE;3400}3401else if(strstr(command,"ELEMENTTYPE") || strstr(command,"ELEMENTCODE")) {3402sscanf(params,"%d",&elemcode);3403}34043405else if(strstr(command,"TRIANGLES CRITICAL ANGLE")) {3406sscanf(params,"%le",&(*grid)[k].triangleangle);3407}3408else if(strstr(command,"TRIANGLES")) {3409for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3410if(strstr(params,"TRUE")) (*grid)[k].triangles = TRUE;3411if(strstr(params,"FALSE")) (*grid)[k].triangles = FALSE;3412}34133414else if(strstr(command,"PLANE ELEMENTS")) {3415sscanf(params,"%d",&(*grid)[k].wantedelems);3416}3417else if(strstr(command,"SURFACE ELEMENTS")) {3418sscanf(params,"%d",&(*grid)[k].wantedelems);3419}3420else if(strstr(command,"REFERENCE DENSITY")) {3421sscanf(params,"%le",&(*grid)[k].limitdx);3422(*grid)[k].autoratio = 3;3423}3424else if(strstr(command,"VERIFY DENSITY")) {3425for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3426if(strstr(params,"TRUE")) (*grid)[k].limitdxverify = TRUE;3427if(strstr(params,"FALSE")) (*grid)[k].limitdxverify = FALSE;3428}3429else if(strstr(command,"VOLUME ELEMENTS")) {3430sscanf(params,"%d",&(*grid)[k].wantedelems3d);3431}3432else if(strstr(command,"VOLUME NODES")) {3433sscanf(params,"%d",&(*grid)[k].wantednodes3d);3434}34353436else if(strstr(command,"COORDINATE RATIO")) {3437if((*grid)[k].dimension == 2)3438sscanf(params,"%le",&(*grid)[k].xyratio);3439if((*grid)[k].dimension == 3)3440sscanf(params,"%le %le",&(*grid)[k].xyratio,&(*grid)[k].xzratio);3441}34423443else if(strstr(command,"ELEMENT RATIOS 1")) {3444cp = params;3445for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xexpand[i] = next_real(&cp);3446}3447else if(strstr(command,"ELEMENT RATIOS 2")) {3448cp = params;3449for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yexpand[i] = next_real(&cp);3450}3451else if(strstr(command,"ELEMENT RATIOS 3")) {3452cp = params;3453for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zexpand[i] = next_real(&cp);3454}34553456else if(strstr(command,"ELEMENT DENSITIES 1")) {3457cp = params;3458for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xdens[i] = next_real(&cp);3459}3460else if(strstr(command,"ELEMENT DENSITIES 2")) {3461cp = params;3462for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].ydens[i] = next_real(&cp);3463}3464else if(strstr(command,"ELEMENT DENSITIES 3")) {3465cp = params;3466for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zdens[i] = next_real(&cp);3467}34683469else if(strstr(command,"ELEMENT DIVISIONS 1")) {3470cp = params;3471for(i=1;i<=(*grid)[k].xcells;i++) (*grid)[k].xelems[i] = next_int(&cp);3472(*grid)[k].autoratio = 0;3473}3474else if(strstr(command,"ELEMENT DIVISIONS 2")) {3475cp = params;3476for(i=1;i<=(*grid)[k].ycells;i++) (*grid)[k].yelems[i] = next_int(&cp);3477(*grid)[k].autoratio = 0;3478}3479else if(strstr(command,"ELEMENT DIVISIONS 3")) {3480cp = params;3481for(i=1;i<=(*grid)[k].zcells;i++) (*grid)[k].zelems[i] = next_int(&cp);3482(*grid)[k].autoratio = 0;3483}34843485/* else if(strstr(command,"EXTRUDED STRUCTURE")) {3486for(i=1;i<=(*grid)[k].zcells;i++) {3487if(i>1) Getline(params,in);3488sscanf(params,"%d %d %d\n",3489&(*grid)[k].zfirstmaterial[i],&(*grid)[k].zlastmaterial[i],&(*grid)[k].zmaterial[i]);3490}3491} */34923493else if(strstr(command,"GEOMETRY MAPPINGS")) {3494if(k > 0) (*grid)[k].mappings = 0;34953496for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);3497for(i=(*grid)[k].mappings;i<MAXMAPPINGS;i++) {3498if(i>(*grid)[k].mappings) Getline(params,in);34993500if(strstr(params,"END")) break;3501cp=params;3502(*grid)[k].mappingtype[i] = next_int(&cp);3503#if 03504(*grid)[k].mappingtype[i] += 50*SGN((*grid)[k].mappingtype[i]);3505#endif3506(*grid)[k].mappingline[i] = next_int(&cp);3507(*grid)[k].mappinglimits[2*i] = next_real(&cp);3508(*grid)[k].mappinglimits[2*i+1] = next_real(&cp);3509(*grid)[k].mappingpoints[i] = next_int(&cp);3510(*grid)[k].mappingparams[i] = Rvector(0,(*grid)[k].mappingpoints[i]);3511for(j=0;j<(*grid)[k].mappingpoints[i];j++)3512(*grid)[k].mappingparams[i][j] = next_real(&cp);3513}3514printf("Loaded %d geometry mappings\n",i);3515(*grid)[k].mappings = i;3516}35173518else if(strstr(command,"END") ) {3519if(0) printf("End of field\n");3520}35213522else if(strstr(command,"START NEW MESH")) {3523if((*nogrids) >= MAXCASES) {3524printf("There are more grids than was allocated for!\n");3525printf("Ignoring meshes starting from %d\n.",(*nogrids)+1);3526goto end;3527}3528(*nogrids)++;3529printf("\nLoading element meshing no %d\n",*nogrids);3530k = *nogrids - 1;3531if(k > nogrids0) (*grid)[k] = (*grid)[k-1];3532}35333534else {3535if(0) printf("Unknown command: %s",command);3536}3537}35383539end:35403541if(info) printf("Found %d divisions for grid\n",*nogrids);35423543for(k=nogrids0;k < (*nogrids) && k<MAXCASES;k++) {35443545if(elemcode == 0) {3546if((*grid)[k].dimension == 1) {3547(*grid)[k].nonodes = (*grid)[k].elemorder + 1;3548}3549else if((*grid)[k].elemmidpoints == FALSE) {3550(*grid)[k].nonodes = 4 * (*grid)[k].elemorder;3551}3552else {3553if((*grid)[k].elemorder == 2) (*grid)[k].nonodes = 9;3554if((*grid)[k].elemorder == 3) (*grid)[k].nonodes = 16;3555}3556}3557else if(elemcode/100 == 2) {3558(*grid)[k].triangles = FALSE;3559(*grid)[k].nonodes = elemcode%100;3560}3561else if(elemcode/100 == 4) {3562(*grid)[k].triangles = FALSE;3563(*grid)[k].nonodes = elemcode%100;3564}3565else if(elemcode/100 == 3) {3566(*grid)[k].triangles = TRUE;3567if(elemcode%100 == 3) (*grid)[k].nonodes = 4;3568else if(elemcode%100 == 6) (*grid)[k].nonodes = 9;3569else if(elemcode%100 == 10) (*grid)[k].nonodes = 16;3570}3571}357235733574/* for(k=nogrids0;k < (*nogrids) && k<MAXCASES;k++) {3575SetElementDivision(&(*grid)[k],relh,info);3576} */35773578fclose(in);3579return(0);3580}3581358235833584void InitParameters(struct ElmergridType *eg)3585{3586int i;35873588eg->relh = 1.0;3589eg->inmethod = 0;3590eg->outmethod = 0;3591eg->silent = FALSE;3592eg->nofilesin = 1;3593eg->unitemeshes = FALSE;3594eg->unitenooverlap = FALSE;3595eg->triangles = FALSE;3596eg->triangleangle = 0.0;3597eg->rotate = FALSE;3598eg->polar = FALSE;3599eg->cylinder = FALSE;3600eg->usenames = TRUE;3601eg->layers = 0;3602eg->layereps = 0.0;3603eg->layermove = 0;3604eg->partitions = 0;3605eg->elements3d = 0;3606eg->nodes3d = 0;3607eg->metis = 0;3608eg->metis_contig = FALSE;3609eg->metis_volcut = FALSE;3610eg->metis_seed = 0;3611eg->metis_ncuts = 1;3612eg->metis_minconn = FALSE;3613eg->partopt = 0;3614eg->partoptim = FALSE;3615eg->partbcoptim = TRUE;3616eg->partjoin = 0;3617for(i=0;i<MAXHALOMODES;i++) eg->parthalo[i] = FALSE;3618eg->partitionindirect = FALSE;3619eg->reduce = FALSE;3620eg->increase = FALSE;3621eg->translate = FALSE;3622eg->isoparam = FALSE;3623eg->multidim = FALSE;3624eg->removelowdim = FALSE;3625eg->removeintbcs = FALSE;3626eg->removeunused = FALSE;3627eg->dim = 3;3628eg->center = FALSE;3629eg->scale = FALSE;3630eg->order = FALSE;3631eg->boundbounds = 0;3632eg->saveinterval[0] = eg->saveinterval[1] = eg->saveinterval[2] = 0;3633eg->bulkbounds = 0;3634eg->partorder = FALSE;3635eg->findsides = FALSE;3636eg->parthypre = FALSE;3637eg->partdual = FALSE;3638eg->partbcz = 0;3639eg->partbcr = 0;3640eg->partbclayers = 1;3641eg->partbcmetis = 0;3642eg->partbw = FALSE;3643eg->saveboundaries = TRUE;3644eg->vtuone = FALSE;3645eg->timeron = FALSE;3646eg->nosave = FALSE;3647eg->nooverwrite = FALSE;3648eg->merge = FALSE;3649eg->bcoffset = FALSE;3650eg->periodic = 0;3651eg->periodicdim[0] = 0;3652eg->periodicdim[1] = 0;3653eg->periodicdim[2] = 0;3654eg->bulkorder = FALSE;3655eg->boundorder = FALSE;3656eg->sidemappings = 0;3657eg->bulkmappings = 0;3658eg->coordinatemap[0] = eg->coordinatemap[1] = eg->coordinatemap[2] = 0;3659eg->clone[0] = eg->clone[1] = eg->clone[2] = 0;3660eg->clonesize[0] = eg->clonesize[1] = eg->clonesize[2] = 0.0;3661eg->mirror[0] = eg->mirror[1] = eg->mirror[2] = 0;3662eg->cloneinds = FALSE;3663eg->mirrorbc = 0;3664eg->decimals = 12;3665eg->discont = 0;3666eg->connect = 0;3667eg->connectboundsnosets = 0;36683669eg->rotatecurve = FALSE;3670eg->curverad = 0.5;3671eg->curveangle = 90.0;3672eg->curvezet = 0.0;3673eg->parttol = 0.0;3674eg->filerenamed = FALSE;36753676for(i=0;i<MAXSIDEBULK;i++)3677eg->sidebulk[i] = 0;3678}36793680368136823683int InlineParameters(struct ElmergridType *eg,int argc,char *argv[],int first,int info)3684{3685int arg,i,dim;3686char command[MAXLINESIZE];36873688dim = eg->dim;36893690printf("Elmergrid reading in-line arguments\n");36913692/* Type of input file */3693if(first > 3) {3694for(i=0;i<MAXLINESIZE;i++) command[i] = ' ';36953696strcpy(command,argv[1]);3697for(i=0;i<MAXLINESIZE;i++) command[i] = toupper(command[i]);3698for(i=0;i<=MAXINMETHODS;i++) {3699if(strstr(command,InMethods[i])) {3700eg->inmethod = i;3701break;3702}3703}3704if(i>MAXINMETHODS) eg->inmethod = atoi(argv[1]);370537063707/* Type of output file (fewer options) */3708strcpy(command,argv[2]);3709for(i=0;i<MAXLINESIZE;i++) command[i] = toupper(command[i]);3710for(i=1;i<=MAXOUTMETHODS;i++) {3711if(strstr(command,OutMethods[i])) {3712eg->outmethod = i;3713break;3714}3715}3716if(i>MAXOUTMETHODS) eg->outmethod = atoi(argv[2]);37173718/* Name of output file */3719strcpy(eg->filesin[0],argv[3]);3720strcpy(eg->filesout[0],eg->filesin[0]);3721strcpy(eg->infofile,eg->filesin[0]);3722}372337243725/* The optional inline parameters */37263727for(arg=first;arg <argc; arg++) {37283729if(strcmp(argv[arg],"-silent") == 0) {3730eg->silent = TRUE;3731info = FALSE;3732}3733else if(strcmp(argv[arg],"-verbose") == 0) {3734eg->silent = FALSE;3735info = TRUE;3736}3737else if(strcmp(argv[arg],"-in") ==0 ) {3738if(arg+1 >= argc) {3739printf("The secondary input file name is required as a parameter\n");3740return(1);3741}3742else {3743strcpy(eg->filesin[eg->nofilesin],argv[arg+1]);3744printf("A secondary input file %s will be loaded.\n",eg->filesin[eg->nofilesin]);3745eg->nofilesin++;3746}3747}3748else if(strcmp(argv[arg],"-out") == 0) {3749if(arg+1 >= argc) {3750printf("The output name is required as a parameter\n");3751return(2);3752}3753else {3754strcpy(eg->filesout[0],argv[arg+1]);3755eg->filerenamed = TRUE;3756}3757}3758else if(strcmp(argv[arg],"-decimals") == 0) {3759eg->decimals = atoi(argv[arg+1]);3760}3761else if(strcmp(argv[arg],"-triangles") ==0) {3762eg->triangles = TRUE;3763printf("The rectangles will be split to triangles.\n");3764if(arg+1 < argc) {3765if(strcmp(argv[arg+1],"-")) {3766eg->triangleangle = atof(argv[arg+1]);3767}3768}3769}3770else if(strcmp(argv[arg],"-merge") == 0) {3771if(arg+1 >= argc) {3772printf("Give a parameter for critical distance.\n");3773return(3);3774}3775else {3776eg->merge = TRUE;3777eg->cmerge = atof(argv[arg+1]);3778}3779}3780else if(strcmp(argv[arg],"-relh") == 0) {3781if(arg+1 >= argc) {3782printf("Give a relative mesh density related to the specifications\n");3783return(3);3784}3785else {3786eg->relh = atof(argv[arg+1]);3787}3788}3789else if(strcmp(argv[arg],"-order") == 0) {3790if(arg+dim >= argc) {3791printf("Give %d parameters for the order vector.\n",dim);3792return(4);3793}3794else {3795eg->order = TRUE;3796eg->corder[0] = atof(argv[arg+1]);3797eg->corder[1] = atof(argv[arg+2]);3798if(dim==3) eg->corder[2] = atof(argv[arg+3]);3799}3800}3801else if(strcmp(argv[arg],"-parttol") == 0) {3802if(arg+1 >= argc) {3803printf("Give a tolerance for geometric partition algorithms\n");3804return(3);3805}3806else {3807eg->parttol = atof(argv[arg+1]);3808}3809}3810else if(strcmp(argv[arg],"-autoorder") == 0) {3811eg->order = 2;3812}3813else if(strcmp(argv[arg],"-halo") == 0) {3814eg->parthalo[1] = TRUE;3815}3816else if(strcmp(argv[arg],"-halobc") == 0) {3817eg->parthalo[2] = TRUE;3818}3819else if(strcmp(argv[arg],"-halodb") == 0) {3820eg->parthalo[1] = TRUE;3821eg->parthalo[2] = TRUE;3822}3823else if(strcmp(argv[arg],"-haloz") == 0) {3824eg->parthalo[3] = TRUE;3825}3826else if(strcmp(argv[arg],"-halor") == 0) {3827eg->parthalo[3] = TRUE;3828}3829else if(strcmp(argv[arg],"-halogreedy") == 0) {3830eg->parthalo[4] = TRUE;3831}3832else if(strcmp(argv[arg],"-indirect") == 0) {3833eg->partitionindirect = TRUE;3834}3835else if(strcmp(argv[arg],"-metisorder") == 0) {3836eg->order = 3;3837}3838else if(strcmp(argv[arg],"-centralize") == 0) {3839eg->center = TRUE;3840}3841else if(strcmp(argv[arg],"-scale") == 0) {3842if(arg+dim >= argc) {3843printf("Give %d parameters for the scaling.\n",dim);3844return(5);3845}3846else {3847eg->scale = TRUE;3848eg->cscale[0] = atof(argv[arg+1]);3849eg->cscale[1] = atof(argv[arg+2]);3850if(dim==3) eg->cscale[2] = atof(argv[arg+3]);3851}3852}3853else if(strcmp(argv[arg],"-translate") == 0) {3854if(arg+dim >= argc) {3855printf("Give %d parameters for the translate vector.\n",dim);3856return(6);3857}3858else {3859eg->translate = TRUE;3860eg->ctranslate[0] = atof(argv[arg+1]);3861eg->ctranslate[1] = atof(argv[arg+2]);3862if(dim==3) eg->ctranslate[2] = atof(argv[arg+3]);3863}3864}3865else if(strcmp(argv[arg],"-saveinterval") == 0) {3866if(arg+dim >= argc) {3867printf("Give min, max and step for the interval.\n");3868return(7);3869}3870else {3871eg->saveinterval[0] = atoi(argv[arg+1]);3872eg->saveinterval[1] = atoi(argv[arg+2]);3873eg->saveinterval[2] = atoi(argv[arg+3]);3874}3875}3876else if(strcmp(argv[arg],"-rotate") == 0 || strcmp(argv[arg],"-rotate") == 0) {3877if(arg+dim >= argc) {3878printf("Give three parameters for the rotation angles.\n");3879return(8);3880}3881else {3882eg->rotate = TRUE;3883eg->crotate[0] = atof(argv[arg+1]);3884eg->crotate[1] = atof(argv[arg+2]);3885eg->crotate[2] = atof(argv[arg+3]);3886}3887}3888else if(strcmp(argv[arg],"-clone") == 0) {3889if(arg+dim >= argc) {3890printf("Give the number of clones in each %d directions.\n",dim);3891return(9);3892}3893else {3894eg->clone[0] = atoi(argv[arg+1]);3895eg->clone[1] = atoi(argv[arg+2]);3896if(dim == 3) eg->clone[2] = atoi(argv[arg+3]);3897}3898}3899else if(strcmp(argv[arg],"-clonesize") == 0) {3900if(arg+dim >= argc) {3901printf("Give the clone size in each %d directions.\n",dim);3902return(10);3903}3904else {3905eg->clonesize[0] = atof(argv[arg+1]);3906eg->clonesize[1] = atof(argv[arg+2]);3907if(dim == 3) eg->clonesize[2] = atof(argv[arg+3]);3908}3909}3910else if(strcmp(argv[arg],"-cloneinds") == 0) {3911eg->cloneinds = TRUE;3912}3913else if(strcmp(argv[arg],"-mirror") == 0) {3914if(arg+dim >= argc) {3915printf("Give the symmetry of the coordinate directions, eg. 1 1 0\n");3916}3917else {3918eg->mirror[0] = atoi(argv[arg+1]);3919eg->mirror[1] = atoi(argv[arg+2]);3920if(dim == 3) eg->mirror[2] = atoi(argv[arg+3]);3921}3922}3923else if(strcmp(argv[arg],"-mirrorbc") == 0) {3924if(arg+1 >= argc) {3925printf("Give the number of symmetry BC.\n");3926return(11);3927}3928else {3929eg->mirrorbc = atoi(argv[arg+1]);3930}3931}3932else if(strcmp(argv[arg],"-unite") == 0) {3933eg->unitemeshes = TRUE;3934printf("The meshes will be united.\n");3935}3936else if(strcmp(argv[arg],"-unitenooverlap") == 0) {3937eg->unitemeshes = TRUE;3938eg->unitenooverlap = TRUE;3939printf("The meshes will be united without overlap in BCs or bodies.\n");3940}3941else if(strcmp(argv[arg],"-nonames") == 0) {3942eg->usenames = FALSE;3943printf("Names will be omitted even if they would exist\n");3944}3945else if(strcmp(argv[arg],"-multidim") == 0) {3946eg->multidim = TRUE;3947printf("Lower dimensional entities may be bulk too!\n");3948}3949else if(strcmp(argv[arg],"-removelowdim") == 0) {3950eg->removelowdim = TRUE;3951printf("Lower dimensional boundaries will be removed\n");3952}3953else if(strcmp(argv[arg],"-removeintbcs") == 0) {3954eg->removeintbcs = TRUE;3955printf("Lower dimensional boundaries will be removed\n");3956}3957else if(strcmp(argv[arg],"-removeunused") == 0) {3958eg->removeunused = TRUE;3959printf("Nodes that do not appear in any element will be removed\n");3960}3961else if(strcmp(argv[arg],"-autoclean") == 0) {3962eg->removelowdim = TRUE;3963eg->bulkorder = TRUE;3964eg->boundorder = TRUE;3965eg->removeunused = TRUE;3966printf("Lower dimensional boundaries will be removed\n");3967printf("Materials and boundaries will be renumbered\n");3968printf("Nodes that do not appear in any element will be removed\n");3969}3970else if(strcmp(argv[arg],"-polar") == 0) {3971eg->polar = TRUE;3972printf("Making transformation to polar coordinates.\n");3973if(arg+1 >= argc) {3974printf("The preferred radius is required as a parameter\n");3975eg->polarradius = 1.0;3976}3977else {3978eg->polarradius = atoi(argv[arg+1]);3979}3980}3981else if(strcmp(argv[arg],"-cylinder") == 0) {3982eg->cylinder = TRUE;3983printf("Making transformation from cylindrical to cartesian coordinates.\n");3984}3985else if(strcmp(argv[arg],"-reduce") == 0) {3986if(arg+2 >= argc) {3987printf("Give two material for the interval.\n");3988return(12);3989}3990else {3991eg->reduce = TRUE;3992eg->reducemat1 = atoi(argv[arg+1]);3993eg->reducemat2 = atoi(argv[arg+2]);3994}3995}3996else if(strcmp(argv[arg],"-increase") == 0) {3997eg->increase = TRUE;3998}3999else if(strcmp(argv[arg],"-bulkorder") == 0) {4000eg->bulkorder = TRUE;4001}4002else if(strcmp(argv[arg],"-boundorder") == 0) {4003eg->boundorder = TRUE;4004}4005else if(strcmp(argv[arg],"-partition") == 0 ||4006strcmp(argv[arg],"-partcell") == 0 ||4007strcmp(argv[arg],"-partcyl") == 0 ) {4008if(arg+dim >= argc) {4009printf("The number of partitions in %d dims is required as parameters.\n",dim);4010return(13);4011}4012else {4013eg->partitions = 1;4014eg->partdim[0] = atoi(argv[arg+1]);4015eg->partdim[1] = atoi(argv[arg+2]);4016if(dim == 3) eg->partdim[2] = atoi(argv[arg+3]);4017eg->partitions = 1;4018for(i=0;i<3;i++) {4019if(eg->partdim[i] == 0) eg->partdim[i] = 1;4020eg->partitions *= eg->partdim[i];4021}4022eg->partopt = -1;4023if( strcmp(argv[arg],"-partition") == 0 ) {4024if(arg+4 < argc)4025if(argv[arg+4][0] != '-') eg->partopt = atoi(argv[arg+4]);4026}4027else if( strcmp( argv[arg],"-partcell") == 0 ) {4028eg->partopt = 2;4029} else if( strcmp( argv[arg],"-partcyl") == 0 ) {4030eg->partopt = 3;4031}40324033printf("The mesh will be partitioned geometrically to %d partitions.\n",4034eg->partitions);4035}4036}4037else if(strcmp(argv[arg],"-partorder") == 0) {4038if(arg+dim >= argc) {4039printf("Give %d parameters for the order vector.\n",dim);4040return(14);4041}4042else {4043eg->partorder = 1;4044eg->partcorder[0] = atof(argv[arg+1]);4045eg->partcorder[1] = atof(argv[arg+2]);4046if(dim==3) eg->partcorder[2] = atof(argv[arg+3]);4047}4048}4049else if(strcmp(argv[arg],"-partoptim") == 0) {4050eg->partoptim = TRUE;4051printf("Aggressive optimization will be applied to node sharing.\n");4052}4053else if(strcmp(argv[arg],"-partnobcoptim") == 0) {4054eg->partbcoptim = FALSE;4055printf("Aggressive optimization will not be applied to parent element sharing.\n");4056}4057else if(strcmp(argv[arg],"-partbw") == 0) {4058eg->partbw = TRUE;4059printf("Bandwidth will be optimized for partitions.\n");4060}4061else if(strcmp(argv[arg],"-parthypre") == 0) {4062eg->parthypre = TRUE;4063printf("Numbering of partitions will be made continuous.\n");4064}4065else if(strcmp(argv[arg],"-partdual") == 0) {4066eg->partdual = TRUE;4067printf("Using dual (elemental) graph in partitioning.\n");4068}4069else if(strcmp(argv[arg],"-metis") == 0 ||4070strcmp(argv[arg],"-metisrec") == 0 ||4071strcmp(argv[arg],"-metiskway") == 0 ) {4072#if USE_METIS4073if(arg+1 >= argc) {4074printf("The number of partitions is required as a parameter\n");4075return(15);4076}4077else {4078eg->metis = atoi(argv[arg+1]);4079printf("The mesh will be partitioned with Metis to %d partitions.\n",eg->metis);4080eg->partopt = 0;4081if(strcmp(argv[arg],"-metisrec") == 0)4082eg->partopt = 2;4083else if(strcmp(argv[arg],"-metiskway") == 0 )4084eg->partopt = 3;4085else if(arg+2 < argc)4086if(argv[arg+2][0] != '-') eg->partopt = atoi(argv[arg+2]);4087}4088#else4089printf("This version of ElmerGrid was compiled without Metis library!\n");4090#endif4091}4092else if(strcmp(argv[arg],"-metisseed") == 0 ) {4093if(arg+1 >= argc) {4094printf("The random number seed is required as parameter for -metisseed!\n");4095return(15);4096}4097else {4098eg->metis_seed = atoi(argv[arg+1]);4099printf("Seed for Metis partitioning routines: %d\n",eg->metis_seed);4100}4101}4102else if(strcmp(argv[arg],"-metisncuts") == 0 ) {4103if(arg+1 >= argc) {4104printf("The number of parameters is required as parameter for -metisncuts!\n");4105return(15);4106}4107else {4108eg->metis_ncuts = atoi(argv[arg+1]);4109printf("Number of competing partitions to generate : %d\n",eg->metis_ncuts);4110}4111}4112else if(strcmp(argv[arg],"-partjoin") == 0) {4113if(arg+1 >= argc) {4114printf("The number of partitions is required as a parameter!\n");4115return(15);4116}4117else {4118eg->partjoin = atoi(argv[arg+1]);4119printf("The results will joined using %d partitions.\n",eg->partjoin);4120}4121}4122else if(strcmp(argv[arg],"-partconnect") == 0 || strcmp(argv[arg],"-partzbc") == 0 ) {4123if(arg+1 >= argc) {4124printf("The number of 1D partitions is required as a parameter!\n");4125return(15);4126}4127else {4128eg->partbcz = atoi(argv[arg+1]);4129printf("The connected BCs will be partitioned to %d partitions in Z.\n",eg->partbcz);4130}4131}4132else if(strcmp(argv[arg],"-partrbc") == 0 ) {4133if(arg+1 >= argc) {4134printf("The number of 1D partitions is required as a parameter!\n");4135return(15);4136}4137else {4138eg->partbcr = atoi(argv[arg+1]);4139printf("The connected BCs will be partitioned to %d partitions in R.\n",eg->partbcr);4140}4141}4142else if(strcmp(argv[arg],"-partlayers") == 0) {4143if(arg+1 >= argc) {4144printf("The number of layers to be extended is required as a parameter\n");4145return(15);4146}4147else {4148eg->partbclayers = atoi(argv[arg+1]);4149printf("The boundary partitioning will be extended by %d layers.\n",eg->partbclayers);4150}4151}4152else if(strcmp(argv[arg],"-metiscontig") == 0 ) {4153eg->metis_contig = TRUE;4154}4155else if(strcmp(argv[arg],"-metisvol") == 0 ) {4156eg->metis_volcut = TRUE;4157}4158else if(strcmp(argv[arg],"-metisminconn") == 0 ) {4159eg->metis_minconn = TRUE;4160}4161else if(strcmp(argv[arg],"-metisconnect") == 0 || strcmp(argv[arg],"-metisbc") == 0 ) {4162if(arg+1 >= argc) {4163printf("The number of Metis partitions is required as a parameter\n");4164return(15);4165}4166else {4167eg->partbcmetis = atoi(argv[arg+1]);4168printf("The connected BCs will be partitioned to %d partitions by Metis.\n",eg->partbcmetis);4169}4170}4171else if(strcmp(argv[arg],"-periodic") == 0) {4172if(arg+dim >= argc) {4173printf("Give the periodic coordinate directions (e.g. 1 1 0)\n");4174return(16);4175}4176else {4177eg->periodicdim[0] = atoi(argv[arg+1]);4178eg->periodicdim[1] = atoi(argv[arg+2]);4179if(dim == 3) eg->periodicdim[2] = atoi(argv[arg+3]);4180}4181}4182else if(strcmp(argv[arg],"-discont") == 0) {4183if(arg+1 >= argc) {4184printf("Give the discontinuous boundary conditions.\n");4185return(17);4186}4187else {4188eg->discontbounds[eg->discont] = atoi(argv[arg+1]);4189eg->discont++;4190}4191}4192else if(strcmp(argv[arg],"-connect") == 0) {4193if(arg+1 >= argc) {4194printf("Give the connected boundary conditions.\n");4195return(10);4196}4197else {4198eg->connectboundsnosets += 1;4199for(i=arg+1;i<argc && strncmp(argv[i],"-",1); i++) {4200eg->connectbounds[eg->connect] = atoi(argv[i]);4201eg->connectboundsset[eg->connect] = eg->connectboundsnosets;4202eg->connect++;4203}4204}4205}4206else if(strcmp(argv[arg],"-connectall") == 0) {4207eg->connectboundsnosets += 1;4208eg->connectbounds[eg->connect] = -1;4209eg->connectboundsset[eg->connect] = eg->connectboundsnosets;4210eg->connect++;4211}4212else if(strcmp(argv[arg],"-connectint") == 0) {4213eg->connectboundsnosets += 1;4214eg->connectbounds[eg->connect] = -2;4215eg->connectboundsset[eg->connect] = eg->connectboundsnosets;4216eg->connect++;4217}4218else if(strcmp(argv[arg],"-connectfree") == 0) {4219eg->connectboundsnosets += 1;4220eg->connectbounds[eg->connect] = -3;4221eg->connectboundsset[eg->connect] = eg->connectboundsnosets;4222eg->connect++;4223}4224else if(strcmp(argv[arg],"-boundbound") == 0) {4225for(i=arg+1;i<=arg+3 && i<argc; i++) {4226eg->boundbound[3*eg->boundbounds+i-(1+arg)] = atoi(argv[i]);4227if((i-arg)%3 == 0) eg->boundbounds++;4228}4229}4230else if(strcmp(argv[arg],"-bulkbound") == 0) {4231for(i=arg+1;i<=arg+3 && i<argc; i++) {4232eg->bulkbound[3*eg->bulkbounds+i-(1+arg)] = atoi(argv[i]);4233if((i-arg)%3 == 0) eg->bulkbounds++;4234}4235}4236else if(strcmp(argv[arg],"-boundtype") == 0) {4237for(i=arg+1;i<argc && strncmp(argv[i],"-",1); i++)4238eg->sidemap[3*eg->sidemappings+i-1-arg] = atoi(argv[i]);4239eg->sidemappings++;4240}4241else if(strcmp(argv[arg],"-bulktype") == 0) {4242for(i=arg+1;i<argc && strncmp(argv[i],"-",1); i++)4243eg->bulkmap[3*eg->bulkmappings+i-1-arg] = atoi(argv[i]);4244eg->bulkmappings++;4245}4246else if(strcmp(argv[arg],"-coordinatemap") == 0) {4247if( arg+3 >= argc ) {4248printf("Give three parameters for the index permutation\n");4249return(18);4250}4251else {4252for(i=0;i<3;i++)4253eg->coordinatemap[i] = atoi(argv[arg+1+i]);4254}4255}4256else if(strcmp(argv[arg],"-layer") == 0) {4257if(arg+4 >= argc) {4258printf("Give four parameters for the layer: boundary, elements, thickness, ratio.\n");4259return(18);4260}4261else if(eg->layers == MAXBOUNDARIES) {4262printf("There can only be %d layers, sorry.\n",MAXBOUNDARIES);4263return(19);4264}4265else {4266eg->layerbounds[eg->layers] = atoi(argv[arg+1]);4267eg->layernumber[eg->layers] = atoi(argv[arg+2]);4268eg->layerthickness[eg->layers] = atof(argv[arg+3]);4269eg->layerratios[eg->layers] = atof(argv[arg+4]);4270eg->layerparents[eg->layers] = 0;4271eg->layers++;4272}4273}4274else if(strcmp(argv[arg],"-layermove") == 0) {4275if(arg+1 >= argc) {4276printf("Give maximum number of Jacobi filters.\n");4277return(20);4278}4279else {4280eg->layermove = atoi(argv[arg+1]);4281}4282}4283/* This uses a very dirty trick where the variables related to argument -layer are used4284with a negative indexing */4285else if(strcmp(argv[arg],"-divlayer") == 0) {4286if(arg+4 >= argc) {4287printf("Give four parameters for the layer: boundary, elements, relative thickness, ratio.\n");4288return(21);4289}4290else if(abs(eg->layers) == MAXBOUNDARIES) {4291printf("There can only be %d layers, sorry.\n",MAXBOUNDARIES);4292return(22);4293}4294else {4295eg->layerbounds[abs(eg->layers)] = atoi(argv[arg+1]);4296eg->layernumber[abs(eg->layers)] = atoi(argv[arg+2]);4297eg->layerthickness[abs(eg->layers)] = atof(argv[arg+3]);4298eg->layerratios[abs(eg->layers)] = atof(argv[arg+4]);4299eg->layerparents[abs(eg->layers)] = 0;4300eg->layers--;4301}4302}4303else if(strcmp(argv[arg],"-3d") == 0) {4304eg->dim = dim = 3;4305}4306else if(strcmp(argv[arg],"-2d") == 0) {4307eg->dim = dim = 2;4308}4309else if(strcmp(argv[arg],"-1d") == 0) {4310eg->dim = dim = 1;4311}4312else if(strcmp(argv[arg],"-isoparam") == 0) {4313eg->isoparam = TRUE;4314}4315else if(strcmp(argv[arg],"-nobound") == 0) {4316eg->saveboundaries = FALSE;4317}4318else if(strcmp(argv[arg],"-vtuone") == 0) {4319eg->vtuone = TRUE;4320}4321else if(strcmp(argv[arg],"-nosave") == 0) {4322eg->nosave = TRUE;4323}4324else if(strcmp(argv[arg],"-nooverwrite") == 0) {4325eg->nooverwrite = TRUE;4326}4327else if(strcmp(argv[arg],"-timer") == 0) {4328eg->timeron = TRUE;4329}4330else if(strcmp(argv[arg],"-infofile") == 0) {4331eg->timeron = TRUE;4332if(arg+1 >= argc) {4333printf("The output name is required as a parameter\n");4334return(2);4335}4336else {4337strcpy(eg->infofile,argv[arg+1]);4338}4339}4340/* The following keywords are not actively used */4341else if(strcmp(argv[arg],"-bcoffset") == 0) {4342eg->bcoffset = atoi(argv[arg+1]);4343}4344else if(strcmp(argv[arg],"-noelements") == 0) {4345eg->elements3d = atoi(argv[arg+1]);4346}4347else if(strcmp(argv[arg],"-nonodes") == 0) {4348eg->nodes3d = atoi(argv[arg+1]);4349}4350else if(strcmp(argv[arg],"-sidefind") == 0) {4351eg->findsides = 0;4352for(i=arg+1;i<argc && strncmp(argv[i],"-",1); i++) {4353eg->sidebulk[i-1-arg] = atoi(argv[i]);4354eg->findsides++;4355}4356}4357else if(strcmp(argv[arg],"-findbound") == 0) {4358eg->findsides = 0;4359for(i=arg+1;i+1<argc && strncmp(argv[i],"-",1); i += 2) {4360eg->sidebulk[i-1-arg] = atoi(argv[i]);4361eg->sidebulk[i-arg] = atoi(argv[i+1]);4362eg->findsides++;4363}4364}4365else if(strcmp(argv[arg],"-") == 0 ) {4366printf("Unknown in-line argument: %s\n",argv[arg]);4367bigerror("Cannot deal with argument, aborting!");4368}43694370}43714372{4373int badpoint;4374char *ptr1,*ptr2;4375ptr1 = strrchr(eg->filesout[0], '.');4376if(ptr1) {4377badpoint=FALSE;4378ptr2 = strrchr(eg->filesout[0], '/');4379if(ptr2 && ptr2 > ptr1) badpoint = TRUE;4380if(!badpoint) *ptr1 = '\0';4381}4382}43834384printf("Output will be saved to file %s.\n",eg->filesout[0]);43854386return(0);4387}43884389439043914392int LoadCommands(char *prefix,struct ElmergridType *eg,4393struct GridType *grid, int mode,int info)4394{4395char filename[MAXFILESIZE];4396char command[MAXLINESIZE],params[MAXLINESIZE],*cp;43974398FILE *in=NULL;4399int i,j,iostat;44004401iodebug = FALSE;44024403if( mode == 0) {4404if ((in = fopen("ELMERGRID_STARTINFO","r"))) {4405iostat = fscanf(in,"%s",filename);4406fclose(in);4407printf("Using the file %s defined in ELMERGRID_STARTINFO\n",filename);4408if ((in = fopen(filename,"r")) == NULL) {4409printf("LoadCommands: opening of the file '%s' wasn't successful !\n",filename);4410return(1);4411}4412else printf("Loading ElmerGrid commands from file '%s'.\n",filename);4413}4414else4415return(2);4416}4417else if(mode == 1) {4418AddExtension(prefix,filename,"eg");4419if ((in = fopen(filename,"r")) == NULL) {4420printf("LoadCommands: opening of the file '%s' wasn't successful !\n",filename);4421return(3);4422}4423if(info) printf("Loading ElmerGrid commands from file '%s'.\n",filename);4424}4425else if(mode == 2) {4426AddExtension(prefix,filename,"grd");4427if ((in = fopen(filename,"r")) == NULL) {4428printf("LoadCommands: opening of the file '%s' wasn't successful !\n",filename);4429return(4);4430}4431if(info) printf("\nLoading ElmerGrid commands from file '%s'.\n",filename);4432}4433443444354436for(;;) {44374438if(GetCommand(command,params,in)) {4439printf("Reached the end of command file\n");4440goto end;4441}44424443/* If the mode is the command file mode read also the file information from the command file. */44444445if(mode <= 1) {4446if(strstr(command,"INPUT FILE")) {4447sscanf(params,"%s",eg->filesin[0]);4448}44494450else if(strstr(command,"OUTPUT FILE")) {4451sscanf(params,"%s",eg->filesout[0]);4452eg->filerenamed = TRUE;4453}44544455else if(strstr(command,"INPUT MODE")) {4456for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);44574458for(i=0;i<=MAXINMETHODS;i++) {4459if(strstr(params,InMethods[i])) {4460eg->inmethod = i;4461break;4462}4463}4464if(i>MAXINMETHODS) sscanf(params,"%d",&eg->inmethod);4465}44664467else if(strstr(command,"OUTPUT MODE")) {4468for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);44694470/* Type of output file (fewer options) */4471for(i=1;i<=MAXOUTMETHODS;i++) {4472if(strstr(params,OutMethods[i])) {4473eg->outmethod = i;4474break;4475}4476}4477if(i>MAXOUTMETHODS) sscanf(params,"%d",&eg->outmethod);4478}4479}4480/* End of command file specific part */448144824483if(strstr(command,"DECIMALS")) {4484sscanf(params,"%d",&eg->decimals);4485}4486else if(strstr(command,"BOUNDARY OFFSET")) {4487sscanf(params,"%d",&eg->bcoffset);4488}4489else if(strstr(command,"TRIANGLES CRITICAL ANGLE")) {4490sscanf(params,"%le",&eg->triangleangle);4491}4492else if(strstr(command,"TRIANGLES")) {4493for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4494if(strstr(params,"TRUE")) eg->triangles = TRUE;4495}4496else if(strstr(command,"MERGE NODES")) {4497eg->merge = TRUE;4498sscanf(params,"%le",&eg->cmerge);4499}4500else if(strstr(command,"UNITE")) {4501for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4502if(strstr(params,"TRUE")) eg->unitemeshes = TRUE;4503}4504else if(strstr(command,"UNITENOOVERLAP")) {4505for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4506if(strstr(params,"TRUE")) {4507eg->unitemeshes = TRUE;4508eg->unitenooverlap = TRUE;4509}4510}45114512else if(strstr(command,"ORDER NODES")) {4513eg->order = TRUE;4514if(eg->dim == 1)4515sscanf(params,"%le",&eg->corder[0]);4516else if(eg->dim == 2)4517sscanf(params,"%le%le",&eg->corder[0],&eg->corder[1]);4518else if(eg->dim == 3)4519sscanf(params,"%le%le%le",&eg->corder[0],&eg->corder[1],&eg->corder[2]);4520}4521else if(strstr(command,"SCALE")) {4522eg->scale = TRUE;4523if(eg->dim == 1)4524sscanf(params,"%le",&eg->cscale[0]);4525else if(eg->dim == 2)4526sscanf(params,"%le%le",&eg->cscale[0],&eg->cscale[1]);4527else if(eg->dim == 3)4528sscanf(params,"%le%le%le",&eg->cscale[0],&eg->cscale[1],&eg->cscale[2]);4529}4530else if(strstr(command,"CENTRALIZE")) {4531eg->center = TRUE;4532}4533else if(strstr(command,"TRANSLATE")) {4534eg->translate = TRUE;4535if(eg->dim == 1)4536sscanf(params,"%le",&eg->ctranslate[0]);4537else if(eg->dim == 2)4538sscanf(params,"%le%le",&eg->ctranslate[0],&eg->ctranslate[1]);4539else if(eg->dim == 3)4540sscanf(params,"%le%le%le",&eg->ctranslate[0],&eg->ctranslate[1],&eg->ctranslate[2]);4541}4542else if(strstr(command,"ROTATE MESH")) {4543eg->rotate = TRUE;4544sscanf(params,"%le%le%le",&eg->crotate[0],&eg->crotate[1],&eg->crotate[2]);4545}4546else if(strstr(command,"CLONE")) {4547if(strstr(command,"CLONE SIZE")) {4548if(eg->dim == 1)4549sscanf(params,"%le",&eg->clonesize[0]);4550else if(eg->dim == 2)4551sscanf(params,"%le%le",&eg->clonesize[0],&eg->clonesize[1]);4552else if(eg->dim == 3)4553sscanf(params,"%le%le%le",&eg->clonesize[0],&eg->clonesize[1],&eg->clonesize[2]);4554}4555else {4556if(eg->dim == 1)4557sscanf(params,"%d",&eg->clone[0]);4558else if(eg->dim == 2)4559sscanf(params,"%d%d",&eg->clone[0],&eg->clone[1]);4560else if(eg->dim == 3)4561sscanf(params,"%d%d%d",&eg->clone[0],&eg->clone[1],&eg->clone[2]);4562}4563}4564else if(strstr(command,"MERGE")) {4565eg->merge = TRUE;4566sscanf(params,"%le",&eg->cmerge);4567}4568else if(strstr(command,"MIRROR")) {4569if(eg->dim == 1)4570sscanf(params,"%d",&eg->mirror[0]);4571else if(eg->dim == 2)4572sscanf(params,"%d%d",&eg->mirror[0],&eg->mirror[1]);4573else if(eg->dim == 3)4574sscanf(params,"%d%d%d",&eg->mirror[0],&eg->mirror[1],&eg->mirror[2]);4575}4576else if(strstr(command,"POLAR RADIUS")) {4577eg->polar = TRUE;4578sscanf(params,"%le",&eg->polarradius);4579}4580else if(strstr(command,"CYLINDER")) {4581for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4582if(strstr(params,"TRUE")) eg->cylinder = TRUE;4583}4584else if(strstr(command,"REDUCE DEGREE")) {4585eg->reduce = TRUE;4586sscanf(params,"%d%d",&eg->reducemat1,&eg->reducemat2);4587}4588else if(strstr(command,"INCREASE DEGREE")) {4589for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4590if(strstr(params,"TRUE")) eg->increase = TRUE;4591}4592else if(strstr(command,"METIS OPTION")) {4593#if USE_METIS4594sscanf(params,"%d",&eg->partopt);4595#else4596printf("This version of ElmerGrid was compiled without Metis library!\n");4597#endif4598}4599else if(strstr(command,"METIS")) {4600#if USE_METIS4601sscanf(params,"%d",&eg->metis);4602#else4603printf("This version of ElmerGrid was compiled without Metis library!\n");4604#endif4605}4606else if(strstr(command,"METISKWAY")) {4607#if USE_METIS4608sscanf(params,"%d",&eg->metis);4609eg->partopt = 3;4610#else4611printf("This version of ElmerGrid was compiled without Metis library!\n");4612#endif4613}4614else if(strstr(command,"METISREC")) {4615#if USE_METIS4616sscanf(params,"%d",&eg->metis);4617eg->partopt = 2;4618#else4619printf("This version of ElmerGrid was compiled without Metis library!\n");4620#endif4621}4622else if(strstr(command,"PARTITION DUAL")) {4623for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4624if(strstr(params,"TRUE")) eg->partdual = TRUE;4625}4626else if(strstr(command,"PARTJOIN")) {4627sscanf(params,"%d",&eg->partjoin);4628}4629else if(strstr(command,"PARTITION ORDER")) {4630eg->partorder = 1;4631if(eg->dim == 2) sscanf(params,"%le%le",&eg->partcorder[0],&eg->partcorder[1]);4632if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->partcorder[0],4633&eg->partcorder[1],&eg->partcorder[2]);4634}4635else if(strstr(command,"PARTITION") || strstr(command,"PARTCYL") || strstr(command,"PARTCELL")) {4636if(eg->dim == 2) sscanf(params,"%d%d",&eg->partdim[0],&eg->partdim[1]);4637if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->partdim[0],&eg->partdim[1],&eg->partdim[2]);4638eg->partitions = 1;4639for(i=0;i<eg->dim;i++) {4640if(eg->partdim[i] < 1) eg->partdim[i] = 1;4641eg->partitions *= eg->partdim[i];4642}4643if( strstr(command,"PARTCYL") ) eg->partopt = 3;4644if( strstr(command,"PARTCCELL") ) eg->partopt = 2;4645}4646else if(strstr(command,"PERIODIC")) {4647if(eg->dim == 2) sscanf(params,"%d%d",&eg->periodicdim[0],&eg->periodicdim[1]);4648if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->periodicdim[0],4649&eg->periodicdim[1],&eg->periodicdim[2]);4650}4651else if(strstr(command,"HALO")) {4652for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4653if(strstr(params,"TRUE")) eg->parthalo[1] = TRUE;4654}4655else if(strstr(command,"BOUNDARY HALO")) {4656for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4657if(strstr(params,"TRUE")) eg->parthalo[2] = TRUE;4658}4659else if(strstr(command,"EXTRUDED HALO")) {4660for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4661if(strstr(params,"TRUE")) eg->parthalo[3] = TRUE;4662}4663else if(strstr(command,"GREEDY HALO")) {4664for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4665if(strstr(params,"TRUE")) eg->parthalo[4] = TRUE;4666}4667else if(strstr(command,"PARTBW")) {4668for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4669if(strstr(params,"TRUE")) eg->partbw = TRUE;4670}4671else if(strstr(command,"PARTHYPRE")) {4672for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4673if(strstr(params,"TRUE")) eg->parthypre = TRUE;4674}4675else if(strstr(command,"INDIRECT")) {4676for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4677if(strstr(params,"TRUE")) eg->partitionindirect = TRUE;4678}4679else if(strstr(command,"BOUNDARY TYPE MAPPINGS")) {4680for(i=0;i<MAXMAPPINGS;i++) {4681if(i>0) Getline(params,in);4682for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4683if(strstr(params,"END")) break;4684cp = params;4685sscanf(params,"%d%d%d",&eg->sidemap[3*i],&eg->sidemap[3*i+1],&eg->sidemap[3*i+2]);4686}4687printf("Found %d boundary type mappings\n",i);4688eg->sidemappings = i;4689}4690else if(strstr(command,"BULK TYPE MAPPINGS")) {4691for(i=0;i<MAXMAPPINGS;i++) {4692if(i>0) Getline(params,in);4693for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4694if(strstr(params,"END")) break;4695cp = params;4696sscanf(params,"%d%d%d",&eg->bulkmap[3*i],&eg->bulkmap[3*i+1],&eg->bulkmap[3*i+2]);4697}4698printf("Found %d bulk type mappings\n",i);4699eg->bulkmappings = i;4700}4701else if(strstr(command,"COORDINATE MAPPING")) {4702sscanf(params,"%d%d%d",&eg->coordinatemap[0],&eg->coordinatemap[1],&eg->coordinatemap[2]);4703}4704else if(strstr(command,"BOUNDARY BOUNDARY")) {4705for(i=0;i<MAXBOUNDARIES;i++) {4706if(i>0) Getline(params,in);4707for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4708if(strstr(params,"END")) break;4709cp = params;4710sscanf(params,"%d%d%d",&eg->boundbound[3*i+2],&eg->boundbound[3*i],&eg->boundbound[3*i+1]);4711}4712printf("Found %d boundary boundary definitions\n",i);4713eg->boundbounds = i;4714}4715else if(strstr(command,"MATERIAL BOUNDARY")) {4716for(i=0;i<MAXBOUNDARIES;i++) {4717if(i>0) Getline(params,in);4718for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4719if(strstr(params,"END")) break;4720cp = params;4721sscanf(params,"%d%d%d",&eg->bulkbound[3*i+2],&eg->bulkbound[3*i],&eg->bulkbound[3*i+1]);4722}4723printf("Found %d material boundary definitions\n",i);4724eg->bulkbounds = i;4725}47264727else if(strstr(command,"RENUMBER BOUNDARY")) {4728for(i=0;i<MAXBOUNDARIES;i++) {4729for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4730if(strstr(params,"END")) break;4731cp = params;4732sscanf(params,"%d%d%d",&eg->sidemap[3*i],&eg->sidemap[3*i+1],&eg->sidemap[3*i+2]);4733}4734printf("Found %d boundary mappings\n",i);4735eg->sidemappings = i;4736}4737else if(strstr(command,"RENUMBER MATERIAL")) {4738for(i=0;i<MAXBOUNDARIES;i++) {4739for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4740if(strstr(params,"END")) break;4741cp = params;4742sscanf(params,"%d%d%d",&eg->bulkmap[3*i],&eg->bulkmap[3*i+1],&eg->bulkmap[3*i+2]);4743}4744printf("Found %d material mappings\n",i);4745eg->bulkmappings = i;4746}47474748else if(strstr(command,"BOUNDARY LAYER")) {4749if(strstr(command,"BOUNDARY LAYER MOVE")) {4750sscanf(params,"%d",&eg->layermove);4751}4752else if(strstr(command,"BOUNDARY LAYER EPSILON")) {4753sscanf(params,"%le",&eg->layereps);4754}4755else {4756for(i=0;i<MAXBOUNDARIES;i++) {4757if(i>0) Getline(params,in);4758for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4759cp = params;47604761if(strstr(params,"END") || strstr(params,"End") ) break;4762eg->layerbounds[i] = next_int(&cp);4763eg->layernumber[i] = next_int(&cp);4764eg->layerthickness[i] = next_real(&cp);4765eg->layerratios[i] = next_real(&cp);4766eg->layerparents[i] = next_int(&cp);4767}4768printf("Found %d boundary layers\n",i);4769eg->layers = i;4770}4771}4772else if(strstr(command,"REMOVE LOWER DIMENSIONAL BOUNDARIES")) {4773for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4774if(strstr(params,"TRUE")) eg->removelowdim = TRUE;4775}4776else if(strstr(command,"REMOVE INTERNAL BOUNDARIES")) {4777for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4778if(strstr(params,"TRUE")) eg->removeintbcs = TRUE;4779}4780else if(strstr(command,"REMOVE UNUSED NODES")) {4781for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4782if(strstr(params,"TRUE")) eg->removeunused = TRUE;4783}4784else if(strstr(command,"NO MESH NAMES")) {4785for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4786if(strstr(params,"TRUE")) eg->usenames = FALSE;4787}4788else if(strstr(command,"REORDER MATERIAL")) {4789for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4790if(strstr(params,"TRUE")) eg->bulkorder = TRUE;4791}4792else if(strstr(command,"REORDER BOUNDARY")) {4793for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4794if(strstr(params,"TRUE")) eg->boundorder = TRUE;4795}4796else if(strstr(command,"DIMENSION")) {4797sscanf(params,"%d",&eg->dim);4798}4799else if(strstr(command,"ISOPARAMETRIC")) {4800for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4801if(strstr(params,"TRUE")) eg->isoparam = TRUE;4802}4803else if(strstr(command,"NO BOUNDARY")) {4804for(j=0;j<MAXLINESIZE;j++) params[j] = toupper(params[j]);4805if(strstr(params,"TRUE")) eg->saveboundaries = FALSE;4806}4807else if(strstr(command,"LAYERED BOUNDARIES")) {4808for(i=0;i<MAXLINESIZE;i++) params[i] = toupper(params[i]);4809if(strstr(params,"TRUE")) grid->layeredbc = 1;4810if(strstr(params,"FALSE")) grid->layeredbc = 0;4811}4812else if(strstr(command,"EXTRUDED")) {4813grid->dimension = 3;48144815if(strstr(command,"EXTRUDED DIVISIONS")) {4816sscanf(params,"%d",&grid->zcells);4817}4818if(strstr(command,"EXTRUDED BC OFFSET")) {4819sscanf(params,"%d",&grid->layerbcoffset);4820}4821else if(strstr(command,"EXTRUDED LIMITS")) {4822cp = params;4823for(i=0;i<=grid->zcells;i++ ) {4824grid->z[i] = next_real(&cp);4825if(i > 0 && grid->z[i] < grid->z[i-1]) {4826printf("Extruded limits %d: %12.6le %12.6le\n",i,grid->z[i],grid->z[i-1]);4827bigerror("Values for limits should be a growing series, existing\n");4828}4829}4830}4831else if(strstr(command,"EXTRUDED SIZES")) {4832cp = params;4833for(i=1;i<=grid->zcells;i++) grid->z[i] = next_real(&cp);4834for(i=1;i<=grid->zcells;i++) grid->z[i] = grid->z[i-1] + grid->z[i];4835}4836else if(strstr(command,"EXTRUDED ELEMENTS")) {4837cp = params;4838for(i=1;i<=grid->zcells;i++) grid->zelems[i] = next_int(&cp);4839grid->autoratio = FALSE;4840}4841else if(strstr(command,"EXTRUDED RATIOS")) {4842cp = params;4843for(i=1;i<=grid->zcells;i++) grid->zexpand[i] = next_real(&cp);4844}4845else if(strstr(command,"EXTRUDED DENSITIES")) {4846cp = params;4847for(i=1;i<=grid->zcells;i++) grid->zdens[i] = next_real(&cp);4848}4849else if(strstr(command,"EXTRUDED STRUCTURE")) {4850for(i=1;i<= grid->zcells;i++) {4851if(i>1) Getline(params,in);4852sscanf(params,"%d %d %d\n",4853&grid->zfirstmaterial[i],&grid->zlastmaterial[i],&grid->zmaterial[i]);4854}4855}4856else if(strstr(command,"EXTRUDED MAX MATERIAL")) {4857sscanf(params,"%d",&grid->maxmaterial);4858}4859else if(strstr(command,"EXTRUDED MATERIAL MAPPINGS")) {4860grid->zmaterialmap = Imatrix(1,grid->zcells,1,grid->maxmaterial);4861for(i=1;i<=grid->zcells;i++) {4862if(i>1) Getline(params,in);4863cp = params;4864for(j=1;j<=grid->maxmaterial;j++)4865grid->zmaterialmap[i][j] = next_int(&cp);4866}4867grid->zmaterialmapexists = TRUE;4868}4869else if(strstr(command,"EXTRUDED HELICITY")) {4870sscanf(params,"%le",&grid->zhelicity);4871grid->zhelicityexists = TRUE;4872}48734874}4875}48764877end:4878printf("Read commands from a file\n");4879fclose(in);4880return(0);4881}488248834884488548864887static int FindParentSide(struct FemType *data,struct BoundaryType *bound,4888int sideelem,int sideelemtype,int *sideind)4889{4890int i,j,sideelemtype2,elemind,parent,normal,elemtype;4891int elemsides,side,sidenodes,nohits,hit,hit1,hit2;4892int sideind2[MAXNODESD1];4893int debug;48944895hit = FALSE;4896elemsides = 0;4897elemtype = 0;4898hit1 = FALSE;4899hit2 = FALSE;49004901debug = FALSE;49024903for(parent=1;parent<=2;parent++) {4904if(parent == 1)4905elemind = bound->parent[sideelem];4906else4907elemind = bound->parent2[sideelem];49084909if(elemind > 0) {4910elemtype = data->elementtypes[elemind];4911elemsides = elemtype / 100;49124913if(elemsides == 8) elemsides = 6;4914else if(elemsides == 7) elemsides = 5;4915else if(elemsides == 6) elemsides = 5;4916else if(elemsides == 5) elemsides = 4;49174918for(normal=1;normal >= -1;normal -= 2) {49194920for(side=0;side<elemsides;side++) {49214922if(debug) printf("elem = %d %d %d %d\n",elemind,elemsides,normal,side);49234924GetElementSide(elemind,side,normal,data,&sideind2[0],&sideelemtype2);49254926if(sideelemtype2 < 300 && sideelemtype > 300) break;4927if(sideelemtype2 < 200 && sideelemtype > 200) break;4928if(sideelemtype != sideelemtype2) continue;49294930sidenodes = sideelemtype / 100;49314932for(j=0;j<sidenodes;j++) {4933if(debug) printf("sidenode: %d %d %d\n",j,sideind[j],sideind2[j]);49344935hit = TRUE;4936for(i=0;i<sidenodes;i++)4937if(sideind[(i+j)%sidenodes] != sideind2[i]) hit = FALSE;49384939if(hit == TRUE) {4940if(parent == 1) {4941hit1 = TRUE;4942bound->side[sideelem] = side;4943bound->normal[sideelem] = normal;4944}4945else {4946hit2 = TRUE;4947bound->side2[sideelem] = side;4948}4949goto skip;4950}4951}4952}4953}495449554956/* this finding of sides does not guarantee that normals are oriented correctly */4957normal = 1;4958hit = FALSE;49594960for(side=0;;side++) {49614962if(0) printf("side = %d\n",side);49634964GetElementSide(elemind,side,normal,data,&sideind2[0],&sideelemtype2);49654966if(sideelemtype2 == 0 ) break;4967if(sideelemtype2 < 300 && sideelemtype > 300) break;4968if(sideelemtype2 < 200 && sideelemtype > 200) break;4969if(sideelemtype != sideelemtype2) continue;49704971sidenodes = sideelemtype % 100;49724973nohits = 0;4974for(j=0;j<sidenodes;j++)4975for(i=0;i<sidenodes;i++)4976if(sideind[i] == sideind2[j]) nohits++;4977if(nohits == sidenodes) {4978hit = TRUE;4979if(parent == 1) {4980hit1 = TRUE;4981bound->side[sideelem] = side;4982}4983else {4984hit2 = TRUE;4985bound->side2[sideelem] = side;4986}4987goto skip;4988}49894990}49914992skip:4993if(!hit) {4994printf("FindParentSide: cannot locate BC element in parent %d: %d\n",parent,elemind);4995printf("BC elem %d of type %d with corner indexes: ",sideelem,sideelemtype);4996for(i=0;i<sideelemtype/100;i++)4997printf(" %d ",sideind[i]);4998printf("\n");49995000printf("Bulk elem %d of type %d with corner indexes: ",elemind,elemtype);5001j = elemtype/100;5002if( j >= 5 && j<=7 ) j = j-1;5003for(i=0;i<j;i++)5004printf(" %d ",data->topology[elemind][i]);5005printf("\n");5006}5007}5008}50095010if(hit1 || hit2)5011return(0);5012else5013return(1);5014}501550165017static int Getnamerow(char *line,FILE *io,int upper)5018{5019int i,isend;5020char *charend;502150225023charend = fgets(line,MAXLINESIZE,io);5024isend = (charend == NULL);50255026if(isend)5027return(1);5028else5029return(0);5030}5031503250335034int LoadElmerInput(struct FemType *data,struct BoundaryType *bound,5035char *prefix,int nonames, int info)5036/* This procedure reads the mesh assuming ElmerSolver format.5037*/5038{5039int noknots,noelements,nosides,maxelemtype,maxnodes,nonodes;5040int sideind[MAXNODESD1],tottypes,elementtype;5041int i,j,k,l,dummyint,cdstat,fail;5042int falseparents,noparents,bctopocreated;5043int activeperm,activeelemperm,mini,maxi,minelem,maxelem,p1,p2;5044int *nodeperm,*elemperm,*invperm,*invelemperm;5045int iostat,noelements0;5046FILE *in;5047char line[MAXLINESIZE],line2[MAXLINESIZE],filename[MAXFILESIZE],directoryname[MAXFILESIZE];5048char *ptr1,*ptr2;504950505051sprintf(directoryname,"%s",prefix);5052cdstat = chdir(directoryname);50535054if(info) {5055if(cdstat)5056printf("Loading mesh in ElmerSolver format from root directory.\n");5057else5058printf("Loading mesh in ElmerSolver format from directory %s.\n",directoryname);5059}50605061InitializeKnots(data);506250635064sprintf(filename,"%s","mesh.header");5065if ((in = fopen(filename,"r")) == NULL) {5066printf("LoadElmerInput: The opening of the header-file %s failed!\n",5067filename);5068return(1);5069}5070else5071printf("Loading header from %s\n",filename);50725073GETLINE;5074sscanf(line,"%d %d %d",&noknots,&noelements,&nosides);5075GETLINE;5076sscanf(line,"%d",&tottypes);50775078maxelemtype = 0;5079maxnodes = 0;5080for(i=1;i<=tottypes;i++) {5081GETLINE;5082sscanf(line,"%d",&dummyint);5083maxelemtype = MAX( dummyint, maxelemtype );5084j = maxelemtype % 100;5085maxnodes = MAX( j, maxnodes );5086}5087printf("Maximum elementtype index is: %d\n",maxelemtype);5088printf("Maximum number of nodes in element is: %d\n",maxnodes);5089fclose(in);50905091data->dim = GetElementDimension(maxelemtype);50925093data->maxnodes = maxnodes;5094data->noknots = noknots;5095data->noelements = noelements0 = noelements;509650975098if(info) printf("Allocating for %d knots and %d elements.\n",5099noknots,noelements);5100AllocateKnots(data);510151025103sprintf(filename,"%s","mesh.nodes");5104if ((in = fopen(filename,"r")) == NULL) {5105if(info) printf("LoadElmerInput: The opening of the nodes-file %s failed!\n",5106filename);5107bigerror("Cannot continue without nodes file!\n");5108}5109else5110printf("Loading %d Elmer nodes from %s\n",noknots,filename);51115112activeperm = FALSE;5113for(i=1; i <= noknots; i++) {5114GETLINE;5115sscanf(line,"%d %d %le %le %le",5116&j, &dummyint, &(data->x[i]),&(data->y[i]),&(data->z[i]));5117if(j != i && !activeperm) {5118printf("LoadElmerInput: The node number (%d) at node %d is not compact, creating permutation\n",j,i);5119activeperm = TRUE;5120nodeperm = Ivector(1,noknots);5121for(k=1;k<i;k++) nodeperm[k] = k;5122}5123if(activeperm) nodeperm[i] = j;5124}5125fclose(in);512651275128/* Create inverse permutation for nodes */5129if(activeperm) {5130for(i=1;i<=noknots;i++) {5131if(i==1) {5132mini = nodeperm[i];5133maxi = nodeperm[i];5134}5135else {5136mini = MIN(nodeperm[i],mini);5137maxi = MAX(nodeperm[i],maxi);5138}5139}5140if(info) printf("LoadElmerInput: Node index range is: [%d %d]\n",mini,maxi);5141invperm = Ivector(mini,maxi);5142for(i=mini;i<=maxi;i++)5143invperm[i] = -1;5144for(i=1;i<=noknots;i++) {5145j = nodeperm[i];5146if( invperm[j] > 0 )5147printf("LoadElmerInput: Node %d is redundant which may be problematic!\n",j);5148else5149invperm[j] = i;5150}5151}5152else {5153mini = 1;5154maxi = noknots;5155}515651575158activeelemperm = FALSE;5159sprintf(filename,"%s","mesh.elements");5160if ((in = fopen(filename,"r")) == NULL) {5161printf("LoadElmerInput: The opening of the element-file %s failed!\n",5162filename);5163bigerror("Cannot continue without element file!\n");5164}5165else5166if(info) printf("Loading %d bulk elements from %s\n",noelements,filename);51675168for(i=1; i <= noelements; i++) {5169iostat = fscanf(in,"%d",&j);5170if(iostat <= 0 ) {5171printf("LoadElmerInput: Failed reading element line %d, reducing size of element table to %d!\n",i,i-1);5172data->noelements = noelements = i-1;5173break;5174}51755176if(i != j && !activeelemperm) {5177printf("LoadElmerInput: The element numbering (%d) at element %d is not compact, creating permutation\n",j,i);5178activeelemperm = TRUE;5179elemperm = Ivector(1,noelements0);5180for(k=1; k < i; k++)5181elemperm[k] = k;5182}5183if( activeelemperm ) elemperm[i] = j;5184iostat = fscanf(in,"%d %d",&(data->material[i]),&elementtype);5185if( iostat < 2 ) {5186printf("LoadElmerInput: Failed reading definitions for bulk element %d\n",j);5187bigerror("Cannot continue without this data!\n");5188}5189if(elementtype > maxelemtype ) {5190printf("Invalid bulk elementtype: %d\n",elementtype);5191bigerror("Cannot continue with invalid elements");5192}5193data->elementtypes[i] = elementtype;5194nonodes = elementtype % 100;5195if( nonodes > maxnodes ) {5196printf("Number of nodes %d in element %d is greater than allocated maximum %d\n",nonodes,j,maxnodes);5197bigerror("Cannot continue with invalid elements");5198}5199for(k=0;k<nonodes;k++) {5200iostat = fscanf(in,"%d",&l);5201if( l < mini || l > maxi ) {5202printf("Node %d in element %d is out of range: %d\n",k+1,j,l);5203bigerror("Cannot continue with this node numbering");5204}5205if( activeperm )5206data->topology[i][k] = invperm[l];5207else5208data->topology[i][k] = l;5209}5210}5211fclose(in);521252135214/* Create inverse permutation for bulk elements */5215if(activeelemperm) {5216for(i=1;i<=noelements;i++) {5217if(i==1) {5218minelem = elemperm[i];5219maxelem = elemperm[i];5220}5221else {5222minelem = MIN(elemperm[i],minelem);5223maxelem = MAX(elemperm[i],maxelem);5224}5225}5226if(info) printf("LoadElmerInput: Element index range is: [%d %d]\n",minelem,maxelem);5227invelemperm = Ivector(minelem,maxelem);5228for(i=minelem;i<=maxelem;i++)5229invelemperm[i] = -1;5230for(i=1;i<=noelements;i++) {5231j = elemperm[i];5232if( invelemperm[j] > 0 )5233printf("LoadElmerInput: Element %d is redundant which may be problematic!\n",j);5234else5235invelemperm[j] = i;5236}5237}5238else {5239minelem = 1;5240maxelem = noelements;5241}5242524352445245falseparents = 0;5246noparents = 0;5247bctopocreated = FALSE;52485249sprintf(filename,"%s","mesh.boundary");5250if ((in = fopen(filename,"r")) == NULL) {5251printf("LoadElmerInput: The opening of the boundary-file %s failed!\n",5252filename);5253return(4);5254}5255else {5256if(info) printf("Loading %d boundary elements from %s\n",nosides,filename);5257}52585259if( nosides > 0 ) {5260AllocateBoundary(bound,nosides);5261data->noboundaries = 1;5262};52635264i = 0;5265for(k=1; k <= nosides; k++) {52665267iostat = fscanf(in,"%d",&dummyint);5268if( iostat < 1 ) {5269printf("LoadElmerInput: Failed reading boundary element line %d, reducing size of element table to %d!\n",k,i);5270bound->nosides = nosides = i;5271break;5272}5273i++;52745275iostat = fscanf(in,"%d %d %d %d",&(bound->types[i]),&p1,&p2,&elementtype);5276if(iostat < 4 ) {5277printf("LoadElmerInput: Failed reading definitions for boundary element %d\n",k);5278bigerror("Cannot continue without this data!\n");5279}5280if( p1 > 0 && (p1 < minelem || p1 > maxelem ) ) {5281printf("Parent in boundary element %d out of range: %d\n",k,p1);5282bigerror("Cannot continue with bad parents");5283}5284if( p2 > 0 && (p2 < minelem || p2 > maxelem ) ) {5285printf("Parent in boundary element %d out of range: %d\n",k,p2);5286bigerror("Cannot continue with bad parents");5287}52885289if(activeelemperm) {5290if( p1 > 0 ) p1 = invelemperm[p1];5291if( p2 > 0 ) p2 = invelemperm[p2];5292}52935294if(elementtype > maxelemtype ) {5295printf("Invalid boundary elementtype: %d\n",elementtype);5296bigerror("Cannot continue with invalid elements");5297}5298nonodes = elementtype % 100;5299if( nonodes > maxnodes ) {5300printf("Number of nodes %d in side element %d is greater than allocated maximum %d\n",nonodes,dummyint,maxnodes);5301bigerror("Cannot continue with invalid elements");5302}53035304for(j=0;j< nonodes ;j++) {5305iostat = fscanf(in,"%d",&l);5306if(activeperm)5307sideind[j] = invperm[l];5308else5309sideind[j] = l;5310}53115312if( p1 == 0 && p2 != 0 ) {5313bound->parent[i] = p2;5314bound->parent2[i] = p1;5315}5316else {5317bound->parent[i] = p1;5318bound->parent2[i] = p2;5319}53205321if(bound->parent[i] > 0) {5322fail = FindParentSide(data,bound,i,elementtype,sideind);5323if(fail) falseparents++;5324}5325else {5326#if 05327printf("Parents not specified for side %d with inds: ",dummyint);5328for(j=0;j< elementtype%100 ;j++)5329printf("%d ",sideind[j]);5330printf("and type: %d\n",bound->types[i]);5331#endif5332if( !bctopocreated ) {5333bound->elementtypes = Ivector(1,nosides);5334for(j=1;j<=nosides;j++)5335bound->elementtypes[j] = 0;5336bound->topology = Imatrix(1,nosides,0,data->maxnodes-1);5337bctopocreated = TRUE;5338}5339for(j=0;j< elementtype%100 ;j++)5340bound->topology[i][j] = sideind[j];5341bound->elementtypes[i] = elementtype;53425343printf("elementtype = %d %d %d\n",i,elementtype,sideind[0]);5344noparents++;5345}5346}53475348if( falseparents ) {5349printf("There seems to be %d false parents in the mesh\n",falseparents);5350}5351if( noparents ) {5352printf("There seems to be %d bc elements without parents in the mesh\n",noparents);5353}53545355bound->nosides = i;5356fclose(in);53575358/* Save node permutation for later use */5359data->nodepermexist = activeperm;5360if(activeperm) {5361data->nodeperm = nodeperm;5362free_Ivector(invperm,mini,maxi);5363}53645365/* Element permutation is irrelevant probably for practical purposes (?) and hence it is forgotten. */5366if(activeelemperm) {5367free_Ivector(invelemperm,minelem,maxelem);5368free_Ivector(elemperm,1,noelements0);5369}5370537153725373sprintf(filename,"%s","mesh.names");5374if ((in = fopen(filename,"r") )) {5375int isbody,started,nameproblem;53765377isbody = TRUE;5378nameproblem = FALSE;53795380if( nonames ) {5381printf("Ignoring > mesh.names < because it was explicitly requested!\n");5382goto namesend;5383}53845385if(info) printf("Loading names for mesh parts from file %s\n",filename);53865387for(;;) {5388if(Getnamerow(line,in,FALSE)) goto namesend;53895390if(strstr(line,"names for boundaries")) {5391if(info) printf("Reading names for mesh boundaries\n");5392isbody = FALSE;5393continue;5394}5395else if(strstr(line,"names for bodies")) {5396if(info) printf("Reading names for mesh bodies\n");5397isbody = TRUE;5398continue;5399}54005401/* get position for entity name */5402ptr1 = strchr( line,'$');5403if(!ptr1) continue;5404ptr1++;54055406/* get position for entity index and read it */5407ptr2 = strchr( line,'=');5408if(!ptr2) continue;5409ptr2++;5410j = next_int(&ptr2);54115412/* Initialize the entity name by white spaces */5413for(i=0;i<MAXLINESIZE;i++)5414line2[i] = ' ';54155416started = FALSE;5417k = 0;5418for(i=0;i<MAXLINESIZE;i++) {5419if( ptr1[0] == '=' ) {5420/* remove possible trailing white space */5421if(line2[k-1] == ' ') k--;5422line2[k] = '\0';5423break;5424}5425if(started || ptr1[0] != ' ') {5426/* remove possible leading white space */5427line2[k] = ptr1[0];5428started = TRUE;5429k++;5430}5431ptr1++;5432}54335434/* Copy the entityname to mesh structure */5435if( isbody ) {5436if(j < 0 || j >= MAXBODIES ) {5437if(!nameproblem) printf("Cannot treat names for bodies beyond %d\n",j);5438nameproblem++;5439}5440else {5441if(!data->bodyname[j]) data->bodyname[j] = Cvector(0,MAXNAMESIZE);5442strcpy(data->bodyname[j],line2);5443data->bodynamesexist = TRUE;5444}5445}5446else {5447if(j < 0 || j >= MAXBCS ) {5448if(!nameproblem) printf("Cannot treat names for boundaries beyond %d\n",j);5449nameproblem++;5450}5451else {5452if(!data->boundaryname[j]) data->boundaryname[j] = Cvector(0,MAXNAMESIZE);5453strcpy(data->boundaryname[j],line2);5454data->boundarynamesexist = TRUE;5455}5456}5457}5458namesend:54595460if( nameproblem ) {5461data->boundarynamesexist = FALSE;5462data->bodynamesexist = FALSE;5463printf("Number of indexes beyond range: %d\n",nameproblem);5464smallerror("Omitting use of names because some indexes are beyond range, code some more...");5465}5466}546754685469if(!cdstat) cdstat = chdir("..");54705471if(info) printf("Elmer mesh loaded successfully\n");54725473return(0);5474}547554765477int SaveElmerInput(struct FemType *data,struct BoundaryType *bound,5478char *prefix,int decimals,int nooverwrite, int info)5479/* Saves the mesh in a form that may be used as input5480in Elmer calculations.5481*/5482{5483int noknots,noelements,material,sumsides,elemtype,fail,cdstat,bcdim;5484int sideelemtype,conelemtype,nodesd1,nodesd2,newtype;5485int i,j,k,l,bulktypes[MAXELEMENTTYPE+1],sidetypes[MAXELEMENTTYPE+1];5486int alltypes[MAXELEMENTTYPE+1],tottypes;5487int ind[MAXNODESD1],ind2[MAXNODESD1],usedbody[MAXBODIES],usedbc[MAXBCS];5488FILE *out;5489char filename[MAXFILESIZE], outstyle[MAXFILESIZE];5490char directoryname[MAXFILESIZE];54915492if(!data->created) {5493printf("You tried to save points that were never created.\n");5494return(1);5495}54965497noelements = data->noelements;5498noknots = data->noknots;5499sumsides = 0;55005501for(i=0;i<=MAXELEMENTTYPE;i++)5502alltypes[i] = bulktypes[i] = sidetypes[i] = 0;55035504for(i=0;i<MAXBODIES;i++)5505usedbody[i] = 0;5506for(i=0;i<MAXBCS;i++)5507usedbc[i] = 0;55085509sprintf(directoryname,"%s",prefix);55105511if(info) printf("Saving mesh in ElmerSolver format to directory %s.\n",5512directoryname);55135514fail = chdir(directoryname);5515if(fail) {5516#ifdef MINGW325517fail = mkdir(directoryname);5518#else5519fail = mkdir(directoryname,0750);5520#endif5521if(fail) {5522printf("Could not create a result directory!\n");5523return(1);5524}5525else {5526cdstat = chdir(directoryname);5527}5528}5529else {5530if(info) printf("Reusing an existing directory\n");5531if(nooverwrite) {5532if ((out = fopen("mesh.header", "r"))) {5533printf("Mesh seems to already exist, writing is cancelled!\n");5534return(1);5535}5536}5537}553855395540sprintf(filename,"%s","mesh.nodes");5541out = fopen(filename,"w");55425543if(info) printf("Saving %d coordinates to %s.\n",noknots,filename);5544if(out == NULL) {5545printf("opening of file was not successful\n");5546return(2);5547}55485549sprintf(outstyle,"%%d %%d %%.%dg %%.%dg %%.%dg\n",decimals,decimals,decimals);5550for(i=1; i <= noknots; i++)5551fprintf(out,outstyle,i,-1,data->x[i],data->y[i],data->z[i]);55525553fclose(out);55545555sprintf(filename,"%s","mesh.elements");5556out = fopen(filename,"w");5557if(info) printf("Saving %d element topologies to %s.\n",noelements,filename);5558if(out == NULL) {5559printf("opening of file was not successful\n");5560return(3);5561}55625563for(i=1;i<=noelements;i++) {5564elemtype = data->elementtypes[i];5565material = data->material[i];55665567if(material < MAXBODIES) usedbody[material] += 1;5568fprintf(out,"%d %d %d",i,material,elemtype);55695570bulktypes[elemtype] += 1;5571nodesd2 = elemtype%100;5572for(j=0;j < nodesd2;j++)5573fprintf(out," %d",data->topology[i][j]);5574fprintf(out,"\n");5575}5576fclose(out);557755785579sprintf(filename,"%s","mesh.boundary");5580out = fopen(filename,"w");5581if(info) printf("Saving boundary elements to %s.\n",filename);5582if(out == NULL) {5583printf("opening of file was not successful\n");5584return(4);5585}55865587sumsides = 0;558855895590/* Save normal boundaries */5591for(j=0;j < MAXBOUNDARIES;j++) {5592if(bound[j].created == FALSE) continue;5593if(bound[j].nosides == 0) continue;55945595for(i=1; i <= bound[j].nosides; i++) {5596GetBoundaryElement(i,&bound[j],data,ind,&sideelemtype);5597sumsides++;55985599fprintf(out,"%d %d %d %d ",5600sumsides,bound[j].types[i],bound[j].parent[i],bound[j].parent2[i]);5601fprintf(out,"%d",sideelemtype);56025603k = bound[j].types[i];5604if(k < MAXBCS) {5605bcdim = GetElementDimension(sideelemtype);5606usedbc[k] = MAX(usedbc[k],bcdim+1);5607}56085609sidetypes[sideelemtype] += 1;5610nodesd1 = sideelemtype%100;5611for(l=0;l<nodesd1;l++)5612fprintf(out," %d",ind[l]);5613fprintf(out,"\n");5614}5615}56165617newtype = 0;5618for(j=0;j < MAXBOUNDARIES;j++) {5619if(bound[j].created == FALSE) continue;5620for(i=1; i <= bound[j].nosides; i++)5621newtype = MAX(newtype, bound[j].types[i]);5622}5623fclose(out);56245625tottypes = 0;5626for(i=0;i<=MAXELEMENTTYPE;i++) {5627alltypes[i] = bulktypes[i] + sidetypes[i];5628if(alltypes[i]) tottypes++;5629}56305631sprintf(filename,"%s","mesh.header");5632out = fopen(filename,"w");5633if(info) printf("Saving header info to %s.\n",filename);5634if(out == NULL) {5635printf("opening of file was not successful\n");5636return(4);5637}5638fprintf(out,"%-6d %-6d %-6d\n",5639noknots,noelements,sumsides);5640fprintf(out,"%-6d\n",tottypes);5641for(i=0;i<=MAXELEMENTTYPE;i++) {5642if(alltypes[i])5643fprintf(out,"%-6d %-6d\n",i,bulktypes[i]+sidetypes[i]);5644}5645fclose(out);564656475648if(data->boundarynamesexist || data->bodynamesexist) {5649sprintf(filename,"%s","mesh.names");5650out = fopen(filename,"w");5651if(info) printf("Saving names info to %s.\n",filename);5652if(out == NULL) {5653printf("opening of file was not successful\n");5654return(5);5655}56565657if(data->bodynamesexist) {5658fprintf(out,"! ----- names for bodies -----\n");5659for(i=1;i<MAXBODIES;i++)5660if(usedbody[i]) {5661if(data->bodyname[i])5662fprintf(out,"$ %s = %d\n",data->bodyname[i],i);5663else5664fprintf(out,"$ body%d = %d\n",i,i);5665}5666}5667if(data->boundarynamesexist) {5668fprintf(out,"! ----- names for boundaries -----\n");5669for(i=1;i<MAXBCS;i++)5670if(usedbc[i]) {5671bcdim = usedbc[i]-1;5672if(data->boundaryname[i])5673fprintf(out,"$ %s = %d\n",data->boundaryname[i],i);5674else if(bcdim == 2) {5675fprintf(out,"$ surf_bc%d = %d\n",i,i);5676}5677else if(bcdim == 1) {5678fprintf(out,"$ line_bc%d = %d\n",i,i);5679}5680else if(bcdim == 0) {5681fprintf(out,"$ node_bc%d = %d\n",i,i);5682}5683}5684}5685fclose(out);56865687sprintf(filename,"%s","entities.sif");5688out = fopen(filename,"w");5689if(info) printf("Saving entities info to %s.\n",filename);5690if(out == NULL) {5691printf("opening of file was not successful\n");5692return(5);5693}56945695if(data->bodynamesexist) {5696fprintf(out,"!------ Skeleton for body section -----\n");5697j = 0;5698for(i=1;i<MAXBODIES;i++) {5699if(usedbody[i]) {5700j = j + 1;5701fprintf(out,"Body %d\n",j);5702if(data->bodyname[i])5703fprintf(out," Name = %s\n",data->bodyname[i]);5704else5705fprintf(out," Name = body%d\n",i);5706fprintf(out,"End\n\n");5707}5708}5709}57105711if(data->boundarynamesexist) {5712fprintf(out,"!------ Skeleton for boundary section -----\n");5713j = 0;5714for(i=1;i<MAXBCS;i++) {5715if(usedbc[i]) {5716j = j + 1;5717fprintf(out,"Boundary Condition %d\n",j);5718if(data->boundaryname[i])5719fprintf(out," Name = %s\n",data->boundaryname[i]);5720else5721fprintf(out," Name = bc%d\n",i);5722fprintf(out,"End\n\n");5723}5724}5725}5726fclose(out);5727}57285729if(data->nodepermexist) {5730sprintf(filename,"%s","mesh.nodeperm");5731out = fopen(filename,"w");57325733if(info) printf("Saving initial node permutation to %s.\n",filename);5734if(out == NULL) {5735printf("opening of file was not successful\n");5736return(3);5737}5738for(i=1; i <= noknots; i++)5739fprintf(out,"%d %d\n",i,data->nodeperm[i]);5740}574157425743cdstat = chdir("..");57445745return(0);5746}574757485749int CreateElmerGridMesh(struct GridType *grid,5750struct FemType *data,struct BoundaryType *boundaries,5751Real relh,int info) {5752int j;5753struct CellType *cell;57545755for(j=0;j<MAXBOUNDARIES;j++) {5756boundaries[j].created = FALSE;5757boundaries[j].nosides = FALSE;5758}57595760SetElementDivision(grid,relh,info);57615762cell = (struct CellType*)5763malloc((size_t) (grid->nocells+1)*sizeof(struct CellType));5764SetCellData(grid,cell,info);57655766if(grid->dimension == 1)5767SetCellKnots1D(grid,cell,info);5768else5769SetCellKnots(grid,cell,info);57705771CreateKnots(grid,cell,data,0,0);57725773if(grid->noboundaries > 0) {5774for(j=0;j<grid->noboundaries;j++) {5775if(grid->boundsolid[j] < 4) {5776CreateBoundary(cell,data,&(boundaries[j]),grid->boundext[j],grid->boundint[j],57771,grid->boundtype[j],info);5778}5779else {5780CreatePoints(cell,data,&(boundaries[j]),grid->boundext[j],grid->boundint[j],5781grid->boundsolid[j],grid->boundtype[j],info);5782}5783}5784}57855786free(cell);57875788return 0;5789}5790579157925793