/* ElmerGrid - A simple mesh generation and manipulation utility Copyright (C) 1995- , CSC - Scientific Computing Ltd. Author: Peter Råback Email: Peter.Raback@csc.fi Address: CSC - Scientific Computing Ltd. Keilaranta 14 02101 Espoo, Finland This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ /**************************************************************************** * * * Elmergrid * * * * This program creates very easily a structured 2D meshes with BCs. * * The element types include 4, 5, 8, 9, 12 and 16-node rectangles and * * 3, 6 and 10-node triangles. There is also limited 3D functionality * * with 8, 20 and 27-node cubes and 6-node prisms. * * * * The program may also be used as a mesh import and export utility. It * * is able to read several different formats and writes mainly Elmer input * * and output formats. The meshes may also be given some simple operations. * * * * Note: this software was initially part of my first fem implementation * * the Pirfem code, then later called Quickmesh, and finally renamed to * * Elmergrid. The code has never been designed and with new features the * * code has eventually become very dirty and does not present my view of * * good programming. * * * ****************************************************************************/ #include #include #include #include #include #include #include "common.h" #include "nrutil.h" #include "femdef.h" #include "femtypes.h" #include "femmesh.h" #include "femknot.h" #include "feminfo.h" #include "femelmer.h" #include "femfilein.h" #include "femfileout.h" #include "femfact.h" #define MAXMETHODS 17 char *IOmethods[] = { /*0*/ "EG", /*1*/ "ELMERGRID", /*2*/ "ELMERSOLVER", /*3*/ "ELMERPOST", /*4*/ "ANSYS", /*5*/ "IDEAS", /*6*/ "ABAQUS", /*7*/ "FIDAP", /*8*/ "EASYMESH", /*9*/ "COMSOL", /*10*/ "FIELDVIEW", /*11*/ "TRIANGLE", /*12*/ "MEDIT", /*13*/ "GID", /*14*/ "GMSH", /*15*/ "PARTITIONED", /*16*/ "UNV", /*17*/ "NASTRAN", /*18*/ "FASTCAP" }; static void Instructions() { printf("****************** Elmergrid ************************\n"); printf("This program can create simple 2D structured meshes consisting of\n"); printf("linear, quadratic or cubic rectangles or triangles. The meshes may\n"); printf("also be extruded and revolved to create 3D forms. In addition many\n"); printf("mesh formats may be imported into Elmer software. Some options have\n"); printf("not been properly tested. Contact the author if you face problems.\n\n"); printf("The program has two operation modes\n"); printf("A) Command file mode which has the command file as the only argument\n"); printf(" 'ElmerGrid commandfile.eg'\n\n"); printf("B) Inline mode which expects at least three input parameters\n"); printf(" 'ElmerGrid 1 3 test'\n\n"); printf("The first parameter defines the input file format:\n"); printf("1) .grd : Elmergrid file format\n"); printf("2) .mesh.* : Elmer input format\n"); printf("3) .ep : Elmer output format\n"); printf("4) .ansys : Ansys input format\n"); printf("5) .inp : Abaqus input format by Ideas\n"); printf("6) .fil : Abaqus output format\n"); printf("7) .FDNEUT : Gambit (Fidap) neutral file\n"); printf("8) .unv : Universal mesh file format\n"); if(0) printf("8) .d : Easymesh input format\n"); printf("9) .mphtxt : Comsol Multiphysics mesh format\n"); printf("10) .dat : Fieldview format\n"); printf("11) .node,.ele: Triangle 2D mesh format\n"); printf("12) .mesh : Medit mesh format\n"); printf("13) .msh : GID mesh format\n"); printf("14) .msh : Gmsh mesh format\n"); printf("15) .ep.i : Partitioned ElmerPost format\n"); #if 0 printf("16) .unv : Universal mesh file format\n"); printf("17) .msh : Nastran format\n"); #endif printf("\nThe second parameter defines the output file format:\n"); printf("1) .grd : ElmerGrid file format\n"); printf("2) .mesh.* : ElmerSolver format (also partitioned .part format)\n"); printf("3) .ep : ElmerPost format\n"); #if 0 printf("5) .inp : Abaqus input format\n"); printf("7) .fidap : Fidap format\n"); if(0) printf("8) .n .e .s : Easymesh output format\n"); printf("18) .ep : Fastcap input format.\n"); #endif printf("\nThe third parameter is the name of the input file.\n"); printf("If the file does not exist, an example with the same name is created.\n"); printf("The default output file name is the same with a different suffix.\n\n"); printf("There are several additional in-line parameters that are\n"); printf("taken into account only when applicable to the given format.\n"); printf("-out str : name of the output file\n"); printf("-in str : name of a secondary input file\n"); printf("-decimals : number of decimals in the saved mesh (eg. 8)\n"); printf("-triangles : rectangles will be divided to triangles\n"); printf("-merge real : merges nodes that are close to each other\n"); printf("-order real[3] : reorder elements and nodes using c1*x+c2*y+c3*z\n"); printf("-centralize : set the center of the mesh to origin\n"); printf("-scale real[3] : scale the coordinates with vector real[3]\n"); printf("-translate real[3] : translate the nodes with vector real[3]\n"); printf("-rotate real[3] : rotate around the main axis with angles real[3]\n"); printf("-clone int[3] : make ideantilcal copies of the mesh\n"); printf("-clonesize real[3] : the size of the mesh to be cloned if larger to the original\n"); printf("-mirror int[3] : copy the mesh around the origin in coordinate directions\n"); printf("-unite : the meshes will be united\n"); printf("-polar real : map 2D mesh to a cylindrical shell with given radius\n"); printf("-cylinder : map 2D/3D cylindrical mesh to a cartesian mesh\n"); printf("-reduce int[2] : reduce element order at material interval [int1 int2]\n"); printf("-increase : increase element order from linear to quadratic\n"); printf("-bcoffset int : add an offset to the boundary conditions\n"); printf("-discont int : make the boundary to have secondary nodes\n"); printf("-connect int : make the boundary to have internal connection among its elements\n"); printf("-removelowdim : remove boundaries that are two ranks lower than highest dim\n"); printf("-removeunused : remove nodes that are not used in any element\n"); printf("-bulkorder : renumber materials types from 1 so that every number is used\n"); printf("-boundorder : renumber boundary types from 1 so that every number is used\n"); printf("-autoclean : this performs the united action of the three above\n"); printf("-bulkbound int[3] : set the union of materials [int1 int2] to be boundary int3\n"); printf("-boundbound int[3] : set the union of boundaries [int1 int2] to be boundary int3\n"); printf("-bulktype int[3] : set material types in interval [int1 int2] to type int3\n"); printf("-boundtype int[3] : set sidetypes in interval [int1 int2] to type int3\n"); printf("-layer int[2] real[2]: make a boundary layer for given boundary\n"); printf("-layermove int : apply Jacobi filter int times to move the layered mesh\n"); printf("-divlayer int[2] real[2]: make a boundary layer for given boundary\n"); printf("-3d / -2d / -1d : mesh is 3, 2 or 1-dimensional (applies to examples)\n"); printf("-isoparam : ensure that higher order elements are convex\n"); printf("-nobound : disable saving of boundary elements in ElmerPost format\n"); printf("\nThe following keywords are related only to the parallel Elmer computations.\n"); printf("-partition int[4] : the mesh will be partitioned in main directions\n"); printf("-partorder real[3] : in the above method, the direction of the ordering\n"); #if PARTMETIS printf("-metis int[2] : the mesh will be partitioned with Metis\n"); #endif printf("-halo : create halo for the partitioning\n"); printf("-indirect : create indirect connections in the partitioning\n"); printf("-periodic int[3] : decleare the periodic coordinate directions for parallel meshes\n"); printf("-saveinterval int[3] : the first, last and step for fusing parallel data\n"); if(0) printf("-names : conserve name information where applicable\n"); #if 0 printf("-map str : file with mapping info for mesh-to-mesh interpolation\n"); #endif #if 0 /* This functionality has moved into the ElmerSolver */ printf("-pelem int[3] : p-elements of power int3 at interval [int1 int2]\n"); printf("-belem int[3] : set bubble dofs to int3 at interval [int1 int2]\n"); #endif } static void Goodbye() { printf("\nThank you for using Elmergrid!\n"); printf("Send bug reports and feature wishes to peter.raback@csc.fi\n"); exit(0); } void InitParameters(struct ElmergridType *eg) { int i; eg->inmethod = 0; eg->outmethod = 0; eg->nofilesin = 1; eg->unitemeshes = FALSE; eg->triangles = FALSE; eg->rotate = FALSE; eg->polar = FALSE; eg->cylinder = FALSE; eg->usenames = FALSE; eg->layers = 0; eg->layereps = 0.0; eg->layermove = 0; eg->partitions = 0; eg->elements3d = 0; eg->nodes3d = 0; eg->metis = 0; eg->partitionhalo = FALSE; eg->partitionindirect = FALSE; eg->reduce = FALSE; eg->increase = FALSE; eg->translate = FALSE; eg->isoparam = FALSE; eg->removelowdim = FALSE; eg->removeunused = FALSE; eg->dim = 3; eg->center = FALSE; eg->scale = FALSE; eg->order = FALSE; eg->boundbounds = 0; eg->saveinterval[0] = eg->saveinterval[1] = eg->saveinterval[2] = 0; eg->bulkbounds = 0; eg->partorder = FALSE; eg->findsides = FALSE; eg->pelems = 0; eg->belems = 0; eg->saveboundaries = TRUE; eg->merge = FALSE; eg->bcoffset = FALSE; eg->periodic = 0; eg->periodicdim[0] = 0; eg->periodicdim[1] = 0; eg->periodicdim[2] = 0; eg->bulkorder = FALSE; eg->boundorder = FALSE; eg->sidemappings = 0; eg->bulkmappings = 0; eg->clone[0] = eg->clone[1] = eg->clone[2] = 0; eg->mirror[0] = eg->mirror[1] = eg->mirror[2] = 0; eg->mirrorbc = 0; eg->decimals = 12; eg->discont = 0; eg->connect = 0; eg->advancedmat = 0; for(i=0;isidebulk[i] = 0; } int InlineParameters(struct ElmergridType *eg,int argc,char *argv[]) { int arg,i,dim; char command[MAXLINESIZE]; dim = eg->dim; printf("Elmergrid reading in-line arguments\n"); /* Type of input file */ strcpy(command,argv[1]); for(i=0;iinmethod = i; break; } } if(i>MAXMETHODS) eg->inmethod = atoi(argv[1]); /* Type of output file (fewer options) */ strcpy(command,argv[2]); for(i=0;ioutmethod = i; break; } } if(i>MAXMETHODS) eg->outmethod = atoi(argv[2]); /* Name of output file */ strcpy(eg->filesin[0],argv[3]); strcpy(eg->filesout[0],eg->filesin[0]); strcpy(eg->mapfile,eg->filesin[0]); /* The optional inline parameters */ for(arg=4;arg = argc) { printf("The secondary input file name is required as a paramater\n"); return(1); } else { strcpy(eg->filesin[eg->nofilesin],argv[arg+1]); printf("A secondary input file %s will be loaded.\n",eg->filesin[eg->nofilesin]); eg->nofilesin++; } } if(strcmp(argv[arg],"-out") == 0) { if(arg+1 >= argc) { printf("The output name is required as a paramater\n"); return(2); } else { strcpy(eg->filesout[0],argv[arg+1]); } } if(strcmp(argv[arg],"-decimals") == 0) { eg->decimals = atoi(argv[arg+1]); } if(strcmp(argv[arg],"-triangles") ==0) { eg->triangles = TRUE; printf("The rectangles will be split to triangles.\n"); } if(strcmp(argv[arg],"-merge") == 0) { if(arg+1 >= argc) { printf("Give a parameter for critical distance.\n"); return(3); } else { eg->merge = TRUE; eg->cmerge = atof(argv[arg+1]); } } if(strcmp(argv[arg],"-order") == 0) { if(arg+dim >= argc) { printf("Give %d parameters for the order vector.\n",dim); return(4); } else { eg->order = TRUE; eg->corder[0] = atof(argv[arg+1]); eg->corder[1] = atof(argv[arg+2]); if(dim==3) eg->corder[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-autoorder") == 0) { eg->order = 2; } if(strcmp(argv[arg],"-halo") == 0) { eg->partitionhalo = TRUE; } if(strcmp(argv[arg],"-indirect") == 0) { eg->partitionindirect = TRUE; } if(strcmp(argv[arg],"-metisorder") == 0) { eg->order = 3; } if(strcmp(argv[arg],"-centralize") == 0) { eg->center = TRUE; } if(strcmp(argv[arg],"-scale") == 0) { if(arg+dim >= argc) { printf("Give %d parameters for the scaling.\n",dim); return(5); } else { eg->scale = TRUE; eg->cscale[0] = atof(argv[arg+1]); eg->cscale[1] = atof(argv[arg+2]); if(dim==3) eg->cscale[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-translate") == 0) { if(arg+dim >= argc) { printf("Give %d parameters for the translate vector.\n",dim); return(6); } else { eg->translate = TRUE; eg->ctranslate[0] = atof(argv[arg+1]); eg->ctranslate[1] = atof(argv[arg+2]); if(dim == 3) eg->ctranslate[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-saveinterval") == 0) { if(arg+dim >= argc) { printf("Give min, max and step for the interval.\n"); return(7); } else { eg->saveinterval[0] = atoi(argv[arg+1]); eg->saveinterval[1] = atoi(argv[arg+2]); eg->saveinterval[2] = atoi(argv[arg+3]); } } if(strcmp(argv[arg],"-rotate") == 0 || strcmp(argv[arg],"-rotate") == 0) { if(arg+dim >= argc) { printf("Give three parameters for the rotation angles.\n"); return(8); } else { eg->rotate = TRUE; eg->crotate[0] = atof(argv[arg+1]); eg->crotate[1] = atof(argv[arg+2]); eg->crotate[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-clone") == 0) { if(arg+dim >= argc) { printf("Give the number of clones in each %d directions.\n",dim); return(9); } else { eg->clone[0] = atoi(argv[arg+1]); eg->clone[1] = atoi(argv[arg+2]); if(dim == 3) eg->clone[2] = atoi(argv[arg+3]); } } if(strcmp(argv[arg],"-clonesize") == 0) { if(arg+dim >= argc) { printf("Give the clone size in each %d directions.\n",dim); return(10); } else { eg->clonesize[0] = atof(argv[arg+1]); eg->clonesize[1] = atof(argv[arg+2]); if(dim == 3) eg->clonesize[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-mirror") == 0) { if(arg+dim >= argc) { printf("Give the symmetry of the coordinate directions, eg. 1 1 0\n"); } else { eg->mirror[0] = atoi(argv[arg+1]); eg->mirror[1] = atoi(argv[arg+2]); if(dim == 3) eg->mirror[2] = atoi(argv[arg+3]); } } if(strcmp(argv[arg],"-mirrorbc") == 0) { if(arg+1 >= argc) { printf("Give the number of symmetry BC.\n"); return(11); } else { eg->mirrorbc = atoi(argv[arg+1]); } } if(strcmp(argv[arg],"-unite") == 0) { eg->unitemeshes = TRUE; printf("The meshes will be united.\n"); } if(strcmp(argv[arg],"-names") == 0) { eg->usenames = TRUE; printf("Names will be conserved when possible\n"); } if(strcmp(argv[arg],"-removelowdim") == 0) { eg->removelowdim = TRUE; printf("Lower dimensional boundaries will be removed\n"); } if(strcmp(argv[arg],"-removeunused") == 0) { eg->removeunused = TRUE; printf("Nodes that do not appear in any element will be removed\n"); } if(strcmp(argv[arg],"-autoclean") == 0) { eg->removelowdim = TRUE; eg->bulkorder = TRUE; eg->boundorder = TRUE; eg->removeunused = TRUE; printf("Lower dimensional boundaries will be removed\n"); printf("Materials and boundaries will be renumbered\n"); printf("Nodes that do not appear in any element will be removed\n"); } if(strcmp(argv[arg],"-polar") == 0) { eg->polar = TRUE; printf("Making transformation to polar coordinates.\n"); if(arg+1 >= argc) { printf("The preferred radius is required as a parameter\n"); eg->polarradius = 1.0; } else { eg->polarradius = atoi(argv[arg+1]); } } if(strcmp(argv[arg],"-cylinder") == 0) { eg->cylinder = TRUE; printf("Making transformation from cylindrical to cartesian coordinates.\n"); } if(strcmp(argv[arg],"-reduce") == 0) { if(arg+2 >= argc) { printf("Give two material for the interval.\n"); return(12); } else { eg->reduce = TRUE; eg->reducemat1 = atoi(argv[arg+1]); eg->reducemat2 = atoi(argv[arg+2]); } } if(strcmp(argv[arg],"-increase") == 0) { eg->increase = TRUE; } if(strcmp(argv[arg],"-bulkorder") == 0) { eg->bulkorder = TRUE; } if(strcmp(argv[arg],"-boundorder") == 0) { eg->boundorder = TRUE; } if(strcmp(argv[arg],"-pelem") == 0) { for(i=arg+1;ipelemmap[3*eg->pelems+i-1-arg] = atoi(argv[i]); eg->pelems++; } if(strcmp(argv[arg],"-belem") == 0) { for(i=arg+1;ibelemmap[3*eg->belems+i-1-arg] = atoi(argv[i]); eg->belems++; } if(strcmp(argv[arg],"-partition") == 0) { if(arg+dim >= argc) { printf("The number of partitions in %d dims is required as paramaters.\n",dim); return(13); } else { eg->partitions = 1; eg->partdim[0] = atoi(argv[arg+1]); eg->partdim[1] = atoi(argv[arg+2]); if(dim == 3) eg->partdim[2] = atoi(argv[arg+3]); eg->partitions = 1; for(i=0;i<3;i++) { if(eg->partdim[i] == 0) eg->partdim[i] = 1; eg->partitions *= eg->partdim[i]; } eg->partopt = 0; if(arg+4 < argc) if(argv[arg+4][0] != '-') eg->partopt = atoi(argv[arg+4]); printf("The mesh will be partitioned with simple division to %d partitions.\n", eg->partitions); } } if(strcmp(argv[arg],"-partorder") == 0) { if(arg+dim >= argc) { printf("Give %d parameters for the order vector.\n",dim); return(14); } else { eg->partorder = 1; eg->partcorder[0] = atof(argv[arg+1]); eg->partcorder[1] = atof(argv[arg+2]); if(dim==3) eg->partcorder[2] = atof(argv[arg+3]); } } if(strcmp(argv[arg],"-metis") == 0) { #if PARTMETIS if(arg+1 >= argc) { printf("The number of partitions is required as a parameter\n"); return(15); } else { eg->metis = atoi(argv[arg+1]); printf("The mesh will be partitioned with Metis to %d partitions.\n",eg->metis); eg->partopt = 0; if(arg+2 < argc) if(argv[arg+2][0] != '-') eg->partopt = atoi(argv[arg+2]); } #else printf("This version of ElmerGrid was compiled without Metis library!\n"); #endif } if(strcmp(argv[arg],"-periodic") == 0) { if(arg+dim >= argc) { printf("Give the periodic coordinate directions (e.g. 1 1 0)\n"); return(16); } else { eg->periodicdim[0] = atoi(argv[arg+1]); eg->periodicdim[1] = atoi(argv[arg+2]); if(dim == 3) eg->periodicdim[2] = atoi(argv[arg+3]); } } if(strcmp(argv[arg],"-discont") == 0) { if(arg+1 >= argc) { printf("Give the discontinuous boundary conditions.\n"); return(17); } else { eg->discontbounds[eg->discont] = atoi(argv[arg+1]); eg->discont++; } } if(strcmp(argv[arg],"-connect") == 0) { if(arg+1 >= argc) { printf("Give the connected boundary conditions.\n"); return(10); } else { eg->connectbounds[eg->connect] = atoi(argv[arg+1]); eg->connect++; } } if(strcmp(argv[arg],"-boundbound") == 0) { for(i=arg+1;i<=arg+3 && iboundbound[3*eg->boundbounds+i-(1+arg)] = atoi(argv[i]); if((i-arg)%3 == 0) eg->boundbounds++; } } if(strcmp(argv[arg],"-bulkbound") == 0) { for(i=arg+1;i<=arg+3 && ibulkbound[3*eg->bulkbounds+i-(1+arg)] = atoi(argv[i]); if((i-arg)%3 == 0) eg->bulkbounds++; } } if(strcmp(argv[arg],"-boundtype") == 0) { for(i=arg+1;isidemap[3*eg->sidemappings+i-1-arg] = atoi(argv[i]); eg->sidemappings++; } if(strcmp(argv[arg],"-bulktype") == 0) { for(i=arg+1;ibulkmap[3*eg->bulkmappings+i-1-arg] = atoi(argv[i]); eg->bulkmappings++; } if(strcmp(argv[arg],"-layer") == 0) { if(arg+4 >= argc) { printf("Give four parameters for the layer: boundary, elements, thickness, ratio.\n"); return(18); } else if(eg->layers == MAXBOUNDARIES) { printf("There can only be %d layers, sorry.\n",MAXBOUNDARIES); return(19); } else { eg->layerbounds[eg->layers] = atoi(argv[arg+1]); eg->layernumber[eg->layers] = atoi(argv[arg+2]); eg->layerthickness[eg->layers] = atof(argv[arg+3]); eg->layerratios[eg->layers] = atof(argv[arg+4]); eg->layerparents[eg->layers] = 0; eg->layers++; } } if(strcmp(argv[arg],"-layermove") == 0) { if(arg+1 >= argc) { printf("Give maximum number of Jacobi filters.\n"); return(20); } else { eg->layermove = atoi(argv[arg+1]); } } /* This uses a very dirty trick where the variables related to argument -layer are used with a negative indexing */ if(strcmp(argv[arg],"-divlayer") == 0) { if(arg+4 >= argc) { printf("Give four parameters for the layer: boundary, elements, relative thickness, ratio.\n"); return(21); } else if(abs(eg->layers) == MAXBOUNDARIES) { printf("There can only be %d layers, sorry.\n",MAXBOUNDARIES); return(22); } else { eg->layerbounds[abs(eg->layers)] = atoi(argv[arg+1]); eg->layernumber[abs(eg->layers)] = atoi(argv[arg+2]); eg->layerthickness[abs(eg->layers)] = atof(argv[arg+3]); eg->layerratios[abs(eg->layers)] = atof(argv[arg+4]); eg->layerparents[abs(eg->layers)] = 0; eg->layers--; } } if(strcmp(argv[arg],"-3d") == 0) { eg->dim = dim = 3; } if(strcmp(argv[arg],"-2d") == 0) { eg->dim = dim = 2; } if(strcmp(argv[arg],"-1d") == 0) { eg->dim = dim = 1; } if(strcmp(argv[arg],"-isoparam") == 0) { eg->isoparam = TRUE; } if(strcmp(argv[arg],"-nobound") == 0) { eg->saveboundaries = FALSE; } /* The following keywords are not actively used */ if(strcmp(argv[arg],"-map") ==0) { if(arg+1 >= argc) { printf("Give the name of the mapping file\n"); return(23); } else { strcpy(eg->mapfile,argv[arg+1]); printf("Mapping file is %s\n",eg->mapfile); } } if(strcmp(argv[arg],"-bcoffset") == 0) { eg->bcoffset = atoi(argv[arg+1]); } if(strcmp(argv[arg],"-noelements") == 0) { eg->elements3d = atoi(argv[arg+1]); } if(strcmp(argv[arg],"-nonodes") == 0) { eg->nodes3d = atoi(argv[arg+1]); } if(strcmp(argv[arg],"-sidefind") == 0) { eg->findsides = 0; for(i=arg+1;isidebulk[i-1-arg] = atoi(argv[i]); eg->findsides++; } } if(strcmp(argv[arg],"-findbound") == 0) { eg->findsides = 0; for(i=arg+1;i+1sidebulk[i-1-arg] = atoi(argv[i]); eg->sidebulk[i-arg] = atoi(argv[i+1]); eg->findsides++; } } } { char *ptr1; ptr1 = strchr(eg->filesout[0], '.'); if (ptr1) *ptr1 = '\0'; ptr1 = strchr(eg->mapfile, '.'); if (ptr1) *ptr1 = '\0'; } printf("Output will be saved to file %s.\n",eg->filesout[0]); return(0); } int LoadCommands(char *prefix,struct ElmergridType *eg, struct GridType *grid, int mode,int info) { char filename[MAXFILESIZE],command[MAXLINESIZE],params[MAXLINESIZE],*cp; FILE *in; int i,j,k,l,error=0; if( mode == 0) { if (in = fopen("ELMERGRID_STARTINFO","r")) { fscanf(in,"%s",filename); fclose(in); printf("Using the file %s defined in ELMERGRID_STARTINFO\n",filename); if ((in = fopen(filename,"r")) == NULL) { printf("LoadCommands: opening of the file '%s' wasn't succesfull !\n",filename); return(1); } else printf("Loading ElmerGrid commands from file '%s'.\n",filename); } else return(2); } if(mode == 1) { AddExtension(prefix,filename,"eg"); if ((in = fopen(filename,"r")) == NULL) { printf("LoadCommands: opening of the file '%s' wasn't succesfull !\n",filename); return(3); } if(info) printf("Loading ElmerGrid commands from file '%s'.\n",filename); } else if(mode == 2) { AddExtension(prefix,filename,"grd"); if ((in = fopen(filename,"r")) == NULL) { printf("LoadCommands: opening of the file '%s' wasn't succesfull !\n",filename); return(4); } if(info) printf("Loading ElmerGrid commands from file '%s'.\n",filename); } for(;;) { if(GetCommand(command,params,in)) { printf("Reached the end of command file\n"); goto end; } /* If the mode is the command file mode read also the file information from the command file. */ if(mode <= 1) { if(strstr(command,"INPUT FILE")) { sscanf(params,"%s",&eg->filesin[0]); } else if(strstr(command,"OUTPUT FILE")) { sscanf(params,"%s",&eg->filesout[0]); } else if(strstr(command,"INPUT MODE")) { for(j=0;jinmethod = i; break; } } if(i>MAXMETHODS) sscanf(params,"%d",&eg->inmethod); } else if(strstr(command,"OUTPUT MODE")) { for(j=0;joutmethod = i; break; } } if(i>MAXMETHODS) sscanf(params,"%d",&eg->outmethod); } } /* End of command file specific part */ if(strstr(command,"DECIMALS")) { sscanf(params,"%d",&eg->decimals); } else if(strstr(command,"TRIANGLES")) { for(j=0;jtriangles = TRUE; } else if(strstr(command,"MERGE NODES")) { eg->merge = TRUE; sscanf(params,"%le",&eg->cmerge); } else if(strstr(command,"UNITE")) { for(j=0;junitemeshes = TRUE; } else if(strstr(command,"ORDER NODES")) { eg->order = TRUE; if(eg->dim == 1) sscanf(params,"%le",&eg->corder[0]); else if(eg->dim == 2) sscanf(params,"%le%le",&eg->corder[0],&eg->corder[1]); else if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->corder[0],&eg->corder[1],&eg->corder[2]); } else if(strstr(command,"SCALE")) { eg->scale = TRUE; if(eg->dim == 1) sscanf(params,"%le",&eg->cscale[0]); else if(eg->dim == 2) sscanf(params,"%le%le",&eg->cscale[0],&eg->cscale[1]); else if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->cscale[0],&eg->cscale[1],&eg->cscale[2]); } else if(strstr(command,"CENTRALIZE")) { eg->center = TRUE; } else if(strstr(command,"TRANSLATE")) { eg->translate = TRUE; if(eg->dim == 1) sscanf(params,"%le",&eg->ctranslate[0]); else if(eg->dim == 2) sscanf(params,"%le%le",&eg->ctranslate[0],&eg->ctranslate[1]); else if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->ctranslate[0],&eg->ctranslate[1],&eg->ctranslate[2]); } else if(strstr(command,"ROTATE MESH")) { eg->rotate = TRUE; sscanf(params,"%le%le%le",&eg->crotate[0],&eg->crotate[1],&eg->crotate[2]); } else if(strstr(command,"CLONE")) { if(strstr(command,"CLONE SIZE")) { if(eg->dim == 1) sscanf(params,"%le",&eg->clonesize[0]); else if(eg->dim == 2) sscanf(params,"%le%le",&eg->clonesize[0],&eg->clonesize[1]); else if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->clonesize[0],&eg->clonesize[1],&eg->clonesize[2]); } else { if(eg->dim == 1) sscanf(params,"%d",&eg->clone[0]); else if(eg->dim == 2) sscanf(params,"%d%d",&eg->clone[0],&eg->clone[1]); else if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->clone[0],&eg->clone[1],&eg->clone[2]); } } else if(strstr(command,"MIRROR")) { if(eg->dim == 1) sscanf(params,"%d",&eg->mirror[0]); else if(eg->dim == 2) sscanf(params,"%d%d",&eg->mirror[0],&eg->mirror[1]); else if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->mirror[0],&eg->mirror[1],&eg->mirror[2]); } else if(strstr(command,"POLAR RADIUS")) { eg->polar = TRUE; sscanf(params,"%le",&eg->polarradius); } else if(strstr(command,"CYLINDER")) { for(j=0;jcylinder = TRUE; } else if(strstr(command,"REDUCE DEGREE")) { eg->reduce = TRUE; sscanf(params,"%d%d",&eg->reducemat1,&eg->reducemat2); } else if(strstr(command,"INCREASE DEGREE")) { for(j=0;jincrease = TRUE; } else if(strstr(command,"ADVANCED ELEMENTS")) { printf("Loading advanced element definitions\n"); for(i=0;i0) Getline(params,in); for(j=0;jadvancedelem[7*i],&eg->advancedelem[7*i+1],&eg->advancedelem[7*i+2], &eg->advancedelem[7*i+3],&eg->advancedelem[7*i+4],&eg->advancedelem[7*i+5], &eg->advancedelem[7*i+6]); } eg->advancedmat = i; printf("Found %d definitions for advanced elements.\n",i); } else if(strstr(command,"POWER ELEMENTS")) { printf("Loading p-type element definitions\n"); for(i=0;i0) Getline(params,in); for(j=0;jpelemmap[3*i],&eg->pelemmap[3*i+1],&eg->pelemmap[3*i+2]); } eg->pelems = i; printf("Found %d definitions for p-elements.\n",i); } else if(strstr(command,"BUBBLE ELEMENTS")) { printf("Loading bubble element definitions\n"); for(i=0;i0) Getline(params,in); for(j=0;jbelemmap[3*i],&eg->belemmap[3*i+1],&eg->belemmap[3*i+2]); } eg->belems = i; printf("Found %d definitions for bubble elements.\n",i); } else if(strstr(command,"METIS OPTION")) { #if PARTMETIS sscanf(params,"%d",&eg->partopt); #else printf("This version of ElmerGrid was compiled without Metis library!\n"); #endif } else if(strstr(command,"METIS")) { #if PARTMETIS sscanf(params,"%d",&eg->metis); #else printf("This version of ElmerGrid was compiled without Metis library!\n"); #endif } else if(strstr(command,"PARTITION ORDER")) { eg->partorder = 1; if(eg->dim == 2) sscanf(params,"%le%le",&eg->partcorder[0],&eg->partcorder[1]); if(eg->dim == 3) sscanf(params,"%le%le%le",&eg->partcorder[0], &eg->partcorder[1],&eg->partcorder[2]); } else if(strstr(command,"PARTITION")) { if(eg->dim == 2) sscanf(params,"%d%d",&eg->partdim[0],&eg->partdim[1]); if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->partdim[0],&eg->partdim[1],&eg->partdim[2]); eg->partitions = 1; for(i=0;idim;i++) { if(eg->partdim[i] < 1) eg->partdim[i] = 1; eg->partitions *= eg->partdim[i]; } } else if(strstr(command,"PERIODIC")) { if(eg->dim == 2) sscanf(params,"%d%d",&eg->periodicdim[0],&eg->periodicdim[1]); if(eg->dim == 3) sscanf(params,"%d%d%d",&eg->periodicdim[0], &eg->periodicdim[1],&eg->periodicdim[2]); } else if(strstr(command,"HALO")) { for(j=0;jpartitionhalo = TRUE; } else if(strstr(command,"INDIRECT")) { for(j=0;jpartitionindirect = TRUE; } else if(strstr(command,"BOUNDARY BOUNDARY")) { for(i=0;i0) Getline(params,in); for(j=0;jboundbound[3*i+2],&eg->boundbound[3*i],&eg->boundbound[3*i+1]); } printf("Found %d boundary boundary definitions\n",i); eg->boundbounds = i; } else if(strstr(command,"MATERIAL BOUNDARY")) { for(i=0;i0) Getline(params,in); for(j=0;jbulkbound[3*i+2],&eg->bulkbound[3*i],&eg->bulkbound[3*i+1]); } printf("Found %d material boundary definitions\n",i); eg->bulkbounds = i; } else if(strstr(command,"RENUMBER BOUNDARY")) { for(i=0;isidemap[3*i],&eg->sidemap[3*i+1],&eg->sidemap[3*i+2]); } printf("Found %d boundary mappings\n",i); eg->sidemappings = i; } else if(strstr(command,"RENUMBER MATERIAL")) { for(i=0;ibulkmap[3*i],&eg->bulkmap[3*i+1],&eg->bulkmap[3*i+2]); } printf("Found %d material mappings\n",i); eg->bulkmappings = i; } else if(strstr(command,"BOUNDARY LAYER")) { if(strstr(command,"BOUNDARY LAYER MOVE")) { sscanf(params,"%d",&eg->layermove); } else if(strstr(command,"BOUNDARY LAYER EPSILON")) { sscanf(params,"%le",&eg->layereps); } else { for(i=0;i0) Getline(params,in); for(j=0;jlayerbounds[i] = next_int(&cp); eg->layernumber[i] = next_int(&cp); eg->layerthickness[i] = next_real(&cp); eg->layerratios[i] = next_real(&cp); eg->layerparents[i] = next_int(&cp); } printf("Found %d boundary layers\n",i); eg->layers = i; } } else if(strstr(command,"REMOVE LOWER DIMENSIONAL BOUNDARIES")) { for(j=0;jremovelowdim = TRUE; } else if(strstr(command,"REMOVE UNUSED NODES")) { for(j=0;jremoveunused = TRUE; } else if(strstr(command,"REORDER MATERIAL")) { for(j=0;jbulkorder = TRUE; } else if(strstr(command,"REORDER BOUNDARY")) { for(j=0;jboundorder = TRUE; } else if(strstr(command,"DIMENSION")) { sscanf(params,"%d",&eg->dim); } else if(strstr(command,"ISOPARAMETRIC")) { for(j=0;jisoparam = TRUE; } else if(strstr(command,"NO BOUNDARY")) { for(j=0;jsaveboundaries = FALSE; } else if(strstr(command,"EXTRUDED")) { grid->dimension = 3; if(strstr(command,"EXTRUDED DIVISIONS")) { sscanf(params,"%d",&grid->zcells); } else if(strstr(command,"EXTRUDED LIMITS")) { cp = params; for(i=0;i<=grid->zcells;i++) grid->z[i] = next_real(&cp); } else if(strstr(command,"EXTRUDED ELEMENTS")) { cp = params; for(i=1;i<=grid->zcells;i++) grid->zelems[i] = next_int(&cp); grid->autoratio = FALSE; } else if(strstr(command,"EXTRUDED RATIOS")) { cp = params; for(i=1;i<=grid->zcells;i++) grid->zexpand[i] = next_real(&cp); } else if(strstr(command,"EXTRUDED DENSITIES")) { cp = params; for(i=1;i<=grid->zcells;i++) grid->zdens[i] = next_real(&cp); } else if(strstr(command,"EXTRUDED STRUCTURE")) { for(i=1;i<= grid->zcells;i++) { if(i>1) Getline(params,in); sscanf(params,"%d %d %d\n", &grid->zfirstmaterial[i],&grid->zlastmaterial[i],&grid->zmaterial[i]); } } } } end: printf("Read commands from a file\n"); return(0); } int main(int argc, char *argv[]) { int i,j,k,l,inmethod,outmethod,info,errorstat,sides; int nogrids,nomeshes,nofile,dim,elementsredone=0; int nodes3d,elements3d,showmem; Real mergeeps; char prefix[MAXFILESIZE]; struct GridType *grids; struct CellType *cell[MAXCASES]; struct FemType data[MAXCASES]; struct BoundaryType *boundaries[MAXCASES]; struct ElmergridType eg; long ii; showmem = TRUE; printf("\nStarting program Elmergrid\n"); InitParameters(&eg); grids = (struct GridType*)malloc((size_t) (MAXCASES)*sizeof(struct GridType)); InitGrid(grids); info = TRUE; if(argc <= 1) { errorstat = LoadCommands(argv[1],&eg,grids,argc-1,info); Instructions(); if(errorstat) Goodbye(); } if(argc == 2) { errorstat = LoadCommands(argv[1],&eg,grids,argc-1,info); if(errorstat) Goodbye(); } else if(argc < 4) { Instructions(); Goodbye(); } else { errorstat = InlineParameters(&eg,argc,argv); if(errorstat) Goodbye(); } if(!eg.outmethod || !eg.inmethod) { printf("Please define the input and output formats\n"); } if(eg.inmethod != 1) { if(eg.outmethod == 1 || eg.outmethod == 8 || eg.outmethod == 9 || eg.outmethod == 10) { printf("input of type %d can't create output of type %d\n", eg.inmethod,eg.outmethod); errorstat++; Goodbye(); } } #if 0 if(eg.inmethod != 8 && eg.outmethod == 5) { printf("To write Easymesh format you need to read easymesh format!\n"); errorstat++; } #endif /**********************************/ printf("\nElmergrid loading data:\n"); dim = eg.dim; nofile = 0; nomeshes = 0; nogrids = 0; inmethod = eg.inmethod; outmethod = eg.outmethod; read_another_file: switch (inmethod) { case 1: if(LoadElmergrid(&grids,&nogrids,eg.filesin[nofile],info) == 1) { if(dim == 3) ExampleGrid3D(&grids,&nogrids,info); if(dim == 2) ExampleGrid2D(&grids,&nogrids,info); if(dim == 1) ExampleGrid1D(&grids,&nogrids,info); SaveElmergrid(grids,nogrids,eg.filesin[nofile],info); printf("Because file %s didn't exist, it was created for you.\n",eg.filesin[nofile]); Goodbye(); } LoadCommands(eg.filesin[nofile],&eg,grids,2,info); break; case 2: boundaries[nofile] = (struct BoundaryType*) malloc((size_t) (MAXBOUNDARIES)*sizeof(struct BoundaryType)); for(i=0;i nomeshes && outmethod != 1) { nomeshes = nogrids; for(k=0;k 0) { for(j=0;j 0) for(k=0;k 0.01 && elementsredone < 5 ) { grids[k].wantedelems *= pow(1.0*elements3d / data[j].noelements, (2.0/3.0)); elementsredone++; } else elementsredone = 0; } else if(nodes3d) { if( abs(data[j].noknots - nodes3d) / (1.0*nodes3d) > 0.01 && elementsredone < 5 ) { grids[k].wantedelems *= pow(1.0*nodes3d / data[j].noknots, (2.0/3.0)); elementsredone++; } else elementsredone = 0; } if(elementsredone) { nomeshes = 0; for(i=0;i < nogrids;i++) SetElementDivision(&(grids[i]),info); DestroyKnots(&data[j]); DestroyKnots(&data[k]); free(cell[k]); if(info) printf("Iteration %d of elements number targiting %d in 2D\n", elementsredone,grids[k].wantedelems); goto redoelements; } } data[k] = data[j]; boundaries[k] = boundaries[j]; } } } /* If the original mesh was given in polar coordinates make the transformation into cartesian ones */ for(k=0;k 1) { strcpy(prefix,eg.filesout[0]); for(k=0;k= eg.sidemap[3*l] && currenttype <= eg.sidemap[3*l+1]) { boundaries[k][j].types[i] = eg.sidemap[3*l+2]; currenttype = -1; } } } } } } if(info) printf("Renumbering boundary types finished\n"); } if(eg.bulkmappings) { int currenttype; for(l=0;l= eg.bulkmap[3*l] && currenttype <= eg.bulkmap[3*l+1]) { data[k].material[j] = eg.bulkmap[3*l+2]; currenttype = -1; } } } } if(info) printf("Renumbering material indexes finished\n"); } for(k=0;k= eg.pelemmap[3*l] && currenttype <= eg.pelemmap[3*l+1]) { data[k].pelemtypes[j] += 1000000 * eg.pelemmap[3*l+2]; currenttype = -1; } } printf("Creating p-elements finished\n"); } if(eg.belems) { for(l=0;l= eg.belemmap[3*l] && currenttype <= eg.belemmap[3*l+1]) { data[k].pelemtypes[j] += 10000 * eg.belemmap[3*l+2]; currenttype = -1; } } if(info) printf("Creating bubble elements finished\n"); } if(eg.advancedmat) { for(l=0;l 99) { if(info) printf("Advanced elements limited to 9 or 99 (not %d)!\n",eg.advancedelem[7*l+i]); } } for(j=1;j<=data[k].noelements;j++) { if( data[k].material[j] == eg.advancedelem[7*l]) { data[k].pelemtypes[j] = 1 * eg.advancedelem[7*l+1] + 10*eg.advancedelem[7*l+2] + 100*eg.advancedelem[7*l+3] + 1000*eg.advancedelem[7*l+4] + 10000*eg.advancedelem[7*l+5] + 1000000*eg.advancedelem[7*l+6]; } } } if(info) printf("Creating advanced elements finished\n"); } } } /********************************/ printf("\nElmergrid saving data:\n"); switch (outmethod) { case 1: SaveElmergrid(grids,nogrids,eg.filesout[0],info); break; case 2: for(k=0;k 1) SaveElmerInputPartitioned(&data[k],boundaries[k],eg.filesout[k],eg.decimals, eg.partitionhalo,eg.partitionindirect,info); else SaveElmerInput(&data[k],boundaries[k],eg.filesout[k],eg.decimals,info); } break; case 22: for(k=0;k