Path: blob/devel/ElmerGUI/Application/plugins/egconvert.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/* --------------------: egconvert.c :-------------------------- */2627#include <stdio.h>28#include <math.h>29#include <stdarg.h>30#include <stdlib.h>31#include <ctype.h>32#include <string.h>33#include <limits.h>3435#include "egutils.h"36#include "egdef.h"37#include "egtypes.h"38#include "egmesh.h"39#include "egconvert.h"4041#define GETLINE (ioptr=fgets(line,MAXLINESIZE,in))42#define GETLONGLINE (ioptr=fgets(longline,LONGLINESIZE,in))4344static int linenumber;45static char *ioptr;4647static int Getrow(char *line1,FILE *io,int upper)48{49int i,isend;50char line0[MAXLINESIZE],*charend;5152for(i=0;i<MAXLINESIZE;i++)53line0[i] = ' ';5455newline:56charend = fgets(line0,MAXLINESIZE,io);57linenumber += 1;5859isend = (charend == NULL);6061if(isend) return(1);6263if(line0[0] == '#' || line0[0] == '!') goto newline;64if(strstr(line0,"#")) goto newline;6566if(upper) {67for(i=0;i<MAXLINESIZE;i++)68line1[i] = toupper(line0[i]);69}70else {71for(i=0;i<MAXLINESIZE;i++)72line1[i] = line0[i];73}7475return(0);76}7778static int GetrowDouble(char *line1,FILE *io)79{80int i,isend;81char line0[MAXLINESIZE],*charend;8283for(i=0;i<MAXLINESIZE;i++)84line0[i] = ' ';8586newline:87charend = fgets(line0,MAXLINESIZE,io);88linenumber += 1;8990isend = (charend == NULL);9192if(isend) return(1);9394if(line0[0] == '#' || line0[0] == '!') goto newline;95if(strstr(line0,"#")) goto newline;9697for(i=0;i<MAXLINESIZE;i++) {9899/* The Fortran double is not recognized by C string operators */100if( line0[i] == 'd' || line0[i] == 'D' ) {101line1[i] = 'e';102} else {103line1[i] = line0[i];104}105}106107return(0);108}109110111static int Comsolrow(char *line1,FILE *io)112{113int i,isend;114char line0[MAXLINESIZE],*charend;115116for(i=0;i<MAXLINESIZE;i++)117line0[i] = ' ';118119charend = fgets(line0,MAXLINESIZE,io);120linenumber += 1;121122isend = (charend == NULL);123124if(isend) return(1);125126for(i=0;i<MAXLINESIZE;i++) line1[i] = line0[i];127128return(0);129}130131static int LinearNodes(int elemtype)132{133int elemfamily,nonodes;134int fam2nodemap[] = {0, 1, 2, 3, 4, 4, 5, 6, 8 };135136elemfamily = elemtype / 100;137nonodes = fam2nodemap[elemfamily];138139return(nonodes);140}141142143static void FindPointParents(struct FemType *data,struct BoundaryType *bound,144int boundarynodes,int *nodeindx,int *boundindx,int info)145{146int i,j,k,sideelemtype,elemind,*indx;147int boundarytype,minboundary,maxboundary,minnode,maxnode,sideelem,elemtype;148int sideind[MAXNODESD1],elemsides,side,sidenodes,hit,nohits;149int *elemhits;150151if(!boundarynodes) return;152153for(j=0;j < MAXBOUNDARIES;j++)154bound[j].created = FALSE;155for(j=0;j < MAXBOUNDARIES;j++)156bound[j].nosides = 0;157158AllocateBoundary(bound,boundarynodes);159160info = TRUE;161162sideelem = 0;163maxboundary = minboundary = boundindx[1];164minnode = maxnode = nodeindx[1];165166for(i=1;i<=boundarynodes;i++) {167if(maxboundary < boundindx[i]) maxboundary = boundindx[i];168if(minboundary > boundindx[i]) minboundary = boundindx[i];169if(maxnode < nodeindx[i]) maxnode = nodeindx[i];170if(minnode > nodeindx[i]) minnode = nodeindx[i];171}172173if(info) {174printf("Boundary types are in interval [%d, %d]\n",minboundary,maxboundary);175printf("Boundary nodes are in interval [%d, %d]\n",minnode,maxnode);176}177178indx = Ivector(1,data->noknots);179180printf("Allocating hit table of size: %d\n",data->noknots);181elemhits = Ivector(1,data->noknots);182for(i=1;i<=data->noknots;i++) elemhits[i] = 0;183184185for(elemind=1;elemind<=data->noelements;elemind++) {186elemtype = data->elementtypes[elemind];187elemsides = elemtype % 100;188189for(i=0;i<elemsides;i++) {190j = data->topology[elemind][i];191elemhits[j] += 1;192}193}194195for(boundarytype=minboundary;boundarytype <= maxboundary;boundarytype++) {196int boundfirst,bchits,bcsame,sideelemtype2;197int sideind2[MAXNODESD1];198int minhits;199200boundfirst = 0;201202for(i=1;i<=data->noknots;i++)203indx[i] = 0;204205for(i=1;i<=boundarynodes;i++) {206if(boundindx[i] == boundarytype)207indx[nodeindx[i]] = TRUE;208}209210211for(elemind=1;elemind<=data->noelements;elemind++) {212elemtype = data->elementtypes[elemind];213214j = LinearNodes(elemtype);215nohits = 0;216for(i=0;i<j;i++)217if(indx[data->topology[elemind][i]]) nohits++;218if(!nohits) continue;219220if(elemtype > 800 )221minhits = 4;222else if( elemtype > 500 )223minhits = 3;224else if( elemtype > 300 )225minhits = 2;226else227minhits = 1;228229if(nohits < minhits) continue;230231elemsides = elemtype / 100;232if(elemsides == 8) elemsides = 6;233else if(elemsides == 5) elemsides = 4;234else if(elemsides == 6 || elemsides == 7) elemsides = 5;235236if(0) printf("elemtype = %d %d %d %d %d\n",elemind,elemtype,elemsides,nohits,minhits);237238/* Check whether the bc nodes occupy every node in the selected side */239for(side=0;side<elemsides;side++) {240GetElementSide(elemind,side,1,data,&sideind[0],&sideelemtype);241sidenodes = sideelemtype%100;242243if(0) printf("sideelemtype = %d %d %d\n",side,sideelemtype,sidenodes);244245hit = TRUE;246nohits = 0;247for(i=0;i<sidenodes;i++) {248if(sideind[i] <= 0) {249if(0) printf("sideind[%d] = %d\n",i,sideind[i]);250hit = FALSE;251}252else if(sideind[i] > data->noknots) {253if(0) printf("sideind[%d] = %d (noknots=%d)\n",i,sideind[i],data->noknots);254hit = FALSE;255}256else if(!indx[sideind[i]]) {257hit = FALSE;258}259else {260nohits++;261}262}263264if(0) {265printf("******\n");266printf("hits=%d ind=%d type=%d sides=%d\n",nohits,elemind,elemtype,elemsides);267printf("sidenodes=%d side=%d\n",sidenodes,side);268269for(i=0;i<sidenodes;i++)270printf("%d ",sideind[i]);271272printf("\neleminds %d %d\n",elemtype,elemind);273for(i=0;i<elemtype%100;i++)274printf("%d ",data->topology[elemind][i]);275printf("\n");276277hit = TRUE;278}279280if(hit == TRUE) {281/* If all the points belong to more than one element there may be282another parent for the side element */283bcsame = FALSE;284bchits = TRUE;285for(i=0;i<sidenodes;i++)286if(elemhits[sideind[i]] < 2) bchits = FALSE;287288if(bchits && boundfirst) {289for(j=boundfirst;j<=sideelem;j++) {290if(bound->parent2[j]) continue;291GetElementSide(bound->parent[j],bound->side[j],1,data,&sideind2[0],&sideelemtype2);292if(sideelemtype != sideelemtype2) continue;293bcsame = 0;294for(i=0;i<sidenodes;i++)295for(k=0;k<sidenodes;k++)296if(sideind[i] == sideind2[k]) bcsame++;297298if(bcsame == sidenodes) {299if(data->material[bound->parent[j]] > data->material[elemind]) {300bound->parent2[j] = bound->parent[j];301bound->side2[j] = bound->side[j];302bound->parent[j] = elemind;303bound->side[j] = side;304}305else {306bound->parent2[j] = elemind;307bound->side2[j] = side;308}309goto bcset;310}311}312}313314sideelem += 1;315316if( sideelem > bound->nosides ) {317printf("There are more side elements than allocated for (%d vs. %d)\n",sideelem,bound->nosides);318}319bound->parent[sideelem] = elemind;320bound->side[sideelem] = side;321bound->parent2[sideelem] = 0;322bound->side2[sideelem] = 0;323bound->types[sideelem] = boundarytype;324325if(!boundfirst) boundfirst = sideelem;326327bcset:328continue;329}330}331}332}333334free_Ivector(indx,1,data->noknots);335336if(info) printf("Found %d side elements formed by %d points.\n",337sideelem,boundarynodes);338339if(sideelem) {340bound->nosides = MIN( sideelem, bound->nosides );341}342else {343if(info) printf("Adding the points as 101 elements to the mesh instead!\n");344345bound->topology = Imatrix(1,boundarynodes,0,0);346bound->elementtypes =Ivector(1,boundarynodes);347348for(i=1;i<=boundarynodes;i++) {349bound->types[i] = boundindx[i];350bound->elementtypes[i] = 101;351bound->topology[i][0] = nodeindx[i];352}353}354355return;356}357358359static void AbaqusSideInfoToBoundary(struct FemType *data,struct BoundaryType *bound,360int nosides,int *sides,int *parent,int *bctypes,int info)361{362int i,j,k,l,n,noelements,noknots,elemside,elemfamily;363int minelemdim,maxelemdim,elemtype,sideelemtype,minelemtype,maxelemtype;364int sideind2[MAXNODESD2];365int order8[]={4,5,0,1,2,3};366int order7[]={3,4,0,1,2};367int order6[]={4,0,1,2,3};368int order5[]={3,0,1,2};369int order4[]={0,1,2,3};370int order3[]={0,1,2};371int *faceorder;372int zeroparent,zerosides;373374375if(info) printf("Making side info of size %d to boundary elements\n",nosides);376377for(j=0;j < MAXBOUNDARIES;j++)378bound[j].created = FALSE;379for(j=0;j < MAXBOUNDARIES;j++)380bound[j].nosides = 0;381if(!nosides) return;382383noelements = data->noelements;384noknots = data->noknots;385386maxelemtype = GetMaxElementType(data);387if(info) printf("Leading bulk elementtype is %d\n",maxelemtype);388389minelemtype = GetMinElementType(data);390if(info) printf("Trailing bulk elementtype is %d\n",minelemtype);391392if(0) maxelemdim = GetElementDimension(maxelemtype);393if(0) minelemdim = GetElementDimension(minelemtype);394395AllocateBoundary(bound,nosides);396397bound->topology = Imatrix(1,nosides,0,MAXNODESD2-1);398for(i=1;i<=nosides;i++)399for(j=0;j<MAXNODESD2;j++)400bound->topology[i][j] = 0;401402j = 0;403zeroparent = 0;404zerosides = 0;405406for(i=0;i<nosides;i++) {407408if(!sides[i]) continue;409410if(parent[i] <= 0) {411zeroparent++;412continue;413}414415if(sides[i] <= 0) {416zerosides++;417continue;418}419420j += 1;421bound->parent[j] = parent[i];422423elemtype = data->elementtypes[parent[i]];424elemfamily = elemtype / 100;425426if(elemfamily == 8 )427faceorder = &order8[0];428else if(elemfamily == 7 )429faceorder = &order7[0];430else if(elemfamily == 6 )431faceorder = &order6[0];432else if(elemfamily == 5 )433faceorder = &order5[0];434else if(elemfamily == 4 )435faceorder = &order4[0];436else if(elemfamily == 3 )437faceorder = &order3[0];438else {439printf("Face order not implemented for family: %d\n",elemfamily);440j--;441continue;442}443444elemside = faceorder[sides[i]-1];445446bound->side[j] = elemside;447bound->parent2[j] = 0;448bound->side2[j] = 0;449bound->types[j] = bctypes[i];450451GetElementSide(parent[i],elemside,1,data,&sideind2[0],&sideelemtype);452453if(!sideelemtype) {454printf("sideele = %d %d\n",sideelemtype,sideelemtype % 100);455j--;456}457else {458for(k=0;k<sideelemtype % 100;k++)459bound->topology[j][k] = sideind2[k];460}461}462if(zeroparent) printf("Number of zero parents: %d\n",zeroparent);463if(zerosides) printf("Number of zero sides: %d\n",zerosides);464465if(info) printf("Setting side %d elements to be BCs finished!\n",j);466467bound->nosides = j;468469return;470}471472static void InpUntreated(char *cmd)473{474printf("Untreated: %s",cmd);475bigerror("Could not read mesh from Abaqus inp file!");476}477478static void InpIgnored(char *cmd)479{480printf("Ignored: %s",cmd);481}482483static void InpComment(char *cmd)484{485printf("Comment: %s",cmd);486}487488489490491int LoadAbaqusInput(struct FemType *data,struct BoundaryType *bound,492char *prefix,int info)493/* Load the grid from a format that can be read by ABAQUS494program designed for structural mechanics. The commands495understood are only those that IDEAS creates when saving496results in ABAQUS format.497*/498{499int noknots,noelements,elemcode,maxnodes,bodyid,maxelem,nodeoffset;500int mode,allocated,nvalue,nvalue2,maxknot,nosides,elemnodes,ncum;501int boundarytype,boundarynodes,cont,bcind;502int *nodeindx=NULL,*boundindx=NULL,*elemindx=NULL;503char *pstr,*pstr2;504char filename[MAXFILESIZE];505char line[MAXLINESIZE];506int i,j,k,l,*ind=NULL;507FILE *in;508Real rvalues[MAXDOFS];509int *ivalues,ivalues0[MAXDOFS];510int ivaluessize;511int setmaterial;512int debug,firstline,generate;513char entityname[MAXNAMESIZE];514int side,type,newsurface;515int *bcsides,*bctypes,*bcparent;516517strcpy(filename,prefix);518if ((in = fopen(filename,"r")) == NULL) {519AddExtension(prefix,filename,"inp");520if ((in = fopen(filename,"r")) == NULL) {521printf("LoadAbaqusInput: opening of the ABAQUS-file '%s' wasn't successful !\n",522filename);523return(1);524}525}526527printf("Reading input from ABAQUS input file %s.\n",filename);528InitializeKnots(data);529530allocated = FALSE;531maxknot = 0;532maxelem = 0;533ivaluessize = MAXDOFS;534ivalues = Ivector(0,ivaluessize-1);535for(i=0;i<ivaluessize;i++)536ivalues[i] = 0;537538539/* Because the file format doesn't provide the number of elements540or nodes the results are read twice but registered only in the541second time. */542543debug = FALSE;544545omstart:546547mode = 0;548maxnodes = 0;549noknots = 0;550noelements = 0;551nodeoffset = 0;552elemcode = 0;553boundarytype = 0;554boundarynodes = 0;555bodyid = 0;556nosides = 0;557bcind = 0;558ivalues0[0] = ivalues0[1] = 0;559newsurface = 0;560561for(;;) {562/* GETLINE; */563564if (Getrow(line,in,TRUE)) goto end;565566/* if(!line) goto end; */567/* if(strstr(line,"END")) goto end; */568569570if(strrchr(line,'*')) {571/* There result to errors hence no "else" needed! */572if(strstr(line,"NEWSET")) InpUntreated(line);573if(strstr(line,"NGEN")) InpUntreated(line);574if(strstr(line,"NFILL")) InpUntreated(line);575576if( mode == 2 ) {577if(!allocated) printf("Number of nodes so far: %d\n",noknots);578}579else if( mode == 3 ) {580if(!allocated) printf("Number of elements so far: %d\n",noelements);581/* if(elmatactive) {582nodeoffset = noknots;583if(!allocated) printf("Node offset is %d\n",nodeoffset);584} */585}586587if( strstr(line,"**") ) {588if(info && !allocated) InpComment(line);589mode = 0;590}591else if(strstr(line,"HEAD")) {592mode = 1;593}594else if(strstr(line,"*NODE")) {595if( ( pstr = strstr(line,"NODE OUTPUT")) ) {596mode = 10;597}598else {599if(strstr(line,"SYSTEM=R")) data->coordsystem = COORD_CART2;600if(strstr(line,"SYSTEM=C")) data->coordsystem = COORD_AXIS;601if(strstr(line,"SYSTEM=P")) data->coordsystem = COORD_POLAR;602mode = 2;603}604}605else if(strstr(line,"*ELEMENT")) {606if( ( pstr = strstr(line,"ELEMENT OUTPUT")) ) {607mode = 10;608}609else {610if(strstr(line,"S3") || strstr(line,"STRI3") || strstr(line,"M3D3"))611elemcode = 303;612else if(strstr(line,"2D4") || strstr(line,"SP4") || strstr(line,"AX4")613|| strstr(line,"S4") || strstr(line,"CPE4"))614elemcode = 404;615else if(strstr(line,"2D8") || strstr(line,"AX8") || strstr(line,"DS8") )616elemcode = 408;617else if(strstr(line,"3D4"))618elemcode = 504;619else if(strstr(line,"3D10"))620elemcode = 510;621else if(strstr(line,"3D5"))622elemcode = 605;623else if(strstr(line,"3D6"))624elemcode = 706;625else if(strstr(line,"3D15"))626elemcode = 715;627else if(strstr(line,"3D8"))628elemcode = 808;629else if(strstr(line,"3D20"))630elemcode = 820;631else {632printf("Unknown element code: %s\n",line);633bigerror("Cannot continue without all elements!");634}635636elemnodes = elemcode % 100;637maxnodes = MAX( maxnodes, elemnodes);638639640mode = 3;641642if(allocated) {643if(info) printf("Loading elements of type %d starting from element %d to body %d.\n",644elemcode,noelements,bodyid);645}646647if( ( pstr = strstr(line,"ELSET=")) ) {648bodyid++;649if(allocated) {650if(info) printf("Loading elements to body %d from ELSET %s",bodyid,pstr+6);651sscanf(pstr+6,"%s",entityname);652if(!data->bodyname[bodyid]) data->bodyname[bodyid] = Cvector(0,MAXNAMESIZE);653strcpy(data->bodyname[bodyid],entityname);654data->bodynamesexist = TRUE;655data->boundarynamesexist = TRUE;656}657}658659firstline = TRUE;660}661}662else if( strstr(line,"BOUNDARY") ) {663boundarytype++;664mode = 4;665if(allocated && info) printf("Treating keyword BOUNDARY for bc %d\n",boundarytype);666}667else if( strstr(line,"SOLID SECTION") ) {668/* Have this here since solid section may include ELSET */669mode = 10;670}671else if( strstr(line,"MEMBRANE SECTION") ) {672/* Have this here since solid section may include ELSET */673mode = 10;674}675else if( strstr(line,"CLOAD") ) {676boundarytype++;677mode = 4;678if(allocated && info) printf("Treating keyword CLOAD for bc %d\n",boundarytype);679}680else if( (pstr = strstr(line,"NSET=")) ) {681682if( strstr(line,"ELSET=") ) {683/* Skipping association of ELSET to NSET */684mode = 10;685}686else {687boundarytype++;688mode = 5;689if(allocated && info) printf("Treating keyword NSET for bc %d from: %s",boundarytype,pstr+5);690}691}692else if( (pstr = strstr(line,"ELSET=")) ) {693mode = 6;694695generate = FALSE;696if( strstr(pstr,"GENERATE") ) generate = TRUE;697side = 0;698699pstr += 6;700if( strstr( line,"ELSET=_")) {701pstr += 1;702703/* This numbering is true for Abaqus-to-Elmer hexas only! */704if( ( pstr2 = strstr(pstr,"_S1") ) )705side = 1;706else if( ( pstr2 = strstr(pstr,"_S2") ) )707side = 2;708else if( ( pstr2 = strstr(pstr,"_S3") ) )709side = 3;710else if( ( pstr2 = strstr(pstr,"_S4") ) )711side = 4;712else if( ( pstr2 = strstr(pstr,"_S5") ) )713side = 5;714else if( ( pstr2 = strstr(pstr,"_S6") ) )715side = 6;716717if(!side ) printf("Could not determine side!\n");718}719720if( side > 0 ) {721if(1)722newsurface = TRUE;723else724bcind += 1;725pstr2[0] = '\n';726sscanf(pstr,"%s",entityname);727if(allocated) {728if(info) printf("Loading boundary set %d for side %d of %s\n",bcind+newsurface,side,entityname);729k = bcind+newsurface;730if(k>MAXBCS) bigerror("Boundary set larger than MAXBCS!");731if(!data->boundaryname[k]) data->boundaryname[k] = Cvector(0,MAXNAMESIZE);732strcpy(data->boundaryname[k],entityname);733data->boundarynamesexist = TRUE;734}735}736else {737bodyid++;738sscanf(pstr,"%s",entityname);739if(allocated) {740if(info) printf("Loading element to body %d from %s\n",bodyid,entityname);741if(bodyid>MAXBODIES) bigerror("Body set larger than MAXBODIES!");742if(!data->bodyname[bodyid]) data->bodyname[bodyid] = Cvector(0,MAXNAMESIZE);743strcpy(data->bodyname[bodyid],entityname);744data->bodynamesexist = TRUE;745}746}747748}749else if( ( pstr = strstr(line,"SURFACE")) ) {750bcind = bcind + newsurface;751newsurface = FALSE;752mode = 0;753}754else if( ( pstr = strstr(line,"PART, NAME=")) ) {755bodyid += 1;756mode = 6;757generate = FALSE;758759if(allocated) {760if(info) printf("Loading part to body %d from %s",bodyid,pstr+11);761sscanf(pstr+6,"%s",entityname);762if(!data->bodyname[bodyid]) data->bodyname[bodyid] = Cvector(0,MAXNAMESIZE);763strcpy(data->bodyname[bodyid],entityname);764data->bodynamesexist = TRUE;765data->boundarynamesexist = TRUE;766}767}768else if( ( pstr = strstr(line,"HWCOLOR")) ) {769/* unused command */770mode = 0;771}772else {773if(!allocated) InpIgnored(line);774mode = 0;775}776}777778else if(mode) {779switch (mode) {780781case 1:782if(info) printf("Loading Abaqus input file:\n%s",line);783break;784785case 2: /* NODE */786nvalue = StringToReal(line,rvalues,MAXNODESD2+1,',');787788if(nvalue > 4 || nvalue < 2 ) {789printf("line: %s\n",line);790printf("Invalid nvalue = %d\n",nvalue);791}792793i = (int)(rvalues[0]+0.5);794noknots++;795796if(allocated) {797if( debug && (i==1 || i==maxknot) ) {798printf("debug node: %i %d %.3le %.3le %.3le\n",i,noknots,rvalues[1],rvalues[2],rvalues[3]);799}800801i = MAX( i, noknots );802if(i <= 0 || i > maxknot) {803printf("Invalid node index = %d\n",i);804}805else {806ind[i] = noknots;807if(nvalue>=2) data->x[noknots] = rvalues[1];808if(nvalue>=3) data->y[noknots] = rvalues[2];809if(nvalue>=4) data->z[noknots] = rvalues[3];810}811}812else {813if(maxknot < i) maxknot = i;814}815break;816817case 3: /* ELEMENT */818noelements++;819820nvalue = StringToIntegerNoZero(line,ivalues,elemnodes+1,',');821822if(allocated) {823if( debug && firstline ) {824printf("debug elem: %d %d %d %d\n",noelements,ivalues[0],elemcode,bodyid);825printf(" topo:");826for(i=0;i<nvalue-1;i++)827printf(" %d",ivalues[i+1]);828printf("\n");829firstline = FALSE;830}831832elemindx[ivalues[0]] = noelements;833data->elementtypes[noelements] = elemcode;834835data->material[noelements] = bodyid;836for(i=0;i<nvalue-1;i++)837data->topology[noelements][i] = ivalues[i+1];838839if( nodeoffset ) {840for(i=0;i<nvalue-1;i++)841data->topology[noelements][i] += nodeoffset;842}843844}845else {846if( maxelem < ivalues[0] ) maxelem = ivalues[0];847}848849ncum = nvalue-1;850851/* Read 2nd line if needed */852if(ncum < elemnodes ) {853Getrow(line,in,TRUE);854nvalue = StringToIntegerNoZero(line,ivalues,elemnodes-ncum,',');855if(allocated) {856for(i=0;i<nvalue;i++)857data->topology[noelements][ncum+i] = ivalues[i];858}859ncum = ncum + nvalue;860}861862/* Be prepared for 3rd line as well */863if(ncum < elemnodes ) {864Getrow(line,in,TRUE);865nvalue = StringToIntegerNoZero(line,ivalues,elemnodes-ncum,',');866if(allocated) {867for(i=0;i<nvalue;i++)868data->topology[noelements][ncum+i] = ivalues[i];869}870ncum = ncum + nvalue;871}872if(ncum != elemnodes) printf("ncum = %d vs. %d\n",ncum,elemnodes);873874if( allocated ) {875j = FALSE;876for(i=0;i<elemnodes;i++)877if(!data->topology[noelements][i]) j = TRUE;878879if(j) {880printf("zero in this element\n");881printf("element = %d %d\n",noelements,elemnodes);882for(i=0;i<elemnodes;i++)883printf("%d ",data->topology[noelements][i]);884printf("\n");885}886}887888break;889890case 4:891nvalue = StringToInteger(line,ivalues,2,',');892893if(ivalues[0] == ivalues0[0] && ivalues[1] != ivalues0[1]) continue;894ivalues0[0] = ivalues[0];895ivalues0[1] = ivalues[1];896897boundarynodes++;898if(allocated) {899nodeindx[boundarynodes] = ivalues[0];900boundindx[boundarynodes] = boundarytype;901}902break;903904case 5: /* NSET */905nvalue = StringToIntegerNoZero(line,ivalues,ivaluessize,',');906907if(allocated) {908for(i=0;i<nvalue;i++) {909boundarynodes += 1;910nodeindx[boundarynodes] = ivalues[i];911boundindx[boundarynodes] = boundarytype;912if(0) printf("bc: %d % d %d\n",boundarynodes,ivalues[i],boundarytype);913}914}915else916boundarynodes += nvalue;917918break;919920case 6: /* ELSET */921nvalue = StringToIntegerNoZero(line,ivalues,ivaluessize,',');922923if(generate) {924nvalue = (ivalues[1]-ivalues[0])/ivalues[2]+1;925if(0) printf("generate: %d %d %d %d\n",ivalues[0],ivalues[1],ivalues[2],nvalue);926}927928if(allocated) {929if(generate) {930i=0;931for(j=ivalues[0];j<=ivalues[1];j+=ivalues[2]) {932if( side ) {933bcsides[nosides+i] = side;934bctypes[nosides+i] = bcind+newsurface;935bcparent[nosides+i] = elemindx[j];936i++;937}938else {939data->material[elemindx[j]] = bodyid;940}941}942}943else {944for(i=0;i<nvalue;i++) {945if( side ) {946bcsides[nosides+i] = side;947bctypes[nosides+i] = bcind+newsurface;948bcparent[nosides+i] = elemindx[ivalues[i]];949}950else {951j = elemindx[ivalues[i]];952data->material[j] = bodyid;953}954}955}956}957958if(side) nosides += nvalue;959break;960961case 10:962/* Doing nothing */963break;964965966default:967printf("Unknown case: %d\n",mode);968}969}970971}972end:973974if(!allocated) {975976rewind(in);977978data->noknots = noknots;979data->noelements = noelements;980data->maxnodes = maxnodes;981data->dim = 3;982983if(info) printf("Allocating for %d knots and %d %d-node elements.\n",984noknots,noelements,maxnodes);985AllocateKnots(data);986987if(info) printf("Number of boundary nodes: %d\n",boundarynodes);988if( boundarynodes > 0 ) {989nodeindx = Ivector(1,boundarynodes);990boundindx = Ivector(1,boundarynodes);991}992993if(info) printf("Maximum temporal index array size: %d\n",ivaluessize);994free_Ivector(ivalues,0,ivaluessize-1);995996if(info) printf("Maximum element index in file: %d\n",maxelem);997maxelem = MAX( maxelem, noelements );998999elemindx = Ivector(1,maxelem);1000for(i=1;i<=maxelem;i++)1001elemindx[i] = 0;10021003if(info) printf("Maximum node index in file: %d\n",maxknot);1004maxknot = MAX( maxknot, noknots );1005ind = ivector(1,maxknot);1006for(i=1;i<=maxknot;i++)1007ind[i] = 0;10081009if(nosides > 0 ) {1010bcsides = Ivector(0,nosides-1);1011bctypes = Ivector(0,nosides-1);1012bcparent = Ivector(0,nosides-1);1013}10141015allocated = TRUE;1016goto omstart;1017}101810191020if(info) printf("The mesh was loaded from file %s.\n",filename);10211022/* ABAQUS format does not expect that all numbers are used1023when numbering the elements. Therefore the nodes must1024be renumbered from 1 to noknots. */10251026if(noknots != maxknot) {1027int errcount,okcount;1028if(info) printf("There are %d nodes but maximum index is %d.\n",noknots,maxknot);1029if(info) printf("Renumbering %d elements\n",noelements);1030errcount = 0;1031okcount = 0;1032for(j=1;j<=noelements;j++) {1033elemcode = data->elementtypes[j];1034elemnodes = elemcode % 100;1035for(i=0;i < elemnodes;i++) {1036k = data->topology[j][i];1037if(k<=0) {1038printf("err elem ind: %d %d %d %d\n",j,elemcode,i,k);1039errcount++;1040}1041else {1042data->topology[j][i] = ind[k];1043okcount++;1044}1045}1046}1047if(info) printf("There are %d positive and %d non-positive indexes in elements!\n",okcount,errcount);10481049if(info) printf("Renumbering %d nodes in node sets\n",boundarynodes);1050errcount = 0;1051okcount = 0;1052for(j=1;j<=boundarynodes;j++) {1053k = nodeindx[j];1054if(k<=0 || k > maxknot) {1055printf("err node set ind: %d %d\n",j,k);1056errcount++;1057}1058else {1059nodeindx[j] = ind[k];1060okcount++;1061}1062}1063printf("There are %d positive and %d non-positive indexes in node sets!\n",okcount,errcount);1064}106510661067{1068int maxid,mincnt;1069maxid = data->material[1];1070mincnt = 0;1071for(i=1;i<=noelements;i++) {1072maxid = MAX(maxid,data->material[i]);1073if(!data->material[i]) mincnt++;1074}1075if(mincnt) {1076maxid +=1;1077if(info) printf("Setting %d unset elements to body index %d and name 'DefaulBody'\n",mincnt,maxid);1078for(i=1;i<=noelements;i++)1079if(!data->material[i]) data->material[i] = maxid;1080if(!data->bodyname[maxid]) data->bodyname[maxid] = Cvector(0,MAXNAMESIZE);1081strcpy(data->bodyname[maxid],"DefaultBody");1082data->bodynamesexist = TRUE;1083data->boundarynamesexist = TRUE;1084}10851086/* The underscore suggest some special Abaqus commands. Scrap that. */1087for(i=1;i<=maxid;i++) {1088if(data->bodyname[i])1089if( ( pstr = strstr(data->bodyname[i],",") ) ) pstr[0] = '\0';1090}1091}109210931094if(nosides) {1095if(info) printf("Creating boundary elements from side pointers!\n");1096AbaqusSideInfoToBoundary(data,bound,nosides,bcsides,bcparent,bctypes,info);1097}1098else if(boundarynodes) {1099if(info) printf("Creating boundary elements from node set!\n");1100FindPointParents(data,bound,boundarynodes,nodeindx,boundindx,info);1101if(0) ElementsToBoundaryConditions(data,bound,FALSE,info);1102}11031104free_ivector(ind,1,maxknot);1105free_Ivector(elemindx,1,maxelem);11061107if( boundarynodes > 0 ) {1108if(info) printf("Number of nodes in boundary sets: %d\n",boundarynodes);1109/* Temporarily suppress the deallocation while trying to find a bug */1110free_Ivector(nodeindx,1,boundarynodes);1111free_Ivector(boundindx,1,boundarynodes);1112}1113fclose(in);11141115if(info) printf("Finished reading ABAQUS input file\n");111611171118return(0);1119}112011211122static int ReadAbaqusField(FILE *in,char *buffer,int *argtype,int *argno)1123/* This subroutine reads the Abaqus file format and tries to make1124sense out of it.1125*/1126{1127int i,val,digits;1128static int maxargno=0,mode=0;11291130val = fgetc(in);11311132if(val==EOF) return(-1);1133if(val=='\n') val = fgetc(in);11341135if(val=='*') {1136if(0) printf("start field\n");1137if((*argno) != maxargno)1138printf("The previous field was of wrong length, debugging time!\n");1139(*argno) = 0;1140mode = 0;1141val = fgetc(in);1142if(val=='\n') val = fgetc(in);1143}11441145if(val=='I') {1146for(i=0;i<2;i++) {1147val = fgetc(in);1148if(val=='\n') val = fgetc(in);1149buffer[i] = val;1150}1151buffer[2] = '\0';1152digits = atoi(buffer);1153for(i=0;i<digits;i++) {1154val = fgetc(in);1155if(val=='\n') val = fgetc(in);1156buffer[i] = val;1157}1158buffer[digits] = '\0';1159(*argno)++;1160(*argtype) = 1;1161if((*argno) == 1) maxargno = atoi(buffer);1162if((*argno) == 2) mode = atoi(buffer);1163}1164else if(val=='D') {1165for(i=0;i<22;i++) {1166val = fgetc(in);1167if(val=='\n') val = fgetc(in);1168if(val=='D') val = 'E';1169buffer[i] = val;1170}1171buffer[22] = '\0';1172(*argno)++;1173(*argtype) = 2;1174}1175else if(val=='A') {1176for(i=0;i<8;i++) {1177val = fgetc(in);1178if(val=='\n') val = fgetc(in);1179buffer[i] = val;1180}1181buffer[8] = '\0';1182(*argno)++;1183(*argtype) = 3;1184}1185else {1186buffer[0] = val;1187buffer[1] = '\0';1188(*argtype) = 0;1189}1190return(mode);1191}1192119311941195int LoadAbaqusOutput(struct FemType *data,char *prefix,int info)1196/* Load the grid from a format that can be read by ABAQUS1197program designed for structural mechanics.1198*/1199{1200int knotno,elemno,elset,secno;1201int argtype,argno;1202int mode,allocated;1203char filename[MAXFILESIZE];1204char buffer[MAXLINESIZE];1205int i,j,prevdog,nodogs;1206int ignored;1207FILE *in=NULL;1208int *indx=NULL;120912101211AddExtension(prefix,filename,"fil");12121213if ((in = fopen(filename,"r")) == NULL) {1214printf("LoadAbaqusOutput: opening of the Abaqus-file '%s' wasn't successful !\n",1215filename);1216return(1);1217}1218if(info) printf("Reading input from ABAQUS output file %s.\n",filename);1219InitializeKnots(data);12201221allocated = FALSE;1222mode = 0;1223knotno = 0;1224elemno = 0;1225nodogs = 0;1226prevdog = 0;1227argno = 0;1228elset = 0;1229secno = 0;1230ignored = 0;1231data->maxnodes = 9;1232data->dim = 3;12331234for(;;) {12351236mode = ReadAbaqusField(in,buffer,&argtype,&argno);1237if(0) printf("%d %d: buffer: %s\n",argtype,argno,buffer);12381239switch (mode) {12401241case -1:1242goto jump;12431244case 0:1245break;12461247case 1921:1248/* General info */1249if(argno == 3) printf("Reading output file for Abaqus %s\n",buffer);1250else if(argno == 4) printf("Created on %s",buffer);1251else if(argno == 5) printf("%s",buffer);1252else if(argno == 6) printf("%s\n",buffer);1253else if(argno == 7) data->noelements = atoi(buffer);1254else if(argno == 8 && allocated == FALSE) {1255data->noknots = atoi(buffer);1256allocated = TRUE;1257AllocateKnots(data);1258indx = Ivector(0,2 * data->noknots);1259for(i=1;i<=2*data->noknots;i++)1260indx[i] = 0;1261}1262break;12631264case 1900:1265/* Element definition */1266if(argno == 3) elemno = atoi(buffer);1267else if(argno == 4) {1268if(strstr(buffer,"2D4") || strstr(buffer,"SP4") || strstr(buffer,"AX4"))1269data->elementtypes[elemno] = 404;1270else if(strstr(buffer,"2D8") || strstr(buffer,"AX8") || strstr(buffer,"S8R5"))1271data->elementtypes[elemno] = 408;1272else if(strstr(buffer,"3D8"))1273data->elementtypes[elemno] = 808;1274else printf("Unknown element code: %s\n",buffer);1275}1276else if(argno >= 5)1277data->topology[elemno][argno-5] = atoi(buffer);1278break;12791280case 1901:1281/* Node definition */1282if(argno == 3) {1283knotno++;1284if(atoi(buffer) > 2*data->noknots)1285printf("LoadAbaqusOutput: allocate more space for indx.\n");1286else1287indx[atoi(buffer)] = knotno;1288}1289if(argno == 4) sscanf(buffer,"%le",&(data->x[knotno]));1290if(argno == 5) sscanf(buffer,"%le",&(data->y[knotno]));1291if(argno == 6) sscanf(buffer,"%le",&(data->z[knotno]));1292break;12931294case 1933:1295/* Element set */1296if(argno == 3) {1297elset++;1298if(!data->bodyname[elset]) data->bodyname[elset] = Cvector(0,MAXNAMESIZE);1299strcpy(data->bodyname[elset],buffer);1300}1301case 1934:1302/* Element set continuation */1303if(argno > 3) {1304elemno = atoi(buffer);1305data->material[elemno] = elset;1306}1307break;13081309case 2001:1310/* Just ignore */1311break;13121313case 1:1314if(argno == 3) knotno = indx[atoi(buffer)];1315if(argno == 5) secno = atoi(buffer);1316break;13171318case 2:1319if(prevdog != mode) {1320prevdog = mode;1321nodogs++;1322CreateVariable(data,nodogs,1,0.0,"Temperature",FALSE);1323}1324break;13251326/* Read vectors in nodes in elements */1327case 11:1328if(prevdog != mode) {1329prevdog = mode;1330nodogs++;1331CreateVariable(data,nodogs,3,0.0,"Stress",FALSE);1332}1333case 12:1334if(prevdog != mode) {1335prevdog = mode;1336nodogs++;1337CreateVariable(data,nodogs,3,0.0,"Invariants",FALSE);1338}1339if(secno==1 && argno == 3) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno-2]));1340if(secno==1 && argno == 4) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno-1]));1341if(secno==1 && argno == 5) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno]));1342break;13431344/* Read vectors in nodes. */1345case 101:1346if(prevdog != mode) {1347prevdog = mode;1348nodogs++;1349CreateVariable(data,nodogs,3,0.0,"Displacement",FALSE);1350}1351case 102:1352if(prevdog != mode) {1353prevdog = mode;1354nodogs++;1355CreateVariable(data,nodogs,3,0.0,"Velocity",FALSE);1356}1357if(argno == 3) knotno = indx[atoi(buffer)];1358if(argno == 4) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno-2]));1359if(argno == 5) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno-1]));1360if(argno == 6) sscanf(buffer,"%le",&(data->dofs[nodogs][3*knotno]));1361break;13621363default:1364if(ignored != mode) {1365printf("Record %d was ignored!\n",mode);1366ignored = mode;1367}1368break;1369}1370}13711372jump:13731374if(info) printf("Renumbering elements\n");1375for(j=1;j<=data->noelements;j++)1376for(i=0;i < data->elementtypes[j]%100;i++)1377data->topology[j][i] = indx[data->topology[j][i]];13781379free_ivector(indx,0,2*data->noknots);13801381fclose(in);13821383if(info) printf("LoadAbacusInput: results were loaded from file %s.\n",filename);13841385return(0);1386}13871388138913901391int LoadNastranInput(struct FemType *data,struct BoundaryType *bound,1392char *prefix,int info)1393/* Load the grid from a format that in Nastran format1394*/1395{1396int noknots,noelements,maxnodes;1397int allocated,maxknot,minknot,nodes;1398char filename[MAXFILESIZE];1399char line[MAXLINESIZE],*cp;1400int j,k;1401FILE *in;140214031404strcpy(filename,prefix);1405if ((in = fopen(filename,"r")) == NULL) {1406AddExtension(prefix,filename,"nas");1407if ((in = fopen(filename,"r")) == NULL) {1408printf("LoadNastranInput: opening of the Nastran file '%s' wasn't successful !\n",1409filename);1410return(1);1411}1412}14131414if(info) printf("Reading mesh from Nastran file %s.\n",filename);1415InitializeKnots(data);14161417allocated = FALSE;1418maxknot = 0;1419minknot = 10000;14201421/* Because the file format doesn't provide the number of elements1422or nodes the results are read twice but registered only in the1423second time. */1424omstart:14251426maxnodes = 0;1427noknots = 0;1428noelements = 0;14291430for(;;) {1431/* GETLINE; */14321433if (Getrow(line,in,TRUE)) goto end;14341435if(line[0] == '$') {1436if(!allocated) InpComment(line);1437}1438else if(strstr(line,"GRID")) {1439noknots++;1440if(0) printf("line=%s\n",line);1441cp = &line[5];1442j = next_int(&cp);1443if(0) printf("j=%d\n",j);14441445if(allocated) {1446k = next_int(&cp);1447data->x[noknots] = next_real(&cp);1448data->y[noknots] = next_real(&cp);1449}1450else {1451if(j > maxknot) maxknot = j;1452if(j < minknot) minknot = j;1453}14541455if(strstr(line,"*"))1456Getrow(line,in,TRUE);14571458if(allocated) {1459cp = &line[4];1460data->z[noknots] = next_real(&cp);1461}14621463}1464else if(strstr(line,"TETRA")) {1465noelements++;1466nodes = 4;1467if(nodes > maxnodes) maxnodes = nodes;1468if(allocated) {1469data->elementtypes[noelements] = 504;1470cp = &line[6];1471k = next_int(&cp);1472data->material[noelements] = next_int(&cp) + 1;1473for(j=0;j<nodes;j++)1474data->topology[noelements][j] = next_int(&cp);1475}1476}1477else if(strstr(line,"PYRAM")) {1478noelements++;1479nodes = 5;1480if(nodes > maxnodes) maxnodes = nodes;1481if(allocated) {1482data->elementtypes[noelements] = 605;1483cp = &line[6];1484k = next_int(&cp);1485data->material[noelements] = next_int(&cp) + 1;1486for(j=0;j<nodes;j++)1487data->topology[noelements][j] = next_int(&cp);1488}1489}1490else if(strstr(line,"PENTA")) {1491noelements++;1492nodes = 6;1493if(nodes > maxnodes) maxnodes = nodes;1494if(allocated) {1495data->elementtypes[noelements] = 706;1496cp = &line[6];1497k = next_int(&cp);1498data->material[noelements] = next_int(&cp) + 1;1499for(j=0;j<nodes;j++)1500data->topology[noelements][j] = next_int(&cp);1501}1502}1503else if(strstr(line,"CHEXA")) {1504noelements++;1505nodes = 8;1506if(nodes > maxnodes) maxnodes = nodes;1507if(allocated) {1508data->elementtypes[noelements] = 808;1509cp = &line[5];1510k = next_int(&cp);1511data->material[noelements] = next_int(&cp) + 1;1512for(j=0;j<6;j++)1513data->topology[noelements][j] = next_int(&cp);1514}1515Getrow(line,in,TRUE);1516if(allocated) {1517cp = &line[1];1518for(j=6;j<8;j++)1519data->topology[noelements][j] = k;1520}1521}1522else if(strstr(line,"ENDDAT")) {1523goto end;1524}1525else {1526if(!allocated) InpIgnored(line);1527}1528}15291530end:15311532if(allocated == TRUE) {1533if(info) printf("The mesh was loaded from file %s.\n",filename);1534fclose(in);1535return(0);1536}15371538rewind(in);1539data->noknots = noknots;1540data->noelements = noelements;1541data->maxnodes = maxnodes;1542data->dim = 3;15431544printf("maxknot = %d minknot = %d\n",maxknot,minknot);15451546if(info) printf("Allocating for %d knots and %d %d-node elements.\n",1547noknots,noelements,maxnodes);1548AllocateKnots(data);15491550allocated = TRUE;1551goto omstart;1552}15531554155515561557static void ReorderFidapNodes(struct FemType *data,int element,int nodes,int typeflag)1558{1559int i,oldtopology[MAXNODESD2],*topology,dim;1560int order808[]={1,2,4,3,5,6,8,7};1561int order408[]={1,3,5,7,2,4,6,8};1562int order306[]={1,3,5,2,4,6};1563int order203[]={1,3,2};1564int order605[]={1,2,4,3,5};15651566dim = data->dim;1567if(typeflag > 10) dim -= 1;15681569data->elementtypes[element] = 101*nodes;1570topology = data->topology[element];15711572if(dim == 1) {1573if(nodes == 3) {1574data->elementtypes[element] = 203;1575for(i=0;i<nodes;i++)1576oldtopology[i] = topology[i];1577for(i=0;i<nodes;i++)1578topology[i] = oldtopology[order203[i]-1];1579}1580}1581else if(dim == 2) {1582if(nodes == 6) {1583data->elementtypes[element] = 306;1584for(i=0;i<nodes;i++)1585oldtopology[i] = topology[i];1586for(i=0;i<nodes;i++)1587topology[i] = oldtopology[order306[i]-1];1588}1589else if(nodes == 8) {1590data->elementtypes[element] = 408;1591for(i=0;i<nodes;i++)1592oldtopology[i] = topology[i];1593for(i=0;i<nodes;i++)1594topology[i] = oldtopology[order408[i]-1];1595}1596}1597else if(dim == 3) {1598if(nodes == 4) {1599data->elementtypes[element] = 504;1600}1601else if(nodes == 5) {1602data->elementtypes[element] = 605;1603for(i=0;i<nodes;i++)1604oldtopology[i] = topology[i];1605for(i=0;i<nodes;i++)1606topology[i] = oldtopology[order605[i]-1];1607}1608else if(nodes == 6) {1609data->elementtypes[element] = 706;1610}1611else if(nodes == 8) {1612for(i=0;i<nodes;i++)1613oldtopology[i] = topology[i];1614for(i=0;i<nodes;i++)1615topology[i] = oldtopology[order808[i]-1];1616}1617else {1618printf("Unknown Fidap elementtype with %d nodes.\n",nodes);1619}16201621}1622else printf("ReorderFidapNodes: unknown dimension (%d)\n",data->dim);1623}16241625162616271628int LoadFidapInput(struct FemType *data,struct BoundaryType *boundaries,char *prefix,int info)1629/* Load the grid from a format that can be read by FIDAP1630program designed for fluid mechanics.16311632Still under implementation1633*/1634{1635int noknots,noelements,dim,novel,maxnodes;1636int mode,maxknot,totelems,entity,maxentity;1637char filename[MAXFILESIZE];1638char line[MAXLINESIZE],entityname[MAXNAMESIZE];1639int i,j,k,*ind,geoflag,typeflag;1640int **topology;1641FILE *in;1642Real *vel,*temp;1643int nogroups,knotno;1644char *isio;16451646AddExtension(prefix,filename,"fidap");16471648if ((in = fopen(filename,"r")) == NULL) {1649AddExtension(prefix,filename,"FDNEUT");1650if ((in = fopen(filename,"r")) == NULL) {1651printf("LoadFidapInput: opening of the Fidap-file '%s' wasn't successful !\n",1652filename);1653return(1);1654}1655}16561657InitializeKnots(data);16581659entity = 0;1660mode = 0;1661noknots = 0;1662noelements = 0;1663dim = 0;1664maxnodes = 4;1665totelems = 0;1666maxentity = 0;16671668for(;;) {1669isio = GETLINE;16701671if(!isio) goto end;1672if(strstr(line,"END")) goto end;16731674/* Control information */1675if(strstr(line,"FIDAP NEUTRAL FILE")) mode = 1;1676else if(strstr(line,"NO. OF NODES")) mode = 2;1677else if(strstr(line,"TEMPERATURE/SPECIES FLAGS")) mode = 3;1678else if(strstr(line,"PRESSURE FLAGS")) mode = 4;1679else if(strstr(line,"NODAL COORDINATES")) mode = 5;1680else if(strstr(line,"BOUNDARY CONDITIONS")) mode = 6;1681else if(strstr(line,"ELEMENT GROUPS")) mode = 7;1682else if(strstr(line,"GROUP:")) mode = 8;1683else if(strstr(line,"VELOCITY")) mode = 10;1684else if(strstr(line,"TEMPERATURE")) mode = 11;1685else if(0) printf("unknown: %s",line);16861687switch (mode) {16881689case 1:1690if(info) printf("Loading FIDAP input file %s\n",filename);1691GETLINE;1692if(info) printf("Name of the case: %s",line);1693mode = 0;1694break;16951696case 2:1697GETLINE;1698if(0) printf("reading the header info\n");1699sscanf(line,"%d%d%d%d%d",&noknots,&noelements,1700&nogroups,&dim,&novel);1701data->noknots = noknots;1702data->noelements = noelements;1703data->maxnodes = maxnodes;1704data->dim = dim;17051706mode = 0;1707break;17081709case 5:1710if(info) printf("Allocating for %d knots and %d %d-node elements.\n",1711noknots,noelements,maxnodes);1712AllocateKnots(data);1713if(info) printf("Reading the nodes\n");1714for(i=1;i<=noknots;i++) {1715GETLINE;1716if (dim == 2)1717sscanf(line,"%d%le%le",&knotno,1718&(data->x[i]),&(data->y[i]));1719else if(dim==3)1720sscanf(line,"%d%le%le%le",&knotno,1721&(data->x[i]),&(data->y[i]),&(data->z[i]));1722}1723break;17241725case 8:1726{1727int val,group,elems,nodes;1728char *cp;17291730i=0;1731do val=line[i++];1732while(val!=':');i++;1733sscanf(&line[i],"%d",&group);17341735do val=line[i++];1736while(val!=':');i++;1737sscanf(&line[i],"%d",&elems);17381739do val=line[i++];1740while(val!=':');i++;1741sscanf(&line[i],"%d",&nodes);17421743do val=line[i++];1744while(val!=':');i++;1745sscanf(&line[i],"%d",&geoflag);17461747do val=line[i++];1748while(val!=':');i++;1749sscanf(&line[i],"%d",&typeflag);17501751GETLINE;1752i=0;1753do val=line[i++];1754while(val!=':');i++;1755sscanf(&line[i],"%s",entityname);17561757if(nodes > maxnodes) {1758if(info) printf("Allocating a %d-node topology matrix\n",nodes);1759topology = Imatrix(1,noelements,0,nodes-1);1760if(totelems > 0) {1761for(j=1;j<=totelems;j++)1762for(i=0;i<data->elementtypes[j] % 100;i++)1763topology[j][i] = data->topology[j][i];1764}1765free_Imatrix(data->topology,1,data->noelements,0,data->maxnodes-1);1766data->maxnodes = maxnodes = nodes;1767data->topology = topology;1768}17691770if(info) printf("reading %d element topologies with %d nodes for %s\n",1771elems,nodes,entityname);17721773for(entity=1;entity<=maxentity;entity++) {1774if(!data->bodyname[entity]) break;1775k = strcmp(entityname,data->bodyname[entity]);1776if(k == 0) break;1777}17781779if(entity > maxentity) {1780maxentity++;1781if(!data->bodyname[entity]) data->bodyname[entity] = Cvector(0,MAXNAMESIZE);1782strcpy(data->bodyname[entity],entityname);1783if(info) printf("Found new entity: %s\n",entityname);1784}17851786for(i=totelems+1;i<=totelems+elems;i++) {1787GETLINE;17881789cp = line;1790j = next_int(&cp);1791for(j=0;j<nodes;j++)1792data->topology[i][j] = next_int(&cp);17931794ReorderFidapNodes(data,i,nodes,typeflag);17951796if(data->elementtypes[i] == 0) {1797printf("Elementtype is zero!\n");1798}17991800if(entity) data->material[i] = entity;1801else data->material[i] = group;1802}1803totelems += elems;1804}1805mode = 0;1806break;18071808case 10:1809dim = 3;1810if(info) printf("Reading the velocity field\n");1811CreateVariable(data,2,dim,0.0,"Velocity",FALSE);1812vel = data->dofs[2];1813for(j=1;j<=noknots;j++) {1814GETLINE;1815if(dim==2)1816sscanf(line,"%le%le",&(vel[2*j-1]),&(vel[2*j]));1817if(dim==3)1818sscanf(line,"%le%le%le",&(vel[3*j-2]),&(vel[3*j-1]),&(vel[3*j]));1819}1820mode = 0;1821break;18221823case 11:1824if(info) printf("Reading the temperature field\n");1825CreateVariable(data,1,1,0.0,"Temperature",FALSE);1826temp = data->dofs[1];1827for(j=1;j<=noknots;j++) {1828GETLINE;1829sscanf(line,"%le",&(temp[j]));1830}1831mode = 0;1832break;18331834default:1835break;1836}1837}18381839end:18401841/* Renumber the nodes */1842maxknot = 0;1843for(i=1;i<=noelements;i++)1844for(j=0;j < data->elementtypes[i]%100;j++)1845if(data->topology[i][j] > maxknot) maxknot = data->topology[i][j];18461847if(maxknot > noknots) {1848if(info) printf("Renumbering the nodes from 1 to %d\n",noknots);18491850ind = ivector(1,maxknot);1851for(i=1;i<=maxknot;i++)1852ind[i] = 0;18531854for(i=1;i<=noelements;i++)1855for(j=0;j < data->elementtypes[i]%100;j++)1856ind[data->topology[i][j]] = data->topology[i][j];1857i=0;1858for(j=1;j<=noknots;j++) {1859i++;1860while(ind[i]==0) i++;1861ind[i] = j;1862}1863for(i=1;i<=noelements;i++)1864for(j=0;j < data->elementtypes[i]%100;j++)1865data->topology[i][j] = ind[data->topology[i][j]];1866}186718681869if(maxentity > 0) data->bodynamesexist = TRUE;18701871fclose(in);18721873if(info) printf("Finished reading the Fidap neutral file\n");18741875ElementsToBoundaryConditions(data,boundaries,FALSE,TRUE);1876/* RenumberBoundaryTypes(data,boundaries,TRUE,0,info); */18771878return(0);1879}1880188118821883static void ReorderAnsysNodes(struct FemType *data,int *oldtopology,1884int element,int dim,int nodes)1885{1886int i,*topology,elementtype;1887int order820[]={1,2,3,4,5,6,7,8,9,10,11,12,17,18,19,20,13,14,15,16};1888int order504[]={1,2,3,5};1889int order306[]={1,2,3,5,6,8};1890int order510[]={1,2,3,5,9,10,12,17,18,19};1891int order613[]={1,2,3,4,5,9,10,11,12,17,18,19,20};1892int order706[]={1,2,3,5,6,7};1893int order715[]={1,2,3,5,6,7,9,10,12,17,18,19,13,14,16};18941895elementtype = 0;1896if(dim == 3) {1897if(nodes == 20) {1898if(oldtopology[2] == oldtopology[3] &&1899oldtopology[4] == oldtopology[5]) elementtype = 510;1900else if(oldtopology[2] == oldtopology[3] &&1901oldtopology[4] != oldtopology[5]) elementtype = 715;1902else if(oldtopology[4] == oldtopology[5]) elementtype = 613;1903else elementtype = 820;1904}1905if(nodes == 8) {1906if(oldtopology[2] == oldtopology[3] &&1907oldtopology[4] == oldtopology[7] &&1908oldtopology[5] == oldtopology[7] &&1909oldtopology[6] == oldtopology[7]) elementtype = 504;1910else if(oldtopology[2] == oldtopology[3] &&1911oldtopology[6] == oldtopology[7]) elementtype = 706;1912else if(oldtopology[4] == oldtopology[5]) elementtype = 605;1913else elementtype = 808;1914}1915if(nodes == 4) elementtype = 504;1916if(nodes == 10) elementtype = 510;1917}1918else if(dim == 2) {1919if(nodes == 9) elementtype = 408;1920if(nodes == 8) {1921if(oldtopology[3] == oldtopology[6])1922elementtype = 306;1923else1924elementtype = 408;1925}1926if(nodes == 4) elementtype = 404;1927if(nodes == 10) elementtype = 310;1928if(nodes == 6) elementtype = 306;1929if(nodes == 3) elementtype = 303;1930}1931else if(dim == 1) {1932if(nodes == 4) elementtype = 204;1933if(nodes == 3) elementtype = 203;1934if(nodes == 2) elementtype = 202;1935}19361937if(!elementtype) {1938printf("Unknown elementtype in element %d (%d nodes, %d dim).\n",1939element,nodes,dim);1940}19411942data->elementtypes[element] = elementtype;1943topology = data->topology[element];19441945switch (elementtype) {19461947case 820:1948for(i=0;i<elementtype%100;i++)1949topology[i] = oldtopology[order820[i]-1];1950break;19511952case 504:1953if(nodes == 4)1954for(i=0;i<elementtype%100;i++)1955topology[i] = oldtopology[i];1956else1957for(i=0;i<elementtype%100;i++)1958topology[i] = oldtopology[order504[i]-1];1959break;196019611962case 510:1963for(i=0;i<elementtype%100;i++) {1964if(oldtopology[2] == oldtopology[3])1965topology[i] = oldtopology[order510[i]-1];1966else1967topology[i] = oldtopology[i];1968}1969break;19701971case 605:1972for(i=0;i<elementtype%100;i++) {1973topology[i] = oldtopology[i];1974}1975break;19761977case 613:1978for(i=0;i<elementtype%100;i++) {1979if(oldtopology[4] == oldtopology[5])1980topology[i] = oldtopology[order613[i]-1];1981else1982topology[i] = oldtopology[i];1983}1984break;19851986case 306:1987for(i=0;i<elementtype%100;i++) {1988if(oldtopology[3] == oldtopology[6])1989topology[i] = oldtopology[order306[i]-1];1990else1991topology[i] = oldtopology[i];1992}1993break;19941995case 706:1996for(i=0;i<elementtype%100;i++) {1997topology[i] = oldtopology[order706[i]-1];1998}1999break;20002001case 715:2002for(i=0;i<elementtype%100;i++) {2003topology[i] = oldtopology[order715[i]-1];2004}2005break;20062007default:2008for(i=0;i<elementtype%100;i++)2009topology[i] = oldtopology[i];20102011}2012}201320142015int LoadAnsysInput(struct FemType *data,struct BoundaryType *bound,2016char *prefix,int info)2017/* This procedure reads the FEM mesh as written by Ansys. */2018{2019int noknots=0,noelements=0,nosides,sidetype,currenttype;2020int maxindx,*indx,*revindx,topology[100],ind;2021int i,j,k,l,imax,*nodeindx,*boundindx,boundarynodes=0;2022int noansystypes,*ansysdim,*ansysnodes,*ansystypes,boundarytypes=0;2023int namesexist,maxside,sides;2024Real x,y,z;2025FILE *in;2026char *cp,line[MAXLINESIZE],filename[MAXFILESIZE],2027text[MAXNAMESIZE],text2[MAXNAMESIZE];202820292030/* ExportMesh.header */20312032sprintf(filename,"%s.header",prefix);2033if ((in = fopen(filename,"r")) == NULL) {2034printf("LoadAnsysInput: The opening of the header-file %s failed!\n",2035filename);2036return(1);2037}20382039if(info) printf("Calculating Ansys elementtypes from %s\n",filename);2040for(i=0;GETLINE;i++);20412042noansystypes = i-1;2043printf("There seems to be %d element types in file %s.\n",noansystypes,filename);20442045ansysdim = Ivector(1,noansystypes);2046ansysnodes = Ivector(1,noansystypes);2047ansystypes = Ivector(1,noansystypes);20482049rewind(in);2050for(i=0;i<=noansystypes;i++) {2051Real dummy1,dummy2,dummy3;2052GETLINE;20532054/* Ansys writes decimal points also for integers and therefore these2055values are read in as real numbers. */20562057sscanf(line,"%le %le %le",&dummy1,&dummy2,&dummy3);20582059if(i==0) {2060noelements = (int) (dummy1+0.5);2061noknots = (int) (dummy2+0.5);2062boundarytypes = (int) (dummy3+0.5);2063}2064else {2065ansysdim[i] = (int) (dummy1+0.5);2066ansysnodes[i] = (int) (dummy2+0.5);2067ansystypes[i] = (int) (dummy3+0.5);2068}2069}2070fclose(in);20712072printf("Ansys file has %d elements, %d nodes and %d boundary types.\n",2073noelements,noknots,boundarytypes);20742075/* ExportMesh.names */20762077sprintf(filename,"%s.names",prefix);2078in = fopen(filename,"r");2079if(in == NULL)2080namesexist = FALSE;2081else2082namesexist = TRUE;20832084if(namesexist) printf("Using names of bodies and boundaries\n");208520862087/* ExportMesh.node */20882089sprintf(filename,"%s.node",prefix);2090if ((in = fopen(filename,"r")) == NULL) {2091printf("LoadAnsysInput: The opening of the nodes-file %s failed!\n",2092filename);2093return(2);2094}20952096if(info) printf("Calculating Ansys nodes from %s\n",filename);2097for(i=0;GETLINE;i++);20982099if(info) printf("There seems to be %d nodes in file %s.\n",i,filename);2100if(i != noknots) printf("Conflicting number of nodes %d vs %d!\n",i,noknots);21012102/* Make room and initialize the mesh */2103InitializeKnots(data);21042105/* Even 2D elements may form a 3D object! */2106data->dim = 3;2107data->maxnodes = 1;21082109for(i=1;i<=noansystypes;i++) {2110if(ansysdim[i] > data->dim) data->dim = ansysdim[i];2111if(ansysnodes[i] > data->maxnodes) data->maxnodes = ansysnodes[i];2112}2113if(data->maxnodes < 8) data->maxnodes = 8;21142115data->noknots = noknots;2116data->noelements = noelements;21172118if(info) printf("Allocating for %d nodes and %d elements with max. %d nodes in %d-dim.\n",2119noknots,noelements,data->maxnodes,data->dim);2120AllocateKnots(data);21212122indx = Ivector(1,noknots);2123for(i=1;i<=noknots;i++) indx[i] = 0;21242125if(info) printf("Loading %d Ansys nodes from %s\n",noknots,filename);2126rewind(in);2127for(i=1;i<=noknots;i++) {2128GETLINE; cp=line;21292130indx[i] = next_int(&cp);2131if(cp[0] == '.') cp++;21322133x = next_real(&cp);2134if(!cp) x = y = z = 0.0;2135else {2136y = next_real(&cp);2137if(!cp) y = z = 0.0;2138else if(data->dim == 3) {2139z = next_real(&cp);2140if(!cp) z = 0.0;2141}2142}2143data->x[i] = x;2144data->y[i] = y;2145if(data->dim == 3) data->z[i] = z;2146}2147fclose(in);21482149/* reorder the indexes */2150maxindx = indx[1];2151for(i=1;i<=noknots;i++)2152if(indx[i] > maxindx) maxindx = indx[i];2153revindx = Ivector(0,maxindx);21542155if(maxindx > noknots) {2156printf("There are %d nodes with indexes up to %d.\n",2157noknots,maxindx);2158for(i=1;i<=maxindx;i++)2159revindx[i] = 0;2160for(i=1;i<=noknots;i++)2161revindx[indx[i]] = i;2162}2163else {2164for(i=1;i<=noknots;i++)2165revindx[i] = i;2166}21672168/* ExportMesh.elem */21692170sprintf(filename,"%s.elem",prefix);2171if ((in = fopen(filename,"r")) == NULL) {2172printf("LoadAnsysInput: The opening of the element-file %s failed!\n",2173filename);2174return(4);2175}21762177if(info) printf("Loading %d Ansys elements from %s\n",noelements,filename);21782179for(j=1;j<=noelements;j++) {21802181GETLINE;2182cp=line;21832184for(i=0;i<8;i++) {2185if (noknots < 1000000) {2186ind = next_int(&cp);2187}2188else if (noknots < 100000000) {2189ind = next_int_n(&cp,8);2190}2191else {2192ind = next_int_n(&cp,10);2193}2194if(cp[0] == '.') cp++;2195topology[i] = revindx[ind];2196}21972198data->material[j] = next_int(&cp);2199currenttype = next_int(&cp);22002201for(k=1;k<=noansystypes;k++)2202if(ansystypes[k] == currenttype) break;2203if(ansystypes[k] != currenttype) k=1;22042205if(ansysnodes[k] > 8) {2206GETLINE;2207cp=line;22082209if(ansysnodes[k] == 10 && topology[2] != topology[3])2210imax = 10;2211else2212imax = 20;22132214for(i=8;i<imax;i++) {2215if (noknots < 1000000) {2216ind = next_int(&cp);2217}2218else if (noknots < 100000000) {2219ind = next_int_n(&cp,8);2220}2221else {2222ind = next_int_n(&cp,10);2223}2224if(cp[0] == '.') cp++;2225topology[i] = revindx[ind];2226}2227}22282229ReorderAnsysNodes(data,&topology[0],j,ansysdim[k],ansysnodes[k]);2230}2231fclose(in);223222332234/* ExportMesh.boundary */22352236sprintf(filename,"%s.boundary",prefix);2237printf("Calculating nodes in file %s\n",filename);2238if ((in = fopen(filename,"r")) == NULL) {2239printf("LoadAnsysInput: The opening of the boundary-file %s failed!\n",2240filename);2241return(5);2242}22432244j = 0;2245for(i=0;GETLINE;i++)2246if(!strstr(line,"Boundary")) j++;22472248boundarynodes = j;2249nosides = 6*boundarynodes;22502251if(info) printf("There are %d boundary nodes, allocating %d elements\n",2252boundarynodes,nosides);2253AllocateBoundary(bound,nosides);2254nodeindx = Ivector(1,boundarynodes);2255boundindx = Ivector(1,boundarynodes);22562257if(info) printf("Loading Ansys boundary from %s\n",filename);22582259for(i=1;i<=boundarynodes;i++) nodeindx[i] = boundindx[i] = 0;22602261rewind(in);2262maxside = 0;2263j = 0;2264for(i=0;GETLINE;i++) {2265if(strstr(line,"Boundary")) {2266sscanf(line,"%d",&sidetype);2267maxside = MAX(sidetype,maxside);2268}2269else {2270j++;2271sscanf(line,"%d",&k);2272nodeindx[j] = revindx[k];2273if(!nodeindx[j]) printf("The boundary %dth node %d is not in index list\n",j,k);2274boundindx[j] = sidetype;2275}2276}2277printf("Found %d boundary nodes with %d as maximum side.\n",j,maxside);2278fclose(in);22792280FindPointParents(data,bound,boundarynodes,nodeindx,boundindx,info);22812282if(namesexist) {2283int bcind=0,*bctypes=NULL,*bctypeused=NULL,*bcused=NULL,newsides=0;22842285data->bodynamesexist = TRUE;2286if(bound[0].nosides) {2287newsides = 0;2288bctypes = Ivector(1,maxside);2289bctypeused = Ivector(1,maxside);2290bcused = Ivector(1,bound[0].nosides);2291for(i=1;i<=bound[0].nosides;i++) bcused[i] = FALSE;2292data->boundarynamesexist = TRUE;2293for(i=1;i<=maxside;i++)2294bctypeused[i] = FALSE;2295}22962297sprintf(filename,"%s.names",prefix);2298in = fopen(filename,"r");22992300for(;;) {2301if(Getrow(line,in,TRUE)) break;2302sscanf(line,"%d%s%s%d",&bcind,&text[0],&text2[0],&sides);23032304if(strstr(text2,"BODY")) {2305GETLINE;2306sscanf(line,"%d%d",&j,&bcind);2307if(!data->bodyname[bcind]) data->bodyname[bcind] = Cvector(0,MAXNAMESIZE);2308strcpy(data->bodyname[bcind],text);2309}2310else if(strstr(text2,"BOUNDARY")) {2311/* Read the boundary groups belonging to a particular name */2312for(i=1;i<=maxside;i++)2313bctypes[i] = 0;2314for(i=1;i<=sides;i++) {2315GETLINE;2316sscanf(line,"%d%d",&j,&bcind);2317bctypes[bcind] = TRUE;2318}23192320/* Find 1st unused boundarytype */2321for(i=1;i<=maxside;i++)2322if(bctypes[i] && !bctypeused[i]) break;23232324bcind = i;2325bctypeused[bcind] = TRUE;2326if(0) printf("First unused boundary is of type %d\n",bcind);2327if(bcind>MAXBCS) bigerror("bcind larger than MAXBCS!");2328if(!data->boundaryname[bcind]) data->boundaryname[bcind] = Cvector(0,MAXNAMESIZE);2329strcpy(data->boundaryname[bcind],text);23302331/* Check which of the BCs have already been named */2332k = l = 0;2333for(i=1;i<=bound[0].nosides;i++) {2334j = bound[0].types[i];23352336/* The bc is not given any name, hence it can't be a duplicate */2337if(!bctypes[j]) continue;23382339if(!bcused[i]) {2340k++;2341bcused[i] = bcind;2342}2343else {2344l++;2345if(newsides == 0) AllocateBoundary(&bound[1],bound[0].nosides);2346newsides++;2347bound[1].types[newsides] = bcind;2348bound[1].parent[newsides] = bound[0].parent[i];2349bound[1].side[newsides] = bound[0].side[i];2350bound[1].parent2[newsides] = bound[0].parent2[i];2351bound[1].side2[newsides] = bound[0].side2[i];2352bound[1].normal[newsides] = bound[0].normal[i];2353}2354}2355if(info) {2356if(data->boundaryname[bcind])2357printf("There are %d boundary elements with name %s.\n",k+l,data->boundaryname[bcind]);2358}2359}2360}23612362fclose(in);23632364/* Put the indexes of all conditions with the same name to be same */2365if(bound[0].nosides) {2366for(i=1;i<=bound[0].nosides;i++)2367if(bcused[i]) bound[0].types[i] = bcused[i];2368if(newsides) {2369bound[1].nosides = newsides;2370if(info) printf("Created %d additional boundary elements to achieve unique naming.\n",newsides);2371}2372free_Ivector(bctypes,1,maxside);2373free_Ivector(bctypeused,1,maxside);2374free_Ivector(bcused,1,bound[0].nosides);2375}2376}23772378free_Ivector(boundindx,1,boundarynodes);2379free_Ivector(nodeindx,1,boundarynodes);23802381if(info) printf("Ansys mesh loaded successfully\n");23822383return(0);2384}238523862387static void ReorderFieldviewNodes(struct FemType *data,int *oldtopology,2388int element,int dim,int nodes)2389{2390int i,*topology,elementtype;2391int order808[]={1,2,4,3,5,6,8,7};2392int order706[]={1,4,6,2,3,5};2393int order404[]={1,2,3,4};23942395elementtype = 0;2396if(dim == 3) {2397if(nodes == 8) elementtype = 808;2398if(nodes == 6) elementtype = 706;2399if(nodes == 4) elementtype = 504;2400}2401else if(dim == 2) {2402if(nodes == 4) elementtype = 404;2403if(nodes == 3) elementtype = 303;2404}24052406if(!elementtype) {2407printf("Unknown elementtype in element %d (%d nodes, %d dim).\n",2408element,nodes,dim);2409bigerror("Cannot continue");2410}24112412data->elementtypes[element] = elementtype;2413topology = data->topology[element];24142415for(i=0;i<elementtype%100;i++) {2416if(elementtype == 808) topology[i] = oldtopology[order808[i]-1];2417else if(elementtype == 706) topology[i] = oldtopology[order706[i]-1];2418else if(elementtype == 404) topology[i] = oldtopology[order404[i]-1];2419else topology[i] = oldtopology[i];2420}2421}24222423242424252426int LoadFieldviewInput(struct FemType *data,struct BoundaryType *bound,char *prefix,int info)2427/* Load the grid from a format that can be read by FieldView2428program by PointWise. This is a suitable format to read files created2429by GridGen. */2430{2431int noknots,noelements,maxnodes,mode;2432char filename[MAXFILESIZE];2433char line[MAXLINESIZE],*cp;2434int i,j,k;2435FILE *in;2436Real x,y,z;2437int maxindx;2438char *isio;2439int nobound=0,nobulk=0,maxsidenodes;2440int *boundtypes=NULL,**boundtopos=NULL,*boundnodes=NULL,*origtopology=NULL;24412442if ((in = fopen(prefix,"r")) == NULL) {2443AddExtension(prefix,filename,"dat");2444if ((in = fopen(filename,"r")) == NULL) {2445printf("LoadFieldviewInput: opening of the Fieldview-file '%s' wasn't successful !\n",2446filename);2447return(1);2448}2449}24502451InitializeKnots(data);2452data->dim = 3;2453data->created = TRUE;24542455mode = 0;2456noknots = 0;2457noelements = 0;2458maxnodes = 8;2459maxsidenodes = 4;2460maxindx = 0;24612462data->maxnodes = maxnodes;24632464for(;;) {24652466if(mode == 0) {2467isio = GETLINE;24682469if(!isio) goto end;2470if(strstr(line,"END")) goto end;24712472/* Control information */2473if(strstr(line,"FIELDVIEW")) mode = 1;2474else if(strstr(line,"CONSTANTS")) mode = 2;2475else if(strstr(line,"GRIDS")) mode = 3;2476else if(strstr(line,"Boundary Table")) mode = 4;2477else if(strstr(line,"Variable Names")) mode = 5;2478else if(strstr(line,"Nodes")) mode = 6;2479else if(strstr(line,"Boundary Faces")) mode = 7;2480else if(strstr(line,"Elements")) mode = 8;2481else if(strstr(line,"Variables")) mode = 9;2482else if(0) printf("unknown: %s",line);2483}24842485switch (mode) {24862487case 1:2488printf("This is indeed a Fieldview input file.\n");2489mode = 0;2490break;24912492case 2:2493if(0) printf("Constants block\n");2494mode = 0;2495break;24962497case 3:2498if(0) printf("Grids block\n");2499mode = 0;2500break;25012502case 4:2503if(0) printf("Boundary Table\n");2504mode = 0;2505break;25062507case 5:2508if(0) printf("Variable names\n");2509mode = 0;2510break;25112512case 6:25132514GETLINE;2515sscanf(line,"%d",&noknots);2516data->noknots = noknots;25172518if(info) printf("Loading %d node coordinates\n",noknots);25192520data->x = Rvector(1,noknots);2521data->y = Rvector(1,noknots);2522data->z = Rvector(1,noknots);25232524for(i=1;i<=noknots;i++) {2525GETLINE;2526sscanf(line,"%le%le%le",&x,&y,&z);2527data->x[i] = x;2528data->y[i] = y;2529data->z[i] = z;2530}2531mode = 0;2532break;25332534case 7:25352536GETLINE;2537sscanf(line,"%d",&nobound);25382539if(info) printf("Loading %d boundary element definitions\n",nobound);25402541boundtypes = Ivector(1,nobound);2542boundtopos = Imatrix(1,nobound,0,maxsidenodes-1);2543boundnodes = Ivector(1,nobound);25442545for(i=1;i<=nobound;i++) {2546GETLINE; cp=line;25472548boundtypes[i]= next_int(&cp);2549maxsidenodes = next_int(&cp);25502551for(j=0;j<maxsidenodes && cp;j++)2552boundtopos[i][j] = next_int(&cp);25532554boundnodes[i] = j;2555}2556mode = 0;2557break;255825592560case 8:25612562if(info) printf("Loading bulk element definitions\n");25632564if(maxsidenodes == 4) noelements = noknots + nobound;2565else noelements = 6*noknots + nobound;25662567origtopology = Ivector(0,maxnodes-1);2568data->topology = Imatrix(1,noelements,0,maxnodes-1);2569data->material = Ivector(1,noelements);2570data->elementtypes = Ivector(1,noelements);25712572for(i=0;;) {2573GETLINE; cp=line;25742575if(strstr(line,"Variables")) mode = 9;2576if(mode != 8) break;25772578i++;25792580k = next_int(&cp);25812582if(k == 2) maxnodes = 8;2583else if(k == 1) maxnodes = 4;25842585data->material[i]= next_int(&cp);25862587for(j=0;j<maxnodes && cp;j++) {2588origtopology[j] = next_int(&cp);2589if(maxindx < origtopology[j]) maxindx = origtopology[j];2590}25912592ReorderFieldviewNodes(data,origtopology,i,3,j);25932594if(nobulk+nobound == noelements+1)2595printf("Too few elements (%d) were allocated!!\n",noelements);25962597}2598nobulk = i;25992600printf("Found %d bulk elements\n",nobulk);2601if(nobulk+nobound > noelements) printf("Too few elements (%d) were allocated!!\n",noelements);2602printf("Allocated %.4lg %% too many elements\n",2603noelements*100.0/(nobulk+nobound)-100.0);260426052606for(i=1;i<=nobound;i++) {2607ReorderFieldviewNodes(data,boundtopos[i],i+nobulk,2,boundnodes[i]);2608data->material[i+nobulk] = boundtypes[i];2609}26102611data->noelements = noelements = nobulk + nobound;26122613mode = 0;2614break;261526162617case 9:26182619printf("Variables\n");26202621mode = 0;2622break;26232624default:2625break;2626}2627}26282629end:26302631if(maxindx != noknots)2632printf("The maximum index %d differs from the number of nodes %d !\n",maxindx,noknots);26332634ElementsToBoundaryConditions(data,bound,FALSE,TRUE);26352636return(0);2637}26382639264026412642int LoadTriangleInput(struct FemType *data,struct BoundaryType *bound,2643char *prefix,int info)2644/* This procedure reads the mesh assuming Triangle format2645*/2646{2647int noknots,noelements,maxnodes,elematts,nodeatts,dim;2648int elementtype,bcmarkers,sideelemtype,offset,bcinds;2649int i,ii,j,k,jmin,jmax,kmin,kmax,*boundnodes;2650FILE *in;2651char *cp,line[MAXLINESIZE],elemfile[MAXFILESIZE],nodefile[MAXFILESIZE],2652polyfile[MAXLINESIZE];2653int *invrow,*invcol;265426552656if(info) printf("Loading mesh in Triangle format from file %s.*\n",prefix);26572658sprintf(nodefile,"%s.node",prefix);2659if ((in = fopen(nodefile,"r")) == NULL) {2660printf("LoadTriangleInput: The opening of the nodes file %s failed!\n",nodefile);2661return(1);2662}2663else2664printf("Loading nodes from file %s\n",nodefile);26652666GETLINE;2667sscanf(line,"%d %d %d %d",&noknots,&dim,&nodeatts,&bcmarkers);2668fclose(in);26692670if(dim != 2) {2671printf("LoadTriangleInput assumes that the space dimension is 2, not %d.\n",dim);2672return(2);2673}26742675sprintf(elemfile,"%s.ele",prefix);2676if ((in = fopen(elemfile,"r")) == NULL) {2677printf("LoadTriangleInput: The opening of the element file %s failed!\n",elemfile);2678return(3);2679}2680else2681printf("Loading elements from file %s\n",elemfile);26822683GETLINE;2684sscanf(line,"%d %d %d",&noelements,&maxnodes,&elematts);2685fclose(in);268626872688InitializeKnots(data);2689data->dim = dim;2690data->maxnodes = maxnodes;2691data->noelements = noelements;2692data->noknots = noknots;2693elementtype = 300 + maxnodes;2694bcinds = FALSE;26952696if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);2697AllocateKnots(data);26982699boundnodes = Ivector(1,noknots);2700for(i=1;i<=noknots;i++)2701boundnodes[i] = 0;27022703k = 0;2704jmax = 0;2705jmin = noknots;2706in = fopen(nodefile,"r");2707GETLINE;2708for(i=1; i <= noknots; i++) {2709GETLINE;2710cp = line;2711j = next_int(&cp);2712if(j != i) k++;2713jmax = MAX(jmax,j);2714jmin = MIN(jmin,j);27152716data->x[i] = next_real(&cp);2717data->y[i] = next_real(&cp);2718for(j=0;j<nodeatts;j++) {2719next_real(&cp);2720}2721if(bcmarkers > 0)2722boundnodes[i] = next_int(&cp);2723}2724fclose(in);2725if(info) {2726printf("LoadTriangleInput: Node index different from order index for %d nodes\n",k);2727printf("LoadTriangleInput: Node index ranged was [%d %d]\n",jmin,jmax);2728}27292730offset = 0;2731if(jmin==0) {2732printf("LoadTriangleInput: Using offset 1 to because of C-type indexing!\n");2733offset = 1;2734}273527362737k = 0;2738jmax = 0;2739jmin = noelements;2740kmax = 0;2741kmin = noknots;2742in = fopen(elemfile,"r");2743GETLINE;2744for(i=1; i <= noelements; i++) {2745GETLINE;2746cp = line;2747data->elementtypes[i] = elementtype;2748j = next_int(&cp);2749if(j != i) k++;2750jmin = MIN(jmin,j);2751jmax = MAX(jmax,j);2752for(j=0;j<3;j++)2753data->topology[i][j] = next_int(&cp);2754if(maxnodes == 6) {2755data->topology[i][4] = next_int(&cp);2756data->topology[i][5] = next_int(&cp);2757data->topology[i][3] = next_int(&cp);2758}2759if(offset) {2760for(j=0;j<maxnodes;j++) data->topology[i][j] = data->topology[i][j]+offset;2761}2762for(j=0;j<maxnodes;j++) kmax = MAX(kmax,data->topology[i][j]);2763for(j=0;j<maxnodes;j++) kmin = MIN(kmin,data->topology[i][j]);2764j = next_int(&cp);2765data->material[i] = MAX(1,j);2766}2767fclose(in);2768if(info) {2769printf("LoadTriangleInput: Element index different from order index for %d nodes\n",k);2770printf("LoadTriangleInput: Element index ranged was [%d %d]\n",jmin,jmax);2771printf("LoadTriangleInput: Node indexes in elements range [%d %d] (with offset)\n",kmin,kmax);2772}277327742775sprintf(polyfile,"%s.edge",prefix);2776if ((in = fopen(polyfile,"r")) == NULL) {2777printf("LoadTriangleInput: The opening of the poly file %s failed!\n",polyfile);2778return(1);2779}2780else2781printf("Loading boundaries from file %s\n",polyfile);27822783{2784int bcelems,markers,ind1,ind2,bctype,j2,k2,hit;2785int elemsides,sideind[2],side,elemind=0;27862787bctype = 1;2788elemsides = 3;2789hit = FALSE;27902791GETLINE;2792sscanf(line,"%d %d",&bcelems,&markers);27932794if(bcelems == 0) goto finish;27952796if(info) printf("Allocating for %d boundary elements.\n",bcelems);27972798CreateInverseTopology(data,info);2799invrow = data->invtopo.rows;2800invcol = data->invtopo.cols;28012802AllocateBoundary(bound,bcelems);28032804jmin = noknots;2805jmax = 0;28062807i = 0;2808for(ii=1;ii<=bcelems;ii++) {2809GETLINE;2810if(markers)2811sscanf(line,"%d %d %d %d",&j,&ind1,&ind2,&bctype);2812else2813sscanf(line,"%d %d %d",&j,&ind1,&ind2);28142815if(!bctype) continue;2816i += 1;28172818bctype = abs(bctype);28192820ind1 += offset;2821ind2 += offset;28222823jmin = MIN(jmin,MIN(ind1,ind2));2824jmax = MAX(jmax,MAX(ind1,ind2));28252826/* find an element which owns both the nodes */2827for(j=invrow[ind1-1];j<invrow[ind1];j++) {2828k = invcol[j]+1;2829hit = FALSE;28302831for(j2=invrow[ind2-1];j2<invrow[ind2];j2++) {2832k2 = invcol[j2]+1;2833if(k == k2) {2834hit = TRUE;2835elemind = k;2836break;2837}2838}2839if(hit) break;2840}28412842/* Find the correct side of the triangular element */2843if(hit) {2844k = 0;2845for(side=0;side<elemsides;side++) {2846GetElementSide(elemind,side,1,data,&sideind[0],&sideelemtype);28472848hit = FALSE;2849if(sideind[0] == ind1 && sideind[1] == ind2) hit = TRUE;2850if(sideind[0] == ind2 && sideind[1] == ind1) hit = TRUE;28512852if(hit) break;2853}2854}28552856if(hit) {2857bound->parent[i] = elemind;2858bound->side[i] = side;2859} else {2860bound->parent[i] = 0;2861bound->side[i] = 0;2862if(!bcinds) {2863bound->topology = Imatrix(1,bcelems,0,1);2864bcinds = TRUE;2865}2866bound->topology[i][0] = ind1;2867bound->topology[i][1] = ind2;2868}2869bound->parent2[i] = 0;2870bound->side2[i] = 0;2871bound->types[i] = bctype;2872k++;28732874if(0) printf("LoadTriangleInput: %d boundary elements found correctly out of %d\n",k,elemsides);28752876}2877bound->nosides = i;2878printf("LoadTriangleInput: Node indexes in boundary range [%d %d] (with offset)\n",jmin,jmax);28792880}28812882finish:2883printf("Successfully read the mesh from the Triangle input file.\n");28842885return(0);2886}28872888288928902891int LoadMeditInput(struct FemType *data,struct BoundaryType *bound,2892char *prefix,int info)2893/* This procedure reads the mesh assuming Medit format2894*/2895{2896int noknots=0,noelements=0,maxnodes,dim=0,elementtype=0;2897int i,j,allocated;2898FILE *in;2899char *cp,line[MAXLINESIZE],nodefile[MAXFILESIZE];290029012902sprintf(nodefile,"%s.mesh",prefix);2903if(info) printf("Loading mesh in Medit format from file %s\n",prefix);29042905if ((in = fopen(nodefile,"r")) == NULL) {2906printf("LoadMeditInput: The opening of the mesh file %s failed!\n",nodefile);2907return(1);2908}29092910allocated = FALSE;2911maxnodes = 0;29122913allocate:29142915if(allocated) {2916InitializeKnots(data);2917data->dim = dim;2918data->maxnodes = maxnodes;2919data->noelements = noelements;2920data->noknots = noknots;2921elementtype = 300 + maxnodes;29222923if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);2924AllocateKnots(data);2925in = fopen(nodefile,"r");2926}292729282929for(;;) {2930if(Getrow(line,in,TRUE)) goto end;2931if(strstr(line,"END")) goto end;29322933if(strstr(line,"DIMENSION")) {2934if(Getrow(line,in,TRUE)) goto end;2935cp = line;2936dim = next_int(&cp);2937printf("dim = %d %s",dim,line);2938}2939else if(strstr(line,"VERTICES")) {2940printf("verts: %s",line);29412942if(Getrow(line,in,TRUE)) goto end;2943cp = line;2944noknots = next_int(&cp);29452946printf("noknots = %d %s",noknots,line);29472948for(i=1; i <= noknots; i++) {2949GETLINE;2950if(allocated) {2951cp = line;2952data->x[i] = next_real(&cp);2953data->y[i] = next_real(&cp);2954if(dim > 2) data->z[i] = next_real(&cp);2955}2956}2957}2958else if(strstr(line,"TRIANGLES")) {2959if(Getrow(line,in,TRUE)) goto end;2960cp = line;2961noelements = next_int(&cp);29622963printf("noelements = %d %s",noelements,line);29642965elementtype = 303;2966if(maxnodes < 3) maxnodes = 3;29672968for(i=1; i <= noelements; i++) {2969GETLINE;2970if(allocated) {2971cp = line;2972data->elementtypes[i] = elementtype;2973for(j=0;j<3;j++)2974data->topology[i][j] = next_int(&cp);2975data->material[i] = next_int(&cp);2976}2977}2978}2979#if 02980else printf("unknown command: %s",line);2981#endif2982}29832984end:2985fclose(in);29862987printf("ALLOCATED=%d\n",allocated);29882989if(!allocated) {2990allocated = TRUE;2991goto allocate;2992}29932994printf("Successfully read the mesh from the Medit input file.\n");29952996return(0);2997}29982999300030013002int LoadGidInput(struct FemType *data,struct BoundaryType *bound,3003char *prefix,int info)3004/* Load the grid from GID mesh format */3005{3006int noknots,noelements,maxnodes,foundsame;3007int mode,allocated,nosides,sideelemtype;3008int boundarytype,side,parent,elemsides,materialtype=0;3009int dim=0, elemnodes=0, elembasis=0, elemtype=0, bulkdone, usedmax=0,hits;3010int minbulk,maxbulk,minbound,maxbound,label,debug;3011int *usedno=NULL, **usedelem=NULL;3012char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;3013int i,j,k,n,ind,inds[MAXNODESD2],sideind[MAXNODESD1];3014FILE *in;3015Real x,y,z;30163017debug = FALSE;30183019strcpy(filename,prefix);3020if ((in = fopen(filename,"r")) == NULL) {3021AddExtension(prefix,filename,"msh");3022if ((in = fopen(filename,"r")) == NULL) {3023printf("LoadGidInput: opening of the GID-file '%s' wasn't successful !\n",3024filename);3025return(1);3026}3027}30283029printf("Reading mesh from GID file %s.\n",filename);3030InitializeKnots(data);30313032allocated = FALSE;30333034/* Because the file format doesn't provide the number of elements3035or nodes the results are read twice but registered only in the3036second time. */30373038minbulk = minbound = 1000;3039maxbulk = maxbound = 0;30403041omstart:30423043mode = 0;3044maxnodes = 0;3045noknots = 0;3046noelements = 0;3047boundarytype = 0;3048nosides = 0;3049bulkdone = FALSE;30503051for(;;) {30523053if(Getrow(line,in,FALSE)) goto end;30543055if(strstr(line,"MESH")) {3056if(debug) printf("MESH\n");30573058if(strstr(line,"dimension 3"))3059dim = 3;3060else if(strstr(line,"dimension 2"))3061dim = 2;3062else printf("Unknown dimension\n");30633064if(strstr(line,"ElemType Tetrahedra"))3065elembasis = 500;3066else if(strstr(line,"ElemType Triangle"))3067elembasis = 300;3068else if(strstr(line,"ElemType Linear"))3069elembasis = 200;3070else printf("Unknown elementtype: %s\n",line);30713072if(strstr(line,"Nnode 4"))3073elemnodes = 4;3074else if(strstr(line,"Nnode 3"))3075elemnodes = 3;3076else if(strstr(line,"Nnode 2"))3077elemnodes = 2;3078else printf("Unknown elementnode: %s\n",line);30793080if(elemnodes > maxnodes) maxnodes = elemnodes;3081elemtype = elembasis + elemnodes;3082mode = 0;30833084if(debug) printf("dim=%d elemtype=%d\n",dim,elemtype);3085}3086else if(strstr(line,"Coordinates")) {3087if(debug) printf("Start coords\n");3088mode = 1;3089}3090else if(strstr(line,"end coordinates")) {3091if(debug) printf("End coords\n");3092mode = 0;3093}3094else if(strstr(line,"Elements")) {3095if(bulkdone) {3096if(debug) printf("Start boundary elems\n");3097mode = 3;3098boundarytype++;3099}3100else {3101if(debug) printf("Start bulk elems\n");3102mode = 2;3103}3104}3105else if(strstr(line,"end elements")) {3106if(debug) printf("End elems\n");31073108mode = 0;3109if(!bulkdone && allocated) {3110usedno = Ivector(1,data->noknots);31113112for(j=1;j<=data->noknots;j++)3113usedno[j] = 0;31143115for(j=1;j<=data->noelements;j++) {3116n = data->elementtypes[j] % 100;3117for(i=0;i<n;i++) {3118ind = data->topology[j][i];3119usedno[data->topology[j][i]] += 1;3120}3121}31223123usedmax = 0;3124for(i=1;i<=data->noknots;i++)3125if(usedno[i] > usedmax) usedmax = usedno[i];31263127for(j=1;j<=data->noknots;j++)3128usedno[j] = 0;31293130usedelem = Imatrix(1,data->noknots,1,usedmax);3131for(j=1;j<=data->noknots;j++)3132for(i=1;i<=usedmax;i++)3133usedelem[j][i] = 0;31343135for(j=1;j<=data->noelements;j++) {3136n = data->elementtypes[j] % 100;3137for(i=0;i<n;i++) {3138ind = data->topology[j][i];3139usedno[ind] += 1;3140k = usedno[ind];3141usedelem[ind][k] = j;3142}3143}3144}3145bulkdone = TRUE;3146}3147else if(!mode) {3148if(debug) printf("mode: %d %s\n",mode,line);3149}3150else if(mode) {3151switch (mode) {31523153case 1:3154cp = line;3155ind = next_int(&cp);3156if(ind > noknots) noknots = ind;31573158x = next_real(&cp);3159y = next_real(&cp);3160if(dim == 3) z = next_real(&cp);31613162if(allocated) {3163data->x[ind] = x;3164data->y[ind] = y;3165if(dim == 3) data->z[ind] = z;3166}3167break;31683169case 2:3170cp = line;3171ind = next_int(&cp);3172if(ind > noelements) noelements = ind;31733174for(i=0;i<elemnodes;i++) {3175k = next_int(&cp);3176if(allocated) {3177data->topology[ind][i] = k;3178data->elementtypes[ind] = elemtype;3179data->material[ind] = 1;3180}3181}3182label = next_int(&cp);31833184if(allocated) {3185if(label) {3186materialtype = label-minbulk+1;3187}3188else if(maxbound) {3189materialtype = maxbulk-minbulk + 2;3190}3191else {3192materialtype = 1;3193}3194data->material[ind] = materialtype;3195}3196else {3197if(label > maxbulk) maxbulk = label;3198if(label < minbulk) minbulk = label;3199}32003201break;32023203case 3:3204cp = line;3205ind = next_int(&cp);3206nosides++;32073208for(i=0;i<elemnodes;i++) {3209k = next_int(&cp);3210inds[i] = k;3211}3212label = next_int(&cp);32133214if(!allocated) {3215if(label) {3216if(label > maxbound) maxbound = label;3217if(label < minbound) minbound = label;3218}3219}32203221if(allocated) {32223223if(label) {3224boundarytype = label-minbound+1;3225}3226else if(maxbound) {3227boundarytype = maxbound-minbound + 2;3228}3229else {3230boundarytype = 1;3231}32323233foundsame = FALSE;3234for(i=1;i<=usedno[inds[0]];i++) {3235parent = usedelem[inds[0]][i];32363237elemsides = data->elementtypes[parent] % 100;32383239for(side=0;side<elemsides;side++) {32403241GetElementSide(parent,side,1,data,&sideind[0],&sideelemtype);32423243if(elemnodes != sideelemtype%100) printf("LoadGidMesh: bug?\n");32443245hits = 0;3246for(j=0;j<elemnodes;j++)3247for(k=0;k<elemnodes;k++)3248if(sideind[j] == inds[k]) hits++;32493250if(hits < elemnodes) continue;32513252if(!foundsame) {3253foundsame++;3254bound->parent[nosides] = parent;3255bound->side[nosides] = side;3256bound->parent2[nosides] = 0;3257bound->side2[nosides] = 0;3258bound->types[nosides] = boundarytype;3259}3260else if(foundsame == 1) {3261if(parent == bound->parent[nosides]) continue;3262foundsame++;3263bound->parent2[nosides] = parent;3264bound->side2[nosides] = side;3265}3266else if(foundsame > 1) {3267printf("Boundary %d has more than 2 parents\n",nosides);3268}3269}3270}3271if(!foundsame) {3272printf("Did not find parent for side %d\n",nosides);3273nosides--;3274}3275else {3276if(debug) printf("Parent of side %d is %d\n",nosides,bound->parent[nosides]);3277}3278}3279}3280}3281}32823283end:32843285if(!allocated) {3286rewind(in);3287data->noknots = noknots;3288data->noelements = noelements;3289data->maxnodes = maxnodes;3290data->dim = dim;32913292if(info) {3293printf("Allocating for %d knots and %d %d-node elements.\n",3294noknots,noelements,maxnodes);3295printf("Initial material indexes are at interval %d to %d.\n",minbulk,maxbulk);3296}3297AllocateKnots(data);32983299if(info) {3300printf("Allocating %d boundary elements\n",nosides);3301printf("Initial boundary indexes are at interval %d to %d.\n",minbound,maxbound);3302}3303AllocateBoundary(bound,nosides);33043305bound->nosides = nosides;3306bound->created = TRUE;33073308nosides = 0;3309bulkdone = FALSE;3310boundarytype = 0;33113312allocated = TRUE;3313goto omstart;3314}33153316bound->nosides = nosides;3317free_Ivector(usedno,1,data->noknots);3318free_Imatrix(usedelem,1,data->noknots,1,usedmax);33193320if(info) printf("The mesh was loaded from file %s.\n",filename);3321return(0);3322}3323332433253326static void ReorderComsolNodes(int elementtype,int *topo)3327{3328int i,tmptopo[MAXNODESD2];3329int order404[]={1,2,4,3};3330int order808[]={1,2,4,3,5,6,8,7};3331int order605[]={1,2,4,3,5};333233333334switch (elementtype) {33353336case 404:3337for(i=0;i<elementtype%100;i++)3338tmptopo[i] = topo[i];3339for(i=0;i<elementtype%100;i++)3340topo[i] = tmptopo[order404[i]-1];3341break;33423343case 808:3344for(i=0;i<elementtype%100;i++)3345tmptopo[i] = topo[i];3346for(i=0;i<elementtype%100;i++)3347topo[i] = tmptopo[order808[i]-1];3348break;33493350case 605:3351for(i=0;i<elementtype%100;i++)3352tmptopo[i] = topo[i];3353for(i=0;i<elementtype%100;i++)3354topo[i] = tmptopo[order605[i]-1];3355break;335633573358default:3359break;33603361}3362}3363336433653366int LoadComsolMesh(struct FemType *data,struct BoundaryType *bound,char *prefix,int info)3367/* Load the grid in Comsol Multiphysics mesh format */3368{3369int noknots,noelements,maxnodes,material;3370int allocated,dim=0, elemnodes=0, elembasis=0, elemtype;3371int debug,domains,mindom,minbc,maxdom,maxbc,maxlabel,elemdim=0,entitylen,entitydim;3372int *bclabel, *domlabel, n_label=0, offset, bcoffset, domoffset, *bcinfo;3373char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;3374char entityname[MAXNAMESIZE];3375int i,j,k;3376FILE *in;33773378strcpy(filename,prefix);3379if ((in = fopen(filename,"r")) == NULL) {3380AddExtension(prefix,filename,"mphtxt");3381if ((in = fopen(filename,"r")) == NULL) {3382if(info) printf("LoadComsolMesh: opening of the Comsol mesh file '%s' wasn't successful !\n",3383filename);3384return(1);3385}3386}33873388if(info) printf("Reading mesh from Comsol mesh file %s.\n",filename);3389InitializeKnots(data);33903391debug = FALSE;3392allocated = FALSE;33933394mindom = 1000;3395minbc = 1000;3396maxdom = 0;3397maxlabel = 0;3398maxbc = 0;3399offset = 1;34003401omstart:34023403maxnodes = 0;3404noknots = 0;3405noelements = 0;3406material = 0;3407domains = 0;340834093410for(;;) {34113412if(Comsolrow(line,in)) goto end;34133414if(strstr(line,"# sdim")) {3415cp = line;3416dim = next_int(&cp);3417if(info && !allocated) printf("Dimension of mesh is: %d\n",dim);3418}34193420else if(strstr(line,"# number of mesh points") || strstr(line, "# number of mesh vertices")) {3421cp = line;3422noknots = next_int(&cp);3423if(debug) printf("noknots=%d\n",noknots);3424}34253426else if(strstr(line,"# lowest mesh point index") || strstr(line, "# lowest mesh vertex index")) {3427cp = line;3428offset = 1 - next_int(&cp);3429if(debug) printf("offset=%d\n",offset);3430}34313432else if(strstr(line,"# type name")) {3433if(strstr(line,"vtx")) elembasis = 100;3434else if(strstr(line,"edg")) elembasis = 200;3435else if(strstr(line,"tri")) elembasis = 300;3436else if(strstr(line,"quad")) elembasis = 400;3437else if(strstr(line,"tet")) elembasis = 500;3438else if(strstr(line,"pyr")) elembasis = 600;3439else if(strstr(line,"prism")) elembasis = 700;3440else if(strstr(line,"hex")) elembasis = 800;3441else {3442printf("unknown element type = %s",line);3443bigerror("Cannot continue!\n");3444}3445}34463447else if(strstr(line,"# number of nodes per element") || strstr(line, "# number of vertices per element")) {3448cp = line;3449elemnodes = next_int(&cp);3450if(elemnodes > maxnodes) maxnodes = elemnodes;3451if(debug) printf("elemnodes=%d\n",elemnodes);3452}34533454else if(strstr(line,"# Mesh point coordinates") || strstr(line, "# Mesh vertex coordinates" )) {3455for(i=1;i<=noknots;i++) {3456Comsolrow(line,in);34573458if(allocated) {3459cp = line;3460data->x[i] = next_real(&cp);3461data->y[i] = next_real(&cp);3462if(dim == 3) data->z[i] = next_real(&cp);3463}3464}3465}34663467else if(strstr(line,"# number of elements")) {34683469cp = line;3470k = next_int(&cp);34713472Comsolrow(line,in);3473elemtype = elemnodes + elembasis;3474elemdim = GetElementDimension(elemtype);34753476if(debug) printf("Loading %d elements of type %d\n",k,elemtype);3477domains = noelements;34783479for(i=1;i<=k;i++) {3480Comsolrow(line,in);34813482if(dim == 3 && elembasis < 300) continue;3483if(dim == 2 && elembasis < 200) continue;34843485noelements = noelements + 1;3486if(allocated) {3487data->elementtypes[noelements] = elemtype;3488data->material[noelements] = 1;3489cp = line;3490for(j=0;j<elemnodes;j++)3491data->topology[noelements][j] = next_int(&cp) + offset;34923493if(1) ReorderComsolNodes(elemtype,data->topology[noelements]);34943495}3496}3497}34983499else if(strstr(line,"# number of geometric entity indices") ||3500strstr(line,"# number of domains")) {35013502cp = line;3503k = next_int(&cp);35043505Comsolrow(line,in);3506if(debug) printf("Loading %d domains for the elements\n",k);35073508for(i=1;i<=k;i++) {3509Comsolrow(line,in);35103511if(dim == 3 && elembasis < 300) continue;3512if(dim == 2 && elembasis < 200) continue;35133514domains = domains + 1;3515cp = line;3516material = next_int(&cp);35173518if(allocated) {3519if( elemdim < dim ) {3520if(maxlabel>0) bcinfo[domains] = TRUE;3521data->material[domains] = material + bcoffset;3522}3523else {3524data->material[domains] = material + domoffset;3525}3526}3527else {3528if(elemdim < dim) {3529minbc = MIN(minbc,material);3530maxbc = MAX(maxbc,material);3531}3532else {3533mindom = MIN(mindom,material);3534maxdom = MAX(maxdom,material);3535}3536}35373538}3539}35403541else if(strstr(line,"# Label") && !strstr(line,"Union Selection")) {3542int ind, ind1, n_ent = 0;35433544n_label += 1;3545maxlabel = MAX(maxlabel,n_label);35463547if(debug) printf("Reading Label %d\n",n_label);35483549if(allocated) {3550/* Read the length of the label and proceed over the empty space*/3551cp = line;3552entitylen = next_int(&cp);3553cp += 1;3554strncpy(entityname,cp,entitylen);3555entityname[entitylen] = '\0';3556if(debug) printf("BoundaryName %d is: %s\n",n_label,entityname);3557}35583559j = 0;3560for(i=1;i<=4;i++) {3561Comsolrow(line,in);3562if(strstr(line,"# Geometry/mesh tag")) j++;3563if(strstr(line,"# Dimension")) {3564cp = line;3565entitydim = next_int(&cp);3566if(debug) printf("Dimension of entity: %d\n",entitydim);3567j++;3568}3569if(strstr(line,"# Number of entities")) {3570j++;3571cp = line;3572n_ent = next_int(&cp);3573if(debug) printf("Number of entities: %d\n",n_ent);3574}3575if(strstr(line,"# Entities")) {3576if(debug) printf("Reading %d entities\n",n_ent);3577j++;3578for(k=1;k<=n_ent;k++) {3579Comsolrow(line,in);3580if(allocated) {3581cp = line;3582if(entitydim == dim ) {3583ind = next_int(&cp)+domoffset;3584if(k==1) {3585/* Use the first entity to represent all entities. */3586ind1 = ind;3587data->bodyname[ind1] = Cvector(0,MAXNAMESIZE);3588strncpy(data->bodyname[ind1],entityname,entitylen);3589}3590domlabel[ind] = ind1;3591if(debug) printf("Mapping bulk: %d %d %d\n",n_label,ind,ind1);3592}3593else if(entitydim == dim-1 ) {3594ind = next_int(&cp)+bcoffset;3595if(k==1) {3596ind1 = ind;3597data->boundaryname[ind1] = Cvector(0,MAXNAMESIZE);3598strncpy(data->boundaryname[ind1],entityname,entitylen);3599}3600bclabel[ind] = ind1;3601if(debug) printf("Mapping bc: %d %d %d\n",n_label,ind,ind1);3602}3603}3604}3605}3606}3607if(j<4) {3608if(debug) printf("We should have number 4 keywords after label so something might be off!");3609break;3610}3611}3612else if(strstr(line,"#")) {3613if(debug) printf("Unused command: %s",line);3614}36153616}36173618end:36193620if(!allocated) {36213622if(noknots == 0 || noelements == 0 || maxnodes == 0) {3623printf("Invalid mesh consists of %d knots and %d %d-node elements.\n",3624noknots,noelements,maxnodes);3625fclose(in);3626return(2);3627}36283629rewind(in);36303631if(info) {3632printf("Comsol mesh consists of %d nodes and %d elements\n",noknots,noelements);3633}36343635data->noknots = noknots;3636data->noelements = noelements;3637data->maxnodes = maxnodes;3638data->dim = dim;3639n_label = 0;36403641bcoffset = 1 - minbc;3642domoffset = 1 - mindom;36433644if(info) {3645printf("Original body index range is [%d,%d]\n",mindom,maxdom);3646printf("Original bc index range is [%d,%d]\n",minbc,maxbc);3647if(domoffset) printf("Offset of body indexing set to start from one!\n");3648if(bcoffset) printf("Offset of BC indexing set to start from one!\n");3649}36503651if(maxlabel>0) {3652if(info) printf("Mesh has %d labels with physical names.\n",maxlabel);36533654/* Allocate for the tables that renumbers geometric entities to physical ones. */3655maxbc++;3656maxdom++;3657bclabel = Ivector(minbc,maxbc);3658for(i=minbc;i<=maxbc;i++)3659bclabel[i] = -1;3660domlabel = Ivector(mindom,maxdom);3661for(i=mindom;i<=maxdom;i++)3662domlabel[i] = -1;36633664bcinfo = Ivector(1,noelements);3665for(i=1;i<=noelements;i++)3666bcinfo[i] = FALSE;36673668/* The code may think bodies are boundaries unless both names are set to exist even if they don't. */3669data->bodynamesexist = TRUE;3670data->boundarynamesexist = TRUE;3671}36723673if(info) {3674printf("Allocating for %d knots and %d %d-node elements.\n",3675noknots,noelements,maxnodes);3676}3677AllocateKnots(data);3678allocated = TRUE;36793680goto omstart;3681}3682fclose(in);36833684/* Perform remapping of entities */3685if(maxlabel > 0 ) {36863687if(debug) {3688for(i=minbc;i<=maxbc;i++)3689if(bclabel[i] > 0) printf("bc map: %d %d\n",i,bclabel[i]);3690for(i=mindom;i<=maxdom;i++)3691if(domlabel[i] > 0) printf("bulk map: %d %d\n",i,domlabel[i]);3692}36933694for(i=1;i<=data->noelements;i++) {3695j = data->material[i];3696if(bcinfo[i]) {3697if(bclabel[j]>-1) data->material[i] = bclabel[j];3698}3699else {3700if(domlabel[j]>-1)3701data->material[i] = domlabel[j];3702}3703}3704free_Ivector(bclabel,minbc,maxbc);3705free_Ivector(domlabel,mindom,maxdom);3706free_Ivector(bcinfo,1,noelements);3707}37083709if(info) printf("Comsol mesh was loaded from file %s.\n\n",filename);3710ElementsToBoundaryConditions(data,bound,FALSE,TRUE);37113712return(0);3713}3714371537163717static int GmshToElmerType(int gmshtype)3718{3719int elmertype = 0;37203721switch (gmshtype) {37223723case 1:3724elmertype = 202;3725break;3726case 2:3727elmertype = 303;3728break;3729case 3:3730elmertype = 404;3731break;3732case 4:3733elmertype = 504;3734break;3735case 5:3736elmertype = 808;3737break;3738case 6:3739elmertype = 706;3740break;3741case 7:3742elmertype = 605;3743break;3744case 8:3745elmertype = 203;3746break;3747case 9:3748elmertype = 306;3749break;3750case 10:3751elmertype = 409;3752break;3753case 11:3754elmertype = 510;3755break;3756case 12:3757elmertype = 827;3758break;3759case 15:3760elmertype = 101;3761break;3762case 16:3763elmertype = 408;3764break;3765case 17:3766elmertype = 820;3767break;3768case 18:3769elmertype = 715;3770break;3771case 19:3772elmertype = 613;3773break;3774case 21:3775elmertype = 310;3776break;3777case 26:3778elmertype = 204;3779break;3780case 36:3781elmertype = 416;3782break;37833784/* These are supported by Gmsh but not by ElmerSolver */3785case 13:3786elmertype = 718;3787break;3788case 14:3789elmertype = 614;3790break;3791case 20:3792elmertype = 309;3793break;3794case 22:3795elmertype = 312;3796break;3797case 24:3798elmertype = 315;3799break;3800case 25:3801elmertype = 320;3802break;3803case 27:3804elmertype = 205;3805break;3806case 28:3807elmertype = 206;3808break;3809case 29:3810elmertype = 520;3811break;38123813default:3814printf("Gmsh element %d does not have an Elmer counterpart!\n",gmshtype);3815}38163817return(elmertype);3818}381938203821static void GmshToElmerIndx(int elemtype,int *topology)3822{3823int i=0,nodes=0,oldtopology[MAXNODESD2];3824int reorder, *porder;38253826int order510[]={0,1,2,3,4,5,6,7,9,8};3827int order614[]={0,1,2,3,4,5,8,10,6,7,9,11,12,13};3828int order718[]={0,1,2,3,4,5,6,9,7,8,10,11,12,14,13,15,17,16};3829int order820[]={0,1,2,3,4,5,6,7,8,11,13,9,10,12,14,15,16,18,19,17};3830int order827[]={0,1,2,3,4,5,6,7,8,11,13,9,10,12,14,15,16,18,19,17,21,23,24,22,20,25,26};3831/* {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26}; */383238333834reorder = FALSE;38353836switch (elemtype) {38373838case 510:3839reorder = TRUE;3840porder = &order510[0];3841break;38423843case 613:3844case 614:3845reorder = TRUE;3846porder = &order614[0];3847break;38483849case 715:3850case 718:3851reorder = TRUE;3852porder = &order718[0];3853break;38543855case 820:3856reorder = TRUE;3857porder = &order820[0];3858break;38593860case 827:3861reorder = TRUE;3862porder = &order827[0];3863break;3864}38653866if( reorder ) {3867nodes = elemtype % 100;3868for(i=0;i<nodes;i++)3869oldtopology[i] = topology[i];3870for(i=0;i<nodes;i++)3871topology[i] = oldtopology[porder[i]];3872}3873}387438753876static int LoadGmshInput1(struct FemType *data,struct BoundaryType *bound,3877char *filename,int info)3878{3879int noknots = 0,noelements = 0,maxnodes,dim;3880int elemind[MAXNODESD2],elementtype;3881int i,j,k,allocated,*revindx=NULL,maxindx;3882int elemno, gmshtype, regphys, regelem, elemnodes,maxelemtype;3883FILE *in;3884char *cp,line[MAXLINESIZE];388538863887if ((in = fopen(filename,"r")) == NULL) {3888printf("LoadGmshInput: The opening of the mesh file %s failed!\n",filename);3889return(1);3890}3891if(info) printf("Loading mesh in Gmsh format 1.0 from file %s\n",filename);38923893allocated = FALSE;3894dim = data->dim;3895maxnodes = 0;3896maxindx = 0;3897maxelemtype = 0;38983899allocate:39003901if(allocated) {3902InitializeKnots(data);3903data->dim = dim;3904data->maxnodes = maxnodes;3905data->noelements = noelements;3906data->noknots = noknots;39073908if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);3909AllocateKnots(data);39103911if(maxindx > noknots) {3912revindx = Ivector(1,maxindx);3913for(i=1;i<=maxindx;i++) revindx[i] = 0;3914}3915in = fopen(filename,"r");3916}391739183919for(;;) {3920if(Getrow(line,in,TRUE)) goto end;3921if(strstr(line,"END")) goto end;39223923if(strstr(line,"$NOD")) {39243925GETLINE;3926cp = line;3927noknots = next_int(&cp);39283929for(i=1; i <= noknots; i++) {3930GETLINE;3931cp = line;39323933j = next_int(&cp);3934if(allocated) {3935if(maxindx > noknots) revindx[j] = i;3936data->x[i] = next_real(&cp);3937data->y[i] = next_real(&cp);3938if(dim > 2) data->z[i] = next_real(&cp);3939}3940else {3941maxindx = MAX(j,maxindx);3942}3943}3944GETLINE;3945if(!strstr(line,"$ENDNOD")) {3946printf("NOD section should end to string ENDNOD\n");3947printf("%s\n",line);3948}3949}39503951if(strstr(line,"$ELM")) {3952GETLINE;3953cp = line;3954noelements = next_int(&cp);39553956for(i=1; i <= noelements; i++) {3957GETLINE;39583959cp = line;3960elemno = next_int(&cp);3961gmshtype = next_int(&cp);3962regphys = next_int(&cp);3963regelem = next_int(&cp);3964elemnodes = next_int(&cp);39653966if(allocated) {3967elementtype = GmshToElmerType(gmshtype);3968maxelemtype = MAX(maxelemtype,elementtype);3969data->elementtypes[i] = elementtype;3970data->material[i] = regphys;39713972if(elemnodes != elementtype%100) {3973printf("Conflict in elementtypes %d and number of nodes %d!\n",3974elementtype,elemnodes);3975}3976for(j=0;j<elemnodes;j++)3977elemind[j] = next_int(&cp);39783979GmshToElmerIndx(elementtype,elemind);39803981for(j=0;j<elemnodes;j++)3982data->topology[i][j] = elemind[j];3983}3984else {3985maxnodes = MAX(elemnodes,maxnodes);3986}39873988}3989GETLINE;3990if(!strstr(line,"$ENDELM"))3991printf("ELM section should end to string ENDELM\n");3992}39933994}39953996end:39973998fclose(in);39994000if(!allocated) {4001allocated = TRUE;4002goto allocate;4003}400440054006if(maxindx > noknots) {4007printf("Renumbering the Gmsh nodes from %d to %d\n",maxindx,noknots);40084009for(i=1; i <= noelements; i++) {4010elementtype = data->elementtypes[i];4011elemnodes = elementtype % 100;40124013for(j=0;j<elemnodes;j++) {4014k = data->topology[i][j];4015if(k <= 0 || k > maxindx)4016printf("index out of bounds %d\n",k);4017else if(revindx[k] <= 0)4018printf("unknown node %d %d in element %d\n",k,revindx[k],i);4019else4020data->topology[i][j] = revindx[k];4021}4022}4023free_Ivector(revindx,1,maxindx);4024}40254026ElementsToBoundaryConditions(data,bound,FALSE,info);40274028printf("Successfully read the mesh from the Gmsh input file.\n");40294030return(0);4031}403240334034static int LoadGmshInput2(struct FemType *data,struct BoundaryType *bound,4035char *filename,int usetaggeom, int keeporphans, int info)4036{4037int noknots = 0,noelements = 0,nophysical = 0,maxnodes,dim,notags;4038int elemind[MAXNODESD2],elementtype;4039int i,j,k,allocated,*revindx=NULL,maxindx;4040int elemno, gmshtype, tagphys=0, taggeom=0, tagpart, elemnodes,maxelemtype;4041int tagmat,verno;4042int physvolexist, physsurfexist;4043FILE *in;4044const char manifoldname[4][10] = {"point", "line", "surface", "volume"};4045char *cp,line[MAXLINESIZE];40464047if ((in = fopen(filename,"r")) == NULL) {4048printf("LoadGmshInput2: The opening of the mesh file %s failed!\n",filename);4049return(1);4050}4051if(info) printf("Loading mesh in Gmsh format 2.0 from file %s\n",filename);40524053allocated = FALSE;4054dim = data->dim;4055maxnodes = 0;4056maxindx = 0;4057maxelemtype = 0;4058physvolexist = FALSE;4059physsurfexist = FALSE;4060usetaggeom = FALSE;40614062omstart:40634064for(;;) {4065if(Getrow(line,in,FALSE)) goto end;4066if(strstr(line,"$End")) continue;40674068if(strstr(line,"$MeshFormat")) {4069GETLINE;4070cp = line;4071verno = next_int(&cp);40724073if(verno != 2) {4074printf("Version number is not compatible with the parser: %d\n",verno);4075}40764077GETLINE;4078if(!strstr(line,"$EndMeshFormat")) {4079printf("$MeshFormat section should end to string $EndMeshFormat:\n%s\n",line);4080}4081}40824083else if(strstr(line,"$Nodes")) {4084GETLINE;4085cp = line;4086noknots = next_int(&cp);40874088for(i=1; i <= noknots; i++) {4089GETLINE;4090cp = line;40914092j = next_int(&cp);4093if(allocated) {4094if(maxindx > noknots) revindx[j] = i;4095data->x[i] = next_real(&cp);4096data->y[i] = next_real(&cp);4097if(dim > 2) data->z[i] = next_real(&cp);4098}4099else {4100maxindx = MAX(j,maxindx);4101}4102}4103GETLINE;4104if(!strstr(line,"$EndNodes")) {4105printf("$Nodes section should end to string $EndNodes:\n%s\n",line);4106}4107}41084109else if(strstr(line,"$Elements")) {4110GETLINE;4111cp = line;4112noelements = next_int(&cp);41134114for(i=1; i <= noelements; i++) {4115GETLINE;41164117cp = line;4118elemno = next_int(&cp);4119gmshtype = next_int(&cp);4120elementtype = GmshToElmerType(gmshtype);41214122if(allocated) {4123elemnodes = elementtype % 100;4124data->elementtypes[i] = elementtype;41254126/* Point does not seem to have physical properties */4127notags = next_int(&cp);4128if(notags > 0) tagphys = next_int(&cp);4129if(notags > 1) taggeom = next_int(&cp);4130if(notags > 2) tagpart = next_int(&cp);4131for(j=4;j<=notags;j++)4132next_int(&cp);41334134if(tagphys) {4135tagmat = tagphys;4136}4137else {4138tagmat = taggeom;4139usetaggeom = TRUE;4140}41414142data->material[i] = tagmat;4143for(j=0;j<elemnodes;j++)4144elemind[j] = next_int(&cp);41454146GmshToElmerIndx(elementtype,elemind);41474148for(j=0;j<elemnodes;j++)4149data->topology[i][j] = elemind[j];4150}4151else {4152maxelemtype = MAX(maxelemtype,elementtype);4153}41544155}4156GETLINE;4157if(!strstr(line,"$EndElements")) {4158printf("$Elements section should end to string $EndElements:\n%s\n",line);4159}4160}4161else if(strstr(line,"$PhysicalNames")) {4162int entdim;4163entdim = dim;4164GETLINE;4165cp = line;4166nophysical = next_int(&cp);4167for(i=0;i<nophysical;i++) {4168GETLINE;4169if(allocated) {4170cp = line;4171gmshtype = next_int(&cp);4172if(gmshtype < entdim-1) {4173printf("Assuming maximum entity dim to be %d\n",dim-1);4174entdim--;4175}4176tagphys = next_int(&cp);4177if(gmshtype == entdim-1) {4178physsurfexist = TRUE;4179if(tagphys < MAXBCS) {4180if(!data->boundaryname[tagphys]) data->boundaryname[tagphys] = Cvector(0,MAXNAMESIZE);4181sscanf(cp," \"%[^\"]\"",data->boundaryname[tagphys]);4182}4183else printf("Index %d too high: ignoring physical %s %s",tagphys,manifoldname[gmshtype],cp+1);4184}4185else if(gmshtype == entdim) {4186physvolexist = TRUE;41874188if(tagphys < MAXBODIES) {4189if(!data->bodyname[tagphys]) data->bodyname[tagphys] = Cvector(0,MAXNAMESIZE);4190sscanf(cp," \"%[^\"]\"",data->bodyname[tagphys]);4191}4192else printf("Index %d too high: ignoring physical %s %s",tagphys,manifoldname[gmshtype],cp+1);4193}4194else printf("Physical groups of dimension %d not supported in %d-dimensional mesh: "4195"ignoring group %d %s",gmshtype,dim,tagphys,cp+1);4196}4197}41984199GETLINE;4200if(!strstr(line,"$EndPhysicalNames")) {4201printf("$PhysicalNames section should end to string $EndPhysicalNames:\n%s\n",line);4202}4203}4204else {4205if(!allocated) printf("Untreated command: %s",line);4206}42074208}42094210end:421142124213if(!allocated) {4214maxnodes = maxelemtype % 100;4215InitializeKnots(data);4216data->dim = dim;4217data->maxnodes = maxnodes;4218data->noelements = noelements;4219data->noknots = noknots;42204221if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);4222AllocateKnots(data);42234224if(maxindx > noknots) {4225revindx = Ivector(1,maxindx);4226for(i=1;i<=maxindx;i++) revindx[i] = 0;4227}4228rewind(in);4229allocated = TRUE;4230goto omstart;4231}42324233if(maxindx > noknots) {4234printf("Renumbering the Gmsh nodes from %d to %d\n",maxindx,noknots);42354236for(i=1; i <= noelements; i++) {4237elementtype = data->elementtypes[i];4238elemnodes = elementtype % 100;42394240for(j=0;j<elemnodes;j++) {4241k = data->topology[i][j];4242if(k <= 0 || k > maxindx)4243printf("index out of bounds %d\n",k);4244else if(revindx[k] <= 0)4245printf("unknown node %d %d in element %d\n",k,revindx[k],i);4246else4247data->topology[i][j] = revindx[k];4248}4249}4250free_Ivector(revindx,1,maxindx);4251}42524253ElementsToBoundaryConditions(data,bound,keeporphans,info);42544255data->bodynamesexist = physvolexist;4256data->boundarynamesexist = physsurfexist;42574258if(info) printf("Successfully read the mesh from the Gmsh input file.\n");42594260return(0);4261}426242634264static int LoadGmshInput4(struct FemType *data,struct BoundaryType *bound,4265char *filename,int usetaggeom, int keeporphans, int info)4266{4267int noknots = 0,noelements = 0,nophysical = 0,maxnodes,dim,notags;4268int elemind[MAXNODESD2],elementtype;4269int i,j,k,l,allocated,*revindx=NULL,maxindx;4270int elemno, gmshtype, tagphys=0, tagpart, elemnodes,maxelemtype;4271int tagmat,verno;4272int physvolexist, physsurfexist,**tagmap,tagsize,maxtag[4];4273FILE *in;4274const char manifoldname[4][10] = {"point", "line", "surface", "volume"};4275char *cp,line[MAXLINESIZE],longline[LONGLINESIZE];42764277if ((in = fopen(filename,"r")) == NULL) {4278printf("LoadGmshInput4: The opening of the mesh file %s failed!\n",filename);4279return(1);4280}4281if(info) printf("Loading mesh in Gmsh format 4.0 from file %s\n",filename);42824283allocated = FALSE;4284dim = data->dim;4285maxnodes = 0;4286maxindx = 0;4287maxelemtype = 0;4288physvolexist = FALSE;4289physsurfexist = FALSE;4290usetaggeom = TRUE; /* The default */4291for(i=0;i<4;i++) maxtag[i] = 0;429242934294omstart:42954296for(;;) {4297if(Getrow(line,in,FALSE)) goto end;4298if(strstr(line,"$End")) continue;42994300if(strstr(line,"$MeshFormat")) {4301GETLINE;4302cp = line;4303verno = next_int(&cp);43044305if(verno != 4) {4306printf("Version number is not compatible with the parser: %d\n",verno);4307}43084309GETLINE;4310if(!strstr(line,"$EndMeshFormat")) {4311printf("$MeshFormat section should end to string $EndMeshFormat:\n%s\n",line);4312}4313}43144315else if(strstr(line,"$Nodes")) {4316int numEntityBlocks,tagEntity,dimEntity,parEntity,numNodes,ind;43174318GETLINE;4319cp = line;43204321numEntityBlocks = next_int(&cp);4322noknots = next_int(&cp);43234324if(allocated && info) printf("Reading %d nodes in %d blocks.\n",noknots,numEntityBlocks);43254326k = 0;43274328for(j=1; j <= numEntityBlocks; j++) {4329GETLINE;4330cp = line;43314332tagEntity = next_int(&cp);4333dimEntity = next_int(&cp);4334parEntity = next_int(&cp);4335numNodes = next_int(&cp);43364337for(i=1; i <= numNodes; i++) {4338GETLINE;4339cp = line;4340k += 1;43414342ind = next_int(&cp);4343if(allocated) {4344if(maxindx > noknots) revindx[ind] = k;4345data->x[k] = next_real(&cp);4346data->y[k] = next_real(&cp);4347if(dim > 2) data->z[k] = next_real(&cp);4348}4349else {4350maxindx = MAX(ind,maxindx);4351}4352}4353}4354GETLINE;43554356if(!strstr(line,"$EndNodes")) {4357printf("$Nodes section should end to string $EndNodes:\n%s\n",line);4358}4359}43604361else if(strstr(line,"$Entities")) {4362int numPoints, numCurves, numSurfaces, numVolumes, numEnt;4363int tag,tagdim,nophys,phystag;4364int nobound, idum;4365Real rdum;43664367usetaggeom = FALSE;43684369GETLINE;4370cp = line;4371numPoints = next_int(&cp);4372numCurves = next_int(&cp);4373numSurfaces = next_int(&cp);4374numVolumes = next_int(&cp);43754376if(allocated) {4377tagsize = 0;4378for(tagdim=0;tagdim<=3;tagdim++)4379tagsize = MAX( tagsize, maxtag[tagdim]);4380if( tagsize > 0 ) {4381tagmap = Imatrix(0,3,1,tagsize);4382for(i=0;i<=3;i++)4383for(j=1;j<=tagsize;j++)4384tagmap[i][j] = 0;4385}4386}43874388for(tagdim=0;tagdim<=3;tagdim++) {43894390if( tagdim == 0 )4391numEnt = numPoints;4392else if( tagdim == 1 )4393numEnt = numCurves;4394else if( tagdim == 2 )4395numEnt = numSurfaces;4396else if( tagdim == 3 )4397numEnt = numVolumes;43984399if(!allocated)4400maxtag[tagdim] = 0;4401else if( maxtag[tagdim] > 0 )4402printf("Tag range for %d %dDIM entities is [%d %d]\n",numEnt,tagdim,0,maxtag[tagdim]);44034404if(numEnt > 0 && !allocated) {4405printf("Reading %d entities in %dD\n",numEnt,tagdim);4406}44074408for(i=1; i <= numEnt; i++) {4409GETLONGLINE;44104411// if( i==1 ) printf("1st line of dim %d with %d entries: %s\n",tagdim,numEnt,line);44124413if( tagdim == 0 ) continue;44144415cp = longline;4416tag = next_int(&cp);44174418if(!allocated)4419maxtag[tagdim] = MAX( maxtag[tagdim], tag );44204421for(j=1;j<=6;j++) rdum = next_real(&cp);4422nophys = next_int(&cp);44234424phystag = 0;4425if( nophys > 0 ) phystag = next_int(&cp);44264427if(allocated) tagmap[tagdim][tag] = phystag;442844294430// The lines may be too long. So fill the string buffer until we get a newline.4431j = k = 0;4432for(;;) {4433for(l=0;l<LONGLINESIZE;l++) {4434if( longline[l] == '\n') {4435j = l;4436break;4437}4438}4439if(j) break;4440k += LONGLINESIZE;4441GETLONGLINE;4442}4443if( k > 0 && !allocated) printf("Entity line %d has length %d.\n",i,k+j);44444445//for(j=2;j<=nophys;j++)4446// idum = next_int(&cp);44474448//// if( tagdim == 0 ) continue;44494450//nobound = next_int(&cp);4451// for(j=1;j<=nobound;j++)4452// idum = next_int(&cp);4453}4454}44554456GETLONGLINE;4457if(!strstr(longline,"$EndEntities")) {4458printf("$Entities section should end to string $EndEntities:\n%s\n",longline);4459}4460}44614462else if(strstr(line,"$Elements")) {4463int numEntityBlocks, numElements, tagEntity, dimEntity, typeEle, NumElements;44644465GETLINE;4466cp = line;44674468k = 0;4469numEntityBlocks = next_int(&cp);4470noelements = next_int(&cp);44714472if(allocated) printf("Reading %d elements in %d blocks.\n",noelements,numEntityBlocks);447344744475for(j=1; j<= numEntityBlocks; j++ ) {44764477GETLINE;4478cp = line;44794480tagEntity = next_int(&cp);4481dimEntity = next_int(&cp);44824483typeEle = next_int(&cp);4484numElements = next_int(&cp);44854486elementtype = GmshToElmerType(typeEle);4487elemnodes = elementtype % 100;4488maxelemtype = MAX(maxelemtype,elementtype);44894490if( allocated && tagsize > 0 ) {4491printf("Reading %d elements with tag %d of type %d\n", numElements, tagEntity, elementtype);4492if( tagsize > 0 ) {4493if( tagmap[dimEntity][tagEntity] ) {4494printf("Mapping mesh tag %d to physical tag %d in %dDIM\n",tagEntity,tagmap[dimEntity][tagEntity],dimEntity);4495tagEntity = tagmap[dimEntity][tagEntity];4496}4497else {4498printf("Mesh tag %d is not associated to any physical tag!\n",tagEntity);4499}4500}4501}45024503for(i=1; i <= numElements; i++) {4504GETLINE;4505cp = line;45064507k += 1;45084509elemno = next_int(&cp);45104511if(allocated) {4512data->elementtypes[k] = elementtype;4513data->material[k] = tagEntity;4514for(l=0;l<elemnodes;l++)4515elemind[l] = next_int(&cp);45164517GmshToElmerIndx(elementtype,elemind);45184519for(l=0;l<elemnodes;l++)4520data->topology[k][l] = elemind[l];4521}4522}4523}45244525GETLINE;4526if(!strstr(line,"$EndElements")) {4527printf("$Elements section should end to string $EndElements:\n%s\n",line);4528}4529}45304531else if(strstr(line,"$PhysicalNames")) {4532int entdim;4533entdim = dim;4534GETLINE;4535cp = line;4536nophysical = next_int(&cp);4537for(i=0;i<nophysical;i++) {4538GETLINE;4539if(allocated) {4540cp = line;4541gmshtype = next_int(&cp);4542if(gmshtype < entdim-1) {4543printf("Assuming maximum entity dim to be %d\n",dim-1);4544entdim--;4545}4546tagphys = next_int(&cp);4547if(gmshtype == entdim-1) {4548physsurfexist = TRUE;4549if(tagphys < MAXBCS) {4550if(!data->boundaryname[tagphys]) data->boundaryname[tagphys] = Cvector(0,MAXNAMESIZE);4551sscanf(cp," \"%[^\"]\"",data->boundaryname[tagphys]);4552printf("Boundary name for physical group %d is: %s\n",tagphys,data->boundaryname[tagphys]);4553}4554else {4555printf("Index %d too high: ignoring physical %s %s",tagphys,manifoldname[gmshtype],cp+1);4556}4557}4558else if(gmshtype == entdim) {4559physvolexist = TRUE;4560if(tagphys < MAXBODIES) {4561if(!data->bodyname[tagphys]) data->bodyname[tagphys] = Cvector(0,MAXNAMESIZE);4562sscanf(cp," \"%[^\"]\"",data->bodyname[tagphys]);4563printf("Body name for physical group %d is: %s\n",tagphys,data->bodyname[tagphys]);4564}4565else {4566printf("Index %d too high: ignoring physical %s %s",tagphys,manifoldname[gmshtype],cp+1);4567}4568}4569else printf("Physical groups of dimension %d not supported in %d-dimensional mesh: "4570"ignoring group %d %s",gmshtype,dim,tagphys,cp+1);4571}4572}45734574GETLINE;4575if(!strstr(line,"$EndPhysicalNames")) {4576printf("$PhysicalNames section should end to string $EndPhysicalNames:\n%s\n",line);4577}4578}4579else if(strstr(line,"$Periodic")) {4580int numPeriodicLinks;4581if(allocated) printf("Reading periodic links but doing nothing with them!\n");45824583GETLINE;4584cp = line;4585numPeriodicLinks = next_int(&cp);4586for(i=1; i <= numPeriodicLinks; i++) {4587GETLINE;4588}4589GETLINE;4590if(!strstr(line,"$EndPeriodic")) {4591printf("$Periodic section should end to string $EndPeriodic:\n%s\n",line);4592}4593}45944595else if(strstr(line,"$PartitionedEntities")) {4596if(allocated) printf("Reading partitioned entities but doing nothing with them!\n");4597for(;;) {4598GETLINE;4599if(strstr(line,"$EndPartitionedEntities")) break;4600}4601}4602else if(strstr(line,"$NodeData")) {4603if(allocated) printf("Reading node data but doing nothing with them!\n");4604for(;;) {4605GETLINE;4606if(strstr(line,"$EndNodeData")) break;4607}4608}4609else if(strstr(line,"$ElementData")) {4610if(allocated) printf("Reading element data but doing nothing with them!\n");4611for(;;) {4612GETLINE;4613if(strstr(line,"$EndElementData")) break;4614}4615}4616else if(strstr(line,"$ElementNodeData")) {4617if(allocated) printf("Reading element node data but doing nothing with them!\n");4618for(;;) {4619GETLINE;4620if(strstr(line,"$EndElementNodeData")) break;4621}4622}4623else if(strstr(line,"$GhostElements")) {4624if(allocated) printf("Reading ghost elements data but doing nothing with them!\n");4625for(;;) {4626GETLINE;4627if(strstr(line,"$EndGhostElements")) break;4628}4629}4630else if(strstr(line,"$InterpolationScheme")) {4631if(allocated) printf("Reading interpolation scheme but doing nothing with them!\n");4632for(;;) {4633GETLINE;4634if(strstr(line,"$EndInterpolationScheme")) break;4635}4636}4637else {4638if(allocated) printf("Untreated command: %s",line);4639}46404641}46424643end:464446454646if(!allocated) {4647if( noelements == 0 ) bigerror("No elements to load in Gmsh file!");4648if( noknots == 0 ) bigerror("No nodes to load in Gmsh file!");46494650maxnodes = maxelemtype % 100;4651InitializeKnots(data);4652data->dim = dim;4653data->maxnodes = maxnodes;4654data->noelements = noelements;4655data->noknots = noknots;46564657if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);4658AllocateKnots(data);46594660if(maxindx > noknots) {4661revindx = Ivector(1,maxindx);4662for(i=1;i<=maxindx;i++) revindx[i] = 0;4663}4664rewind(in);4665allocated = TRUE;4666goto omstart;4667}46684669if(maxindx > noknots) {4670printf("Renumbering the Gmsh nodes from %d to %d\n",maxindx,noknots);46714672for(i=1; i <= noelements; i++) {4673elementtype = data->elementtypes[i];4674elemnodes = elementtype % 100;46754676for(j=0;j<elemnodes;j++) {4677k = data->topology[i][j];4678if(k <= 0 || k > maxindx)4679printf("index out of bounds %d\n",k);4680else if(revindx[k] <= 0)4681printf("unknown node %d %d in element %d\n",k,revindx[k],i);4682else4683data->topology[i][j] = revindx[k];4684}4685}4686free_Ivector(revindx,1,maxindx);4687}46884689ElementsToBoundaryConditions(data,bound,keeporphans,info);46904691data->bodynamesexist = physvolexist;4692data->boundarynamesexist = physsurfexist;46934694if( tagsize > 0 ) free_Imatrix(tagmap,0,3,1,tagsize);46954696if(info) printf("Successfully read the mesh from the Gmsh input file.\n");46974698return(0);4699}470047014702static int LoadGmshInput41(struct FemType *data,struct BoundaryType *bound,4703char *filename,int usetaggeom, int keeporphans, int gmshbinary, int info)4704{4705int noknots = 0,noelements = 0,nophysical = 0,maxnodes,dim,notags;4706int elemind[MAXNODESD2],elementtype;4707int i,j,k,l,allocated,*revindx=NULL,maxindx;4708int elemno, gmshtype, tagphys=0, tagpart, elemnodes,maxelemtype;4709int tagmat,verno,meshdim,tagdim,frcount;4710int physvolexist, physsurfexist,**tagmap,tagsize;4711int maxtag[4],mintag[4],maxreadtag[4],minreadtag[4];4712int maxphystag[4],minphystag[4],tagoffset[4],phystagoffset[4];4713FILE *in;4714const char manifoldname[4][10] = {"point", "line", "surface", "volume"};4715char *cp,line[MAXLINESIZE],longline[LONGLINESIZE];47164717if ((in = fopen(filename,"rb")) == NULL) {4718printf("The opening of the mesh file %s failed!\n",filename);4719return(1);4720}4721if(info) printf("Loading mesh in Gmsh format 4.1 from file %s\n",filename);47224723allocated = FALSE;4724dim = data->dim;4725meshdim = 0;4726maxnodes = 0;4727maxindx = 0;4728maxelemtype = 0;4729physvolexist = FALSE;4730physsurfexist = FALSE;4731usetaggeom = TRUE; /* The default */4732for(i=0;i<4;i++) {4733maxtag[i] = mintag[i] = -1;4734minreadtag[i] = maxreadtag[i] = -1;4735maxphystag[i] = minphystag[i] = -1;4736tagoffset[i] = phystagoffset[i] = 0;4737}47384739omstart:47404741if(allocated) printf("Leading element dimension is %d\n",meshdim);47424743for(;;) {4744if(Getrow(line,in,FALSE)) goto end;4745if(strstr(line,"$End")) continue;47464747if(strstr(line,"$MeshFormat")) {4748GETLINE;4749if(gmshbinary){4750int one;4751fread(&one, sizeof(int), 1, in);4752if(one != 1) {4753printf("Gmsh binary file needs to swap bytes, not implemented in ElmerGrid. Exiting!\n");4754bigerror("Gmsh binary file needs to swap bytes, not implemented in ElmerGrid. Exiting!");4755}4756GETLINE;4757}4758GETLINE;4759if(!strstr(line,"$EndMeshFormat"))4760printf("$MeshFormat section should end to string $EndMeshFormat:\n%s\n",line);4761}47624763else if(strstr(line,"$Nodes")) {4764int numEntityBlocks,tagEntity,dimEntity,parEntity,numNodes;4765int minNodeTag, maxNodeTag, parTag;4766size_t tagNode;47674768if(gmshbinary) {4769size_t inputData[4];4770frcount = fread(inputData, sizeof(size_t), 4, in);4771if(frcount != 4)4772printf("1 fread error, frcount = %d, not equal to %d\n",frcount,4);4773numEntityBlocks = (int) inputData[0];4774noknots = (int) inputData[1];4775minNodeTag = (int) inputData[2];4776maxNodeTag = (int) inputData[3];4777}4778else {4779GETLINE;4780cp = line;4781numEntityBlocks = next_int(&cp);4782noknots = next_int(&cp);4783minNodeTag = next_int(&cp);4784maxNodeTag = next_int(&cp);4785}4786if(allocated && info) printf("Reading %d nodes in %d blocks.\n",4787noknots,numEntityBlocks);47884789k = 0;47904791for(j=1; j <= numEntityBlocks; j++) {4792if(gmshbinary) {4793int inputData[3];4794size_t numNodesInBlock;4795frcount = fread(inputData, sizeof(int), 3, in);4796if(frcount != 3)4797printf("2 fread error, frcount = %d, not equal to %d\n",frcount,3);4798dimEntity = inputData[0];4799tagEntity = inputData[1];4800parTag = inputData[2];48014802frcount = fread(&numNodesInBlock, sizeof(size_t), 1, in);4803if(frcount != 1)4804printf("3 fread error, frcount = %d, not equal to %d\n",frcount,1);4805numNodes = (int) numNodesInBlock;4806}4807else {4808GETLINE;4809cp = line;4810dimEntity = next_int(&cp);4811tagEntity = next_int(&cp);4812parTag = next_int(&cp);4813numNodes = next_int(&cp);4814}48154816if( 0 && numNodes > 1 ) printf("Reading node block %d with %d nodes\n",j,numNodes);48174818for(i=1; i <= numNodes; i++) {4819if(gmshbinary) {4820frcount = fread(&tagNode, sizeof(size_t), 1, in);4821if(frcount != 1)4822printf("4 fread error, frcount = %d, not equal to %d\n",frcount,1);4823}4824else {4825GETLINE;4826cp = line;4827tagNode = next_int(&cp);4828}48294830if( 0 && numNodes > 1 ) printf("block %d node %d tagNode %lu %d\n",j,i,(unsigned long)tagNode,k+i);48314832if(allocated) {4833if(maxindx > noknots) revindx[tagNode] = k+i;4834}4835else {4836maxindx = MAX(tagNode,maxindx);4837}4838}48394840for(i=1; i <= numNodes; i++) {4841if(gmshbinary) {4842double inputData[3];4843frcount = fread(inputData, sizeof(double), 3, in);4844if(frcount != 3)4845printf("5 fread error, frcount = %d, not equal to %d\n",frcount,3);4846if(allocated) {4847data->x[k+i] = inputData[0];4848data->y[k+i] = inputData[1];4849data->z[k+i] = inputData[2];4850}4851}4852else {4853double x,y,z;4854GETLINE;4855cp = line;4856if(allocated) {4857data->x[k+i] = next_real(&cp);4858data->y[k+i] = next_real(&cp);4859data->z[k+i] = next_real(&cp);4860}4861}4862}4863k += numNodes;4864}4865if(gmshbinary) GETLINE;4866GETLINE;4867if(!strstr(line,"$EndNodes"))4868printf("$Nodes section should end to string $EndNodes:\n%s\n",line);4869}48704871else if(strstr(line,"$Entities")) {4872int numPoints, numCurves, numSurfaces, numVolumes, numEnt;4873int tag,phystag;4874size_t nophys,nobound;4875int idum;4876Real rdum;48774878usetaggeom = FALSE;48794880if(gmshbinary) {4881size_t data[4];4882frcount = fread(data, sizeof(size_t), 4, in);4883if(frcount != 4)4884printf("6 fread error, frcount = %d, not equal to %d\n",frcount,4);4885numPoints = (int) data[0];4886numCurves = (int) data[1];4887numSurfaces = (int) data[2];4888numVolumes = (int) data[3];4889}4890else {4891GETLINE;4892cp = line;4893numPoints = next_int(&cp);4894numCurves = next_int(&cp);4895numSurfaces = next_int(&cp);4896numVolumes = next_int(&cp);4897}48984899if(allocated) {4900tagsize = 0;4901for(tagdim=0; tagdim<=meshdim; tagdim++)4902tagsize = MAX( tagsize, maxtag[tagdim]);4903if(info) printf("Allocating lookup table for tags of size %d\n",tagsize);4904if( tagsize > 0 ) {4905tagmap = Imatrix(0,3,1,tagsize);4906for(i=0; i<=3; i++)4907for(j=1; j<=tagsize; j++)4908tagmap[i][j] = 0;4909}4910}4911for(tagdim=0; tagdim<=3; tagdim++) {49124913if( tagdim == 0 )4914numEnt = numPoints;4915else if( tagdim == 1 )4916numEnt = numCurves;4917else if( tagdim == 2 )4918numEnt = numSurfaces;4919else if( tagdim == 3 )4920numEnt = numVolumes;49214922if(allocated && numEnt > 0 ) {4923if( maxtag[tagdim] > 0 ) {4924if( mintag[tagdim] == -1 ) mintag[tagdim] = maxtag[tagdim];4925if( minphystag[tagdim] == -1) minphystag[tagdim] = maxphystag[tagdim];4926printf("Defined %d %dDIM entities with geometric tag range [%d %d]\n",4927numEnt,tagdim,mintag[tagdim],maxtag[tagdim]);4928if( maxphystag[tagdim] > 0 || maxreadtag[tagdim] > 0 ) {4929printf(" Physical given tag range is [%d %d]\n",minphystag[tagdim],maxphystag[tagdim]);4930if( maxreadtag[tagdim] != maxphystag[tagdim] || minreadtag[tagdim] != minphystag[tagdim]) {4931if(maxreadtag[tagdim] > 0 )4932printf(" Physical read tag range is [%d %d]\n",minreadtag[tagdim],maxreadtag[tagdim]);4933else4934printf(" No physical tags read for real!\n");4935if(0) smallerror("Physical names not used consistently!");4936}4937} else {4938if(0) printf("No physical tags defined, using geometric entities!\n");4939}49404941}4942if( tagdim > meshdim ) {4943printf("We have %d %dDIM tags that are beyond mesh dimension %d!\n",4944numEnt, tagdim, meshdim );4945}4946}49474948if(numEnt > 0 && !allocated) printf("Reading %d entities in %dD\n",numEnt,tagdim);49494950for(i=1; i <= numEnt; i++) {4951if(gmshbinary) {4952frcount = fread(&tag, sizeof(int), 1, in);4953if(frcount != 1)4954printf("7 fread error, frcount = %d, not equal to %d\n",frcount,1);49554956if(tagdim == 0) {4957double inputData3[3];4958// read away the bounding box data that we do not need for anything4959frcount = fread(&inputData3, sizeof(double), 3, in);4960if(frcount != 3)4961printf("8 fread error, frcount = %d, not equal to %d\n",frcount,3);4962frcount = fread(&nophys, sizeof(size_t), 1, in);4963if(frcount != 1)4964printf("9 fread error, frcount = %d, not equal to %d\n",frcount,1);4965if(nophys > 0) {4966fread(&phystag, sizeof(int), nophys, in);4967if(frcount != (int) nophys)4968printf("9 fread error, frcount = %d, not equal to %lu\n",4969frcount,(unsigned long) nophys);4970}4971} else {4972double inputData6[6];4973// read away the bounding box data that we do not need for anything4974frcount = fread(&inputData6, sizeof(double), 6, in);4975if(frcount != 6)4976printf("10 fread error, frcount = %d, not equal to %d\n",frcount,6);4977frcount = fread(&nophys, sizeof(size_t), 1, in);4978if(frcount != 1)4979printf("11 fread error, frcount = %d, not equal to %d\n",frcount,1);4980if(nophys > 0) {4981frcount = fread(&phystag, sizeof(int), nophys, in);4982if(frcount != (int) nophys)4983printf("12 fread error, frcount = %d, not equal to %lu\n",4984frcount,(unsigned long) nophys);4985}4986frcount = fread(&nobound, sizeof(size_t), 1, in);4987if(frcount != 1)4988printf("13 fread error, frcount = %d, not equal to %d\n",frcount,1);49894990int noboundint = (int) nobound;4991if(noboundint > 0) {4992for( k= 0; k < noboundint; k++) {4993frcount = fread(&idum, sizeof(int), 1, in);4994if(frcount != 1)4995printf("14 fread error, frcount = %d, not equal to %d\n",frcount,1);4996}4997}4998}4999// Read the first physical tag if there are any5000if( nophys > 0 ) {5001if(!allocated) {5002maxreadtag[tagdim] = MAX( maxreadtag[tagdim], phystag );5003if( minreadtag[tagdim] == -1 ) {5004minreadtag[tagdim] = phystag;5005}5006else {5007minreadtag[tagdim] = MIN( minreadtag[tagdim], phystag );5008}5009}5010else {5011tagmap[tagdim][tag] = phystag;5012}5013}5014}5015else {5016GETLONGLINE;5017// printf("%d line of dim %d with %d entries: %s\n",i,tagdim,numEnt,line);50185019//if( tagdim == 0 ) continue;50205021cp = longline;5022tag = next_int(&cp);50235024if(!allocated) {5025maxtag[tagdim] = MAX( maxtag[tagdim], tag );5026if( mintag[tagdim] == -1 ) {5027mintag[tagdim] = tag;5028}5029else {5030mintag[tagdim] = MIN( mintag[tagdim], tag );5031}5032}50335034// read away the bounding box data that we do not need for anything5035if(tagdim == 0)5036k = 3;5037else5038k = 6;5039for(j=1; j<=k; j++) rdum = next_real(&cp);50405041// Number of physical tags5042nophys = next_int(&cp);50435044// Read the first physical tag if there are any5045if( nophys > 0 ) {5046if(0) printf("Reading number of physical tags: %lu\n",(unsigned long) nophys);5047phystag = next_int(&cp);5048if(!allocated) {5049if(0) printf("Phystag: %d %d %d %d\n",tagdim,tag,i,phystag);5050maxreadtag[tagdim] = MAX( maxreadtag[tagdim], phystag );5051if( minreadtag[tagdim] == -1 ) {5052minreadtag[tagdim] = phystag;5053}5054else {5055minreadtag[tagdim] = MIN( minreadtag[tagdim], phystag );5056}5057}5058else {5059tagmap[tagdim][tag] = phystag;5060}5061}5062}50635064if(!allocated) {5065maxtag[tagdim] = MAX( maxtag[tagdim], tag );5066if( mintag[tagdim] == -1 ) {5067mintag[tagdim] = tag;5068}5069else {5070mintag[tagdim] = MIN( mintag[tagdim], tag );5071}5072}5073if(!gmshbinary) {5074// The lines may be too long. So fill the string buffer until we get a newline.5075j = k = 0;5076for(;;) {5077for(l=0; l<LONGLINESIZE; l++) {5078if( longline[l] == '\n') {5079j = l;5080break;5081}5082}5083if(j) break;5084k += LONGLINESIZE;5085GETLONGLINE;5086printf("extra getlongline: %s\n",longline);5087fflush(stdout);5088}5089if( k > 0 && !allocated) printf("Entity line %d has length %d.\n",i,k+j);5090}5091}5092}50935094for(tagdim=meshdim-2;tagdim>=0;tagdim--) {5095phystagoffset[tagdim] = phystagoffset[tagdim+1]+MAX(0,maxphystag[tagdim+1]);5096printf("Physical tag offset for %dD is %d\n",tagdim,phystagoffset[tagdim]);5097}50985099if(meshdim>0) {5100tagoffset[meshdim] = maxphystag[meshdim];5101tagoffset[meshdim-1] = phystagoffset[0];5102}5103for(tagdim=meshdim-2;tagdim>=0;tagdim--) {5104tagoffset[tagdim] = tagoffset[tagdim+1]+MAX(0,maxtag[tagdim+1]);5105printf("Geometric tag offset for %dD is %d\n",tagdim,tagoffset[tagdim]);5106}51075108if(gmshbinary) GETLONGLINE;5109GETLONGLINE;5110if(!strstr(longline,"$EndEntities"))5111printf("$Entities section should end to string $EndEntities:\n%s\n",longline);5112}51135114else if(strstr(line,"$Elements")) {5115size_t numEntityBlocks, minElementTag, maxElementTag;5116size_t numElementsInBlock;5117int dimEntity, tagEntity, typeEle, numElements;51185119k = 0;51205121if(gmshbinary) {5122size_t data[4], totalNumElements;5123frcount = fread(data, sizeof(size_t), 4, in);5124if(frcount != 4)5125printf("17 fread error, frcount = %d, not equal to %d\n",frcount,4);5126numEntityBlocks = data[0];5127totalNumElements = data[1];5128noelements = (int) totalNumElements;5129minElementTag = data[2];5130maxElementTag = data[3];5131}5132else {5133GETLINE;5134cp = line;5135numEntityBlocks = next_int(&cp);5136noelements = next_int(&cp);5137minElementTag = next_int(&cp);5138maxElementTag = next_int(&cp);5139}51405141if(allocated) printf("Reading %d elements in %lu blocks.\n",noelements,(unsigned long) numEntityBlocks);51425143for(j=1; j<= (int) numEntityBlocks; j++ ) {51445145if(gmshbinary) {5146int data[3];5147frcount = fread(data, sizeof(int), 3, in);5148if(frcount != 3)5149printf("18 fread error, frcount = %d, not equal to %d\n",frcount,3);5150dimEntity = data[0];5151tagEntity = data[1];5152typeEle = data[2];5153frcount = fread(&numElementsInBlock, sizeof(size_t), 1, in);5154if(frcount != 1)5155printf("19 fread error, frcount = %d, not equal to %d\n",frcount,1);5156numElements = (int) numElementsInBlock;5157}5158else {5159GETLINE;5160cp = line;5161dimEntity = next_int(&cp);5162tagEntity = next_int(&cp);5163typeEle = next_int(&cp);5164numElements = next_int(&cp);5165}51665167elementtype = GmshToElmerType(typeEle);5168if(!elementtype)5169bigerror("Gmsh element type does not have an Elmer counterpart!\n");5170elemnodes = elementtype % 100;5171maxelemtype = MAX(maxelemtype,elementtype);51725173if(!allocated) meshdim = MAX(meshdim, GetElementDimension(elementtype));51745175if( allocated ) {5176if( tagsize > 0 ) {5177if( tagmap[dimEntity][tagEntity] ) {5178printf("Mapping mesh tag %d to physical tag %d in %dDIM\n",5179tagEntity,tagmap[dimEntity][tagEntity],dimEntity);5180tagEntity = tagmap[dimEntity][tagEntity] + phystagoffset[dimEntity];5181}5182else {5183tagEntity += tagoffset[dimEntity];5184}5185}5186else {5187tagEntity += tagoffset[dimEntity];5188}5189}51905191size_t elementTag, nodeTag[126];5192// nodeTag size is based on gmsh element type 93, 125-node fourth order hexahedron5193// if newer and larger elements are added, then increase nodeTag size to match5194if(elemnodes > 125) {5195printf("error: number of nodes per element of %d, exceeds 125\n",elemnodes);5196printf("increase size of nodeTag and recompile. Exiting!\n");5197bigerror("number of nodes per element exceeds 125. Exiting!");5198}51995200for(int m=1; m <= numElements; m++) {5201if(gmshbinary) {5202frcount = fread(&elementTag, sizeof(size_t), 1, in);5203if(frcount != 1)5204printf("20 fread error, frcount = %d, not equal to %d\n",frcount,1);5205elemno = (int) elementTag;52065207k += 1;52085209if(allocated) {5210data->elementtypes[k] = elementtype;5211data->material[k] = tagEntity;5212frcount = fread(nodeTag, sizeof(size_t), elemnodes, in);5213if(frcount != elemnodes)5214printf("21 fread error, frcount = %d, not equal to %d\n",frcount,elemnodes);52155216for(l=0; l<elemnodes; l++){5217elemind[l] = (int) nodeTag[l];5218}52195220GmshToElmerIndx(elementtype,elemind);52215222for(l=0; l<elemnodes; l++)5223data->topology[k][l] = elemind[l];5224}5225else {5226frcount = fread(nodeTag, sizeof(size_t), elemnodes, in);5227if(frcount != elemnodes)5228printf("22 fread error, frcount = %d, not equal to %d\n",frcount,elemnodes);5229}5230}5231else {5232GETLINE;5233cp = line;5234elemno = next_int(&cp);52355236k += 1;52375238if(allocated) {5239data->elementtypes[k] = elementtype;5240data->material[k] = tagEntity;5241for(l=0; l<elemnodes; l++)5242elemind[l] = next_int(&cp);52435244GmshToElmerIndx(elementtype,elemind);52455246for(l=0; l<elemnodes; l++)5247data->topology[k][l] = elemind[l];5248}5249}5250}5251}52525253if(gmshbinary) GETLINE;5254GETLINE;5255if(!strstr(line,"$EndElements"))5256printf("$Elements section should end to string $EndElements:\n%s\n",line);5257}52585259else if(strstr(line,"$PhysicalNames")) {5260int entdim;5261entdim = dim;52625263GETLINE;5264cp = line;5265nophysical = next_int(&cp);5266for(i=0; i<nophysical; i++) {5267GETLINE;5268cp = line;5269tagdim = next_int(&cp);5270tagphys = next_int(&cp);52715272if(!allocated) {5273maxphystag[tagdim] = MAX( maxphystag[tagdim], tagphys );5274if( minphystag[tagdim] == -1 ) {5275minphystag[tagdim] = tagphys;5276}5277else {5278minphystag[tagdim] = MIN( minphystag[tagdim], tagphys );5279}5280}5281else if(allocated) {5282// We must not let different tags be overrun5283l = phystagoffset[tagdim];52845285if(tagdim < meshdim) {5286physsurfexist = TRUE;5287if(tagphys+l < MAXBCS) {5288data->boundarynamesexist = TRUE;5289if(!data->boundaryname[tagphys+l]) data->boundaryname[tagphys+l] = Cvector(0,MAXNAMESIZE);5290sscanf(cp," \"%[^\"]\"",data->boundaryname[tagphys+l]);5291printf("BC name for physical group %d is: %s\n",tagphys,data->boundaryname[tagphys+l]);5292}5293else {5294printf("Index %d too high: ignoring physical %s %s",tagphys,manifoldname[tagdim],cp+1);5295}5296}5297else if(tagdim == meshdim) {5298physvolexist = TRUE;5299if(tagphys < MAXBODIES) {5300data->bodynamesexist = TRUE;5301if(!data->bodyname[tagphys]) data->bodyname[tagphys] = Cvector(0,MAXNAMESIZE);5302sscanf(cp," \"%[^\"]\"",data->bodyname[tagphys]);5303printf("Body name for physical group %d is: %s\n",tagphys,data->bodyname[tagphys]);5304}5305else {5306printf("Index %d too large: ignoring physical %s %s",tagphys,manifoldname[tagdim],cp+1);5307}5308}5309}5310}53115312GETLINE;5313if(!strstr(line,"$EndPhysicalNames"))5314printf("$PhysicalNames section should end to string $EndPhysicalNames:\n%s\n",line);5315}5316else if(strstr(line,"$Periodic")) {5317int numPeriodicLinks;5318if(allocated) printf("Reading periodic links but doing nothing with them!\n");53195320if(1) {5321numPeriodicLinks = 0;5322for(;;) {5323GETLINE;5324if(strstr(line,"$EndPeriodic")) {5325if(allocated) printf("Number of lines for periodic stuff: %d\n",numPeriodicLinks);5326break;5327}5328numPeriodicLinks++;5329}5330}5331else {5332GETLINE;5333cp = line;5334numPeriodicLinks = next_int(&cp);5335for(i=1; i <= numPeriodicLinks; i++) {5336GETLINE;5337}5338GETLINE;5339if(!strstr(line,"$EndPeriodic")) {5340printf("$Periodic section should end to string $EndPeriodic:\n%s\n",line);5341}5342}5343}53445345else if(strstr(line,"$PartitionedEntities")) {5346if(allocated) printf("Reading partitioned entities but doing nothing with them!\n");5347for(;;) {5348GETLINE;5349if(strstr(line,"$EndPartitionedEntities")) break;5350}5351}5352else if(strstr(line,"$NodeData")) {5353if(allocated) printf("Reading node data but doing nothing with them!\n");5354for(;;) {5355GETLINE;5356if(strstr(line,"$EndNodeData")) break;5357}5358}5359else if(strstr(line,"$ElementData")) {5360if(allocated) printf("Reading element data but doing nothing with them!\n");5361for(;;) {5362GETLINE;5363if(strstr(line,"$EndElementData")) break;5364}5365}5366else if(strstr(line,"$ElementNodeData")) {5367if(allocated) printf("Reading element node data but doing nothing with them!\n");5368for(;;) {5369GETLINE;5370if(strstr(line,"$EndElementNodeData")) break;5371}5372}5373else if(strstr(line,"$GhostElements")) {5374if(allocated) printf("Reading ghost elements data but doing nothing with them!\n");5375for(;;){5376GETLINE;5377if(strstr(line,"$EndGhostElements")) break;5378}5379}5380else if(strstr(line,"$InterpolationScheme")) {5381if(allocated) printf("Reading interpolation scheme but doing nothing with them!\n");5382for(;;) {5383GETLINE;5384if(strstr(line,"$EndInterpolationScheme")) break;5385}5386}5387else {5388if(allocated) printf("Untreated command: %s",line);5389}5390}53915392end:539353945395if(!allocated) {5396if( noelements == 0 ) bigerror("No elements to load in Gmsh file!");5397if( noknots == 0 ) bigerror("No nodes to load in Gmsh file!");53985399maxnodes = maxelemtype % 100;5400InitializeKnots(data);5401data->dim = dim;5402data->maxnodes = maxnodes;5403data->noelements = noelements;5404data->noknots = noknots;54055406if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);5407AllocateKnots(data);54085409if(maxindx > noknots) {5410revindx = Ivector(1,maxindx);5411for(i=1;i<=maxindx;i++) revindx[i] = 0;5412}5413rewind(in);5414allocated = TRUE;5415goto omstart;5416}54175418if(maxindx > noknots) {5419printf("Renumbering the Gmsh nodes from %d to %d\n",maxindx,noknots);54205421for(i=1; i <= noelements; i++) {5422elementtype = data->elementtypes[i];5423elemnodes = elementtype % 100;54245425for(j=0; j<elemnodes; j++) {5426k = data->topology[i][j];5427if(k <= 0 || k > maxindx)5428printf("index out of bounds %d\n",k);5429else if(revindx[k] <= 0)5430printf("unknown node %d %d in element %d\n",k,revindx[k],i);5431else5432data->topology[i][j] = revindx[k];5433}5434}5435free_Ivector(revindx,1,maxindx);5436}54375438ElementsToBoundaryConditions(data,bound,keeporphans,info);54395440data->bodynamesexist = physvolexist;5441data->boundarynamesexist = physsurfexist;54425443if( tagsize > 0 ) free_Imatrix(tagmap,0,3,1,tagsize);54445445if(info) printf("Successfully read the mesh from the Gmsh input file %s\n",filename);54465447return(0);5448}54495450int LoadGmshInput(struct FemType *data,struct BoundaryType *bound,5451char *prefix,int keeporphans,int dim,int info)5452{5453FILE *in;5454char line[MAXLINESIZE],filename[MAXFILESIZE];5455int errnum,usetaggeom,i;54565457/* keeprophans - Should we keep lower order elements not associated to any5458higher order entity? ElmerGUI certainly does not like it. */54595460sprintf(filename,"%s",prefix);5461if ((in = fopen(filename,"r")) == NULL) {5462sprintf(filename,"%s.msh",prefix);5463if ((in = fopen(filename,"r")) == NULL) {5464printf("LoadGmshInput: The opening of the mesh file %s failed!\n",filename);5465return(1);5466}5467}54685469Getrow(line,in,FALSE);54705471if(info) printf("Format chosen using the first line: %s",line);54725473if(strstr(line,"$MeshFormat")) {5474// gmsh uses floating point for the version number, so let's also use floating point.5475// using the gmsh method with a double, actually works better and5476// is able to detect types 1 and 3 formats.5477double gmshversion;5478int gmshbinary,gmshsize;54795480Getrow(line,in,FALSE);5481fclose(in);54825483if(sscanf(line, "%lf %d %d", &gmshversion, &gmshbinary, &gmshsize) != 3) {5484printf("Gmsh input line: %s, expected but didn't receive three items on line. Exiting!\n",line);5485printf("Input line: %s\n",line);5486bigerror("Gmsh input line didn't receive the expected three items!");5487}54885489// gmshversion is a float, hence the ugly decimal points to insure proper comparisons5490if(gmshversion < 2.99) {5491if(gmshbinary) {5492printf("Gmsh input file format is type %5.1f, binary is not supported.\n",gmshversion);5493printf("If binary is needed, use Gmsh format 4.1 for output from Gmsh\n");5494bigerror("Gmsh input file in format 2.x, binary is not supported!");5495} else {5496printf("Gmsh input file format is type %5.1f in ASCII.\n",gmshversion);5497errnum = LoadGmshInput2(data,bound,filename,usetaggeom,keeporphans,info);5498}5499} else if(gmshversion < 3.99) {5500printf("Gmsh input file of format type %5.1f, is not supported. Exiting!\n",gmshversion);5501printf("Please use Gmsh 4 versions for output from Gmsh\n");5502bigerror("Gmsh input file format is not supported!");5503} else if(gmshversion < 4.09) {5504printf("Gmsh input file format is type %5.1f in ASCII.\n",gmshversion);5505errnum = LoadGmshInput4(data,bound,filename,usetaggeom,keeporphans,info);5506} else if(gmshversion < 5.0) {5507if(gmshbinary) {5508printf("Gmsh input file format is type %5.1f in binary.\n",gmshversion);5509} else {5510printf("Gmsh input file format is type %5.1f in ASCII.\n",gmshversion);5511}5512errnum = LoadGmshInput41(data,bound,filename,usetaggeom,keeporphans,gmshbinary,info);5513} else {5514printf("Gmsh input file of format type %5.1f, is not supported. Exiting!\n",gmshversion);5515printf("Please use Gmsh 4 versions for output from Gmsh\n");5516bigerror("Gmsh input file format is not supported!");5517}5518} else {5519printf("*****************************************************\n");5520printf("The first line did not start with $MeshFormat, assuming Gmsh 1 format\n");5521printf("This version of Gmsh format is no longer supported\n");5522printf("Please use Gmsh 4 versions for output from Gmsh\n");5523printf("*****************************************************\n");55245525errnum = LoadGmshInput1(data,bound,filename,info);5526}55275528if( info ) {5529if( usetaggeom )5530printf("Using geometric numbering of entities\n");5531else5532printf("Using physical numbering of entities\n");5533}55345535if(dim < 3)5536for(i=1;i<=data->noknots;i++) data->z[i] = 0.0;5537if(dim < 2)5538for(i=1;i<=data->noknots;i++) data->y[i] = 0.0;55395540return(errnum);5541}5542554355445545int LoadFvcomMesh(struct FemType *data,struct BoundaryType *bound,5546char *filename,int info)5547{5548int noknots = 0,noelements = 0,maxnodes,dim;5549int elemind[MAXNODESD2],elementtype;5550int i,j,k,allocated,*revindx=NULL,maxindx;5551int elemnodes,maxelemtype,elemtype0,bclines;5552int tagmat,bccount;5553int *bcinds,*bctags,nbc,nbc0,bc_id;5554FILE *in;5555char *cp,line[MAXLINESIZE];555655575558if ((in = fopen(filename,"r")) == NULL) {5559printf("LoadFVCOMInput: The opening of the FVCOM mesh file %s failed!\n",filename);5560return(1);5561}5562if(info) printf("Loading mesh in FVCOM format from file %s\n",filename);55635564allocated = FALSE;5565dim = 2;5566maxnodes = 0;5567maxindx = 0;5568maxelemtype = 303;55695570noelements = 0;5571bclines = 0;557255735574omstart:55755576noelements = 0;5577noknots = 0;5578nbc = 0;5579nbc0 = 1;5580bclines = 0;5581bccount = 0;55825583for(;;) {5584if(Getrow(line,in,FALSE)) goto end;5585if(line[0]=='\0') goto end;55865587if(memcmp(line,"E3T",3) == 0 ) {5588noelements += 1;5589if(allocated) {5590cp = line+4;5591i = next_int(&cp);5592if(i != noelements ) printf("Invalid element number: %d %d\n",noelements,i);55935594data->elementtypes[i] = 303;5595for(k=0;k<3;k++)5596data->topology[i][k] = next_int(&cp);5597data->material[i] = next_int(&cp);5598}5599}5600else if(memcmp(line,"ND",2) == 0 ) {5601noknots += 1;5602if(allocated) {5603cp = line+3;5604i = next_int(&cp);5605if(i != noknots ) printf("Invalid node number: %d %d\n",noknots,i);5606data->x[i] = next_real(&cp);5607data->y[i] = next_real(&cp);5608if(dim > 2) data->z[i] = next_real(&cp);5609}5610}5611else if(memcmp(line,"NS",2) == 0 ) {5612bclines += 1;56135614if(allocated){5615cp = line+3;56165617for(i=0;i<10;i++) {5618j = next_int(&cp);56195620nbc += 1;5621bcinds[nbc] = abs(j);56225623if( j < 0 ) {5624bccount += 1;5625bc_id = next_int(&cp);56265627for(k=nbc0;k<=nbc;k++)5628bctags[k] = bc_id;56295630nbc0 = nbc+1;5631break;5632}5633}5634}5635}5636else if(memcmp(line,"MESH2D",6) == 0 ) {5637if(!allocated) printf("Yes, we have MESH2D as we should\n");5638}5639else if(memcmp(line,"MESHNAME",8) == 0 ) {5640if(!allocated) printf("Mesh name found but not used: %s\n",line+9);5641}5642}56435644end:564556465647if(!allocated) {5648maxnodes = maxelemtype % 100;5649InitializeKnots(data);5650data->dim = dim;5651data->maxnodes = maxnodes;5652data->noelements = noelements;5653data->noknots = noknots;56545655if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);5656AllocateKnots(data);56575658printf("Number of BC lines: %d\n",bclines);5659bcinds = Ivector(1,10*bclines);5660bctags = Ivector(1,10*bclines);5661for(i=1;i<=10*bclines;i++) bcinds[i] = bctags[i] = 0;56625663rewind(in);5664allocated = TRUE;5665goto omstart;5666}56675668printf("Number of different BCs: %d\n",bccount);5669printf("Number of BC nodes: %d\n",nbc);56705671NodesToBoundaryChain(data,bound,bcinds,bctags,nbc,bccount,info);56725673free_Ivector(bcinds,1,10*bclines);5674free_Ivector(bctags,1,10*bclines);56755676if(info) printf("Successfully read the mesh from the FVCOM file!\n");56775678return(0);5679}568056815682int LoadGeoInput(struct FemType *data,struct BoundaryType *bound,5683char *filename,int info)5684{5685int noknots = 0,noelements = 0,maxnodes,dim;5686int elemind[MAXNODESD2],elementtype;5687int i,j,k,allocated,*revindx=NULL,maxindx;5688int elemnodes,maxelemtype,elemtype0;5689int tagmat;5690FILE *in;5691char *cp,line[MAXLINESIZE];569256935694if ((in = fopen(filename,"r")) == NULL) {5695printf("LoadGeoInput: The opening of the mesh file %s failed!\n",filename);5696return(1);5697}5698if(info) printf("Loading mesh in geo format from file %s\n",filename);56995700allocated = FALSE;5701dim = 3;5702maxnodes = 0;5703maxindx = 0;5704maxelemtype = 0;57055706omstart:570757085709for(;;) {5710if(Getrow(line,in,FALSE)) goto end;5711if(line[0]=='\0') goto end;5712if(strstr(line,"$End")) continue;57135714if(strstr(line,"TYPES")) {5715if(!strstr(line,"ALL=TET04")) {5716printf("Only all tets implemented at the moment!\n");5717return(1);5718}5719elemtype0 = 504;5720GETLINE;5721}5722else if(strstr(line,"COORDINATES")) {5723i = 0;5724for(;;) {5725GETLINE;5726if( strstr(line,"END_COORDINATES")) break;5727cp = line;5728j = next_int(&cp);5729i = i + 1;5730if(allocated) {5731if(maxindx > noknots) revindx[j] = i;5732data->x[i] = next_real(&cp);5733data->y[i] = next_real(&cp);5734if(dim > 2) data->z[i] = next_real(&cp);5735}5736else {5737maxindx = MAX(j,maxindx);5738}5739}5740noknots = i;5741}5742else if(strstr(line,"ELEMENTS")) {5743i = 0;5744elementtype = elemtype0;5745tagmat = 1;57465747for(;;) {5748GETLINE;5749if( strstr(line,"END_ELEMENTS")) break;5750cp = line;5751j = next_int(&cp);5752i = i + 1;57535754if(allocated) {5755elemnodes = elementtype % 100;5756data->elementtypes[i] = elementtype;5757data->material[i] = tagmat;5758for(k=0;k<elemnodes;k++)5759elemind[k] = next_int(&cp);5760for(k=0;k<elemnodes;k++)5761data->topology[i][k] = elemind[k];5762}5763else {5764maxelemtype = MAX(maxelemtype,elementtype);5765}5766}5767noelements = i;5768}5769else if ( strstr(line,"BOUNDARIES")) {5770for(;;) {5771GETLINE;5772if( strstr(line,"END_BOUNDARIES")) break;57735774printf("Implement boundaries!\n");5775}5776}5777}57785779end:578057815782if(!allocated) {5783maxnodes = maxelemtype % 100;5784InitializeKnots(data);5785data->dim = dim;5786data->maxnodes = maxnodes;5787data->noelements = noelements;5788data->noknots = noknots;57895790if(info) printf("Allocating for %d knots and %d elements.\n",noknots,noelements);5791AllocateKnots(data);57925793if(maxindx > noknots) {5794revindx = Ivector(1,maxindx);5795for(i=1;i<=maxindx;i++) revindx[i] = 0;5796}5797rewind(in);5798allocated = TRUE;5799goto omstart;5800}58015802if(maxindx > noknots) {5803printf("Renumbering the Geo nodes from %d to %d\n",maxindx,noknots);58045805for(i=1; i <= noelements; i++) {5806elementtype = data->elementtypes[i];5807elemnodes = elementtype % 100;58085809for(j=0;j<elemnodes;j++) {5810k = data->topology[i][j];5811if(k <= 0 || k > maxindx)5812printf("index out of bounds %d\n",k);5813else if(revindx[k] <= 0)5814printf("unknown node %d %d in element %d\n",k,revindx[k],i);5815else5816data->topology[i][j] = revindx[k];5817}5818}5819free_Ivector(revindx,1,maxindx);5820}58215822if(0) ElementsToBoundaryConditions(data,bound,FALSE,info);58235824if(info) printf("Successfully read the mesh from the Geo input file.\n");58255826return(0);5827}582858295830/* Mapping between the element type of Universal file format and5831ElmerSolver element type. */5832static int UnvToElmerType(int unvtype)5833{5834int elmertype;58355836switch (unvtype) {58375838case 11:5839case 21:5840elmertype = 202;5841break;58425843case 22:5844case 23:5845case 24:5846elmertype = 203;5847break;58485849case 41:5850case 51:5851case 61:5852case 74:5853case 81:5854case 91:5855elmertype = 303;5856break;58575858case 42:5859case 52:5860case 62:5861case 72:5862case 82:5863case 92:5864elmertype = 306;5865break;58665867case 43:5868case 53:5869case 63:5870case 73:5871case 93:5872elmertype = 310;5873break;58745875case 44:5876case 54:5877case 64:5878case 71:5879case 84:5880case 94:5881elmertype = 404;5882break;58835884case 45:5885case 46:5886case 56:5887case 66:5888case 76:5889case 96:5890elmertype = 408;5891break;58925893case 111:5894elmertype = 504;5895break;58965897case 118:5898elmertype = 510;5899break;59005901case 101:5902case 112:5903elmertype = 706;5904break;59055906case 102:5907case 113:5908elmertype = 715;5909break;59105911case 104:5912case 115:5913elmertype = 808;5914break;59155916case 105:5917case 116:5918elmertype = 820;5919break;59205921default:5922elmertype = 0;5923if(0) printf("Unknown elementtype in universal mesh format: %d\n",unvtype);5924}59255926return(elmertype);5927}592859295930/* The Universal format supports something as "degenerated" elements.5931This means that the same node is given multiple times in the element5932topology */5933static int UnvRedundantIndexes(int nonodes,int *ind)5934{5935int i,j,redundant;59365937redundant = FALSE;5938for(i=0;i<nonodes;i++) {5939if( ind[i] == 0 ) redundant = TRUE;5940for(j=i+1;j<nonodes;j++)5941if(ind[i] == ind[j]) redundant = TRUE;5942}5943if( redundant ) {5944printf("Redundant element %d: ",nonodes);5945for(i=0;i<nonodes;i++)5946printf(" %d ",ind[i]);5947printf("\n");5948}59495950return(redundant);5951}595259535954/* Mapping between the elemental node order of Universal file format to5955Elmer file format. */5956static void UnvToElmerIndx(int elemtype,int *topology)5957{5958int i=0,nodes=0,oldtopology[MAXNODESD2];5959int reorder, *porder;59605961int order203[]={1,3,2};5962int order306[]={1,3,5,2,4,6};5963int order510[]={1,3,5,10,2,4,6,7,8,9};5964int order408[]={1,3,5,7,2,4,6,8};5965int order820[]={1,3,5,7,13,15,17,19,2,4,6,8,9,10,11,12,14,16,18,20};596659675968reorder = FALSE;59695970switch (elemtype) {59715972case 203:5973reorder = TRUE;5974porder = &order203[0];5975break;59765977case 306:5978reorder = TRUE;5979porder = &order306[0];5980break;59815982case 510:5983reorder = TRUE;5984porder = &order510[0];5985break;59865987case 408:5988reorder = TRUE;5989porder = &order408[0];5990break;59915992case 820:5993reorder = TRUE;5994porder = &order820[0];5995break;59965997}59985999if( reorder ) {6000nodes = elemtype % 100;6001for(i=0;i<nodes;i++)6002oldtopology[i] = topology[i];6003for(i=0;i<nodes;i++)6004topology[i] = oldtopology[porder[i]-1];6005}6006}60076008600960106011int LoadUniversalMesh(struct FemType *data,struct BoundaryType *bound,6012char *prefix,int info)6013/* Load the grid in universal file format. This format includes thousands of possible6014fields and hence the parser can never be exhaustive. Just the mostly common used6015fields in FE community are treated. */6016{6017int noknots,totknots,noelements,elemcode,maxnodes;6018int allocated,dim,ind,lines,groupset,goffset,poffset,noconf1,noconf2;6019int reordernodes,reorderelements,nogroups,maxnodeind,maxelem,elid,unvtype,elmertype;6020int nonodes,group,grouptype,mode,nopoints,nodeind,matind,physind,colorind;6021int minelemtype,maxelemtype,doscaling=FALSE;6022int debug,mingroup,maxgroup,minphys,maxphys,nogroup,noentities,dummy,isbeam;6023int *u2eind=NULL,*u2eelem=NULL;6024int *elementtypes,*physmap;6025char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;6026int i,j,k;6027char entityname[MAXNAMESIZE];6028Real scaling[4];6029FILE *in;603060316032strcpy(filename,prefix);6033if ((in = fopen(filename,"r")) == NULL) {6034AddExtension(prefix,filename,"unv");6035if ((in = fopen(filename,"r")) == NULL) {6036printf("LoadUniversalMesh: opening of the universal mesh file '%s' wasn't successful !\n",6037filename);6038return(1);6039}6040}60416042printf("Reading mesh from universal mesh file %s.\n",filename);6043InitializeKnots(data);60446045dim = 3;6046allocated = FALSE;6047reordernodes = FALSE;6048reorderelements = FALSE;60496050debug = FALSE;6051if( debug ){6052elementtypes = Ivector(0,820);6053for(i=0;i<=820;i++) elementtypes[i] = FALSE;6054}60556056maxnodeind = 0;6057maxnodes = 0;6058maxelem = 0;6059mingroup = INT_MAX;6060maxgroup = 0;6061minphys = INT_MAX;6062maxphys = 0;6063groupset = 0;6064goffset = 0;6065poffset = 0;6066noconf1 = 0;6067noconf2 = 0;60686069omstart:60706071/* this is a global variable in the module */6072linenumber = 0;60736074if(info) {6075if(allocated)6076printf("Second round for reading data\n");6077else6078printf("First round for allocating data\n");6079}60806081noknots = 0;6082noelements = 0;6083nogroups = 0;6084nopoints = 0;6085group = 0;6086mode = 0;608760886089for(;;) {60906091if(0) printf("line: %d %s\n",mode,line);60926093nextline:6094if( !strncmp(line," -1",6)) mode = 0;6095if( Getrow(line,in,FALSE)) {6096goto end;6097}6098if(line[0]=='\0') goto end;60996100if( !strncmp(line," -1",6)) mode = 0;6101else if( !strncmp(line," 2411",6)) mode = 2411;6102else if( !strncmp(line," 2412",6)) mode = 2412;6103else if( !strncmp(line," 2420",6)) mode = 2420;6104else if( !strncmp(line," 2467",6)) mode = 2467;6105else if( !strncmp(line," 2435",6)) mode = 2435;6106else if( !strncmp(line," 781",6)) mode = 781;6107else if( !strncmp(line," 780",6)) mode = 780;6108else if( !strncmp(line," 164",6)) mode = 164;6109else if( allocated && strncmp(line," ",6)) printf("Unknown mode line %d: %s",linenumber,line);611061116112if(debug && mode) printf("Current mode is %d\n",mode);61136114/* node definition */6115if( mode == 2411 || mode == 781 ) {6116if(allocated && info) printf("Reading node coordinates\n");6117for(;;) {6118GetrowDouble(line,in);6119if( !strncmp(line," -1",6)) {6120if(!allocated && info) printf("There are %d nodes in the mesh\n",noknots);6121goto nextline;6122}61236124cp = line;6125nodeind = next_int(&cp);6126/* Three other fields omitted: two coordinate systems and color */6127noknots += 1;6128GetrowDouble(line,in);61296130if(allocated) {6131if(reordernodes) {6132if(u2eind[nodeind])6133printf("Reordering node %d already set (%d vs. %d)\n",6134nodeind,u2eind[nodeind],noknots);6135else6136u2eind[nodeind] = noknots;6137}61386139cp = line;6140data->x[noknots] = next_real(&cp);6141data->y[noknots] = next_real(&cp);6142data->z[noknots] = next_real(&cp);6143}6144else {6145if(nodeind != noknots) reordernodes = TRUE;6146maxnodeind = MAX(maxnodeind,nodeind);6147}6148}6149}61506151if( mode == 2412 ) {6152minelemtype = INT_MAX;6153maxelemtype = 0;61546155if(allocated && info) printf("Reading element topologies\n");6156for(;;) {6157Getrow(line,in,FALSE);6158if( strstr(line,"-1")) {6159if(info && !allocated) printf("Element type range in mesh [%d,%d]\n",minelemtype,maxelemtype);6160goto nextline;6161}61626163noelements += 1;6164cp = line;6165elid = next_int(&cp);6166unvtype = next_int(&cp);6167physind = next_int(&cp);6168matind = next_int(&cp);6169colorind = next_int(&cp);6170nonodes = next_int(&cp);61716172if(!allocated ) {6173if(0) printf("elem = %d %d %d %d\n",noelements,unvtype,physind,matind);6174}61756176elmertype = UnvToElmerType(unvtype);6177if(!elmertype) {6178printf("Unknown elementtype %d %d %d %d %d %d %d\n",6179noelements,elid,unvtype,physind,matind,colorind,nonodes);6180printf("line %d: %s\n",linenumber,line);6181bigerror("done");6182}61836184if (!allocated) {6185minphys = MIN( minphys, physind );6186maxphys = MAX( maxphys, physind );6187maxnodes = MAX(maxnodes, nonodes);6188if(elid != noelements) reorderelements = TRUE;6189maxelem = MAX(maxelem, elid);6190}6191else {6192physind += poffset;6193}61946195/* For beam elements there is a stupid additional row filled with zeros? */6196isbeam = ( elmertype / 100 == 2);6197if(isbeam)Getrow(line,in,FALSE);61986199Getrow(line,in,FALSE);6200cp = line;62016202if(elmertype == 510 )6203lines = 1;6204else if(elmertype == 820 )6205lines = 2;6206else6207lines = 0;62086209if(allocated) {6210if(reorderelements) u2eelem[elid] = noelements;62116212if(debug && !elementtypes[elmertype]) {6213elementtypes[elmertype] = TRUE;6214printf("new elementtype in elmer: %d (unv: %d)\n",elmertype,unvtype);6215}62166217if(elmertype % 100 != nonodes) {6218printf("nonodes = %d elemtype = %d elid = %d\n",nonodes,elmertype,elid);6219nonodes = elmertype % 100;6220}62216222data->elementtypes[noelements] = elmertype;6223for(i=0;i<nonodes;i++) {6224if( lines > 0 && i >= 8 ) {6225if( i%8 == 0 ) {6226Getrow(line,in,FALSE);6227cp = line;6228}6229}6230data->topology[noelements][i] = next_int(&cp);6231}62326233UnvRedundantIndexes(nonodes,data->topology[noelements]);62346235UnvToElmerIndx(elmertype,data->topology[noelements]);62366237/* should this be physical property or material property? */6238data->material[noelements] = physind;6239}6240else {6241minelemtype = MIN( minelemtype, elmertype );6242maxelemtype = MAX( maxelemtype, elmertype );6243for(i=1;i<=lines;i++) {6244Getrow(line,in,FALSE);6245}6246}6247}6248if(info) {6249printf("Element type range in whole mesh is [%d %d]\n",minelemtype,maxelemtype);6250}6251}62526253if( mode == 2420 ) {6254int partuid,coordlabel,coordtype;6255Real coeff;6256if(allocated && info) printf("Reading Coordinate system information\n");62576258Getrow(line,in,FALSE);6259if( !allocated ) {6260cp = line;6261partuid = next_int(&cp);6262printf("Part UID = %d\n",partuid);6263}6264Getrow(line,in,FALSE);6265if(!allocated ) {6266sscanf(line,"%s",entityname);6267printf("Part name = %s\n",entityname);6268}6269Getrow(line,in,FALSE);6270if( !allocated ) {6271cp = line;6272coordlabel = next_int(&cp);6273coordtype = next_int(&cp);6274if( coordtype != 0 ) {6275printf("Coordinate system is not cartesian: %d\n",coordtype);6276printf("Code some more if you want to consider this!\n");6277}6278}62796280Getrow(line,in,FALSE);6281if(!allocated ) {6282sscanf(line,"%s",entityname);6283printf("Coord system name = %s\n",entityname);6284}6285for(i=1;i<=4;i++) {6286Getrow(line,in,FALSE);6287if( !allocated ) {6288cp = line;6289if(!cp) printf("Problem reading line %d for coordinate system\n",i);6290for(j=1;j<= 3;j++) {6291coeff = next_real(&cp);6292if( i == j ) {6293scaling[i] = coeff;6294if( fabs(coeff) < 1.0e-20) {6295printf("Scaling for component %d too small %le\n",i,coeff);6296}6297else if( fabs(coeff-1.0) ) {6298doscaling = TRUE;6299printf("Scaling component %d by %le\n",i,coeff);6300}6301}6302else {6303if(fabs(coeff) > 1.0e-20 ) {6304printf("Transformation matrix is not diagonal %d%d: %e\n",i,j,coeff);6305smallerror("Code some more...");6306}6307}6308}6309}6310}6311Getrow(line,in,FALSE);6312if( strncmp(line," -1",6))6313printf("Field 2420 should already be ending: %s\n",line);6314goto nextline;6315}63166317if( mode == 780 ) {6318int physind2,matind2;6319maxelemtype = 0;6320minelemtype = 1000;63216322if(allocated && info) printf("Reading element groups in mode %d\n",mode);6323for(;;) {6324Getrow(line,in,FALSE);6325if( !strncmp(line," -1",6)) goto nextline;63266327noelements += 1;6328cp = line;6329elid = next_int(&cp);6330unvtype = next_int(&cp);63316332physind = next_int(&cp);6333physind2 = next_int(&cp);6334matind = next_int(&cp);6335matind2 = next_int(&cp);6336colorind = next_int(&cp);6337nonodes = next_int(&cp);63386339if (!allocated) {6340maxnodes = MAX(maxnodes, nonodes);6341if(elid != noelements) reorderelements = TRUE;6342maxelem = MAX(maxelem, elid);6343minphys = MIN( minphys, physind );6344maxphys = MAX( maxphys, physind );6345}6346else {6347physind += poffset;6348}634963506351if(unvtype == 11 || unvtype == 21) Getrow(line,in,FALSE);6352Getrow(line,in,FALSE);6353cp = line;6354if(allocated) {6355if(reorderelements) u2eelem[elid] = noelements;63566357elmertype = UnvToElmerType(unvtype);6358maxelemtype = MAX( maxelemtype, elmertype );6359minelemtype = MIN( minelemtype, elmertype );63606361if(debug && !elementtypes[elmertype]) {6362elementtypes[elmertype] = TRUE;6363printf("new elementtype in elmer: %d (unv: %d)\n",elmertype,unvtype);6364}63656366if(elmertype % 100 != nonodes) {6367printf("nonodes = %d elemtype = %d elid = %d\n",nonodes,elmertype,elid);6368nonodes = elmertype % 100;6369}63706371data->elementtypes[noelements] = elmertype;6372for(i=0;i<nonodes;i++)6373data->topology[noelements][i] = next_int(&cp);63746375UnvRedundantIndexes(nonodes,data->topology[noelements]);63766377UnvToElmerIndx(elmertype,data->topology[noelements]);63786379/* should this be physical property or material property? */6380data->material[noelements] = physind;6381}6382}6383}63846385if( mode == 2467 || mode == 2435) {6386if(allocated && info) printf("Reading element groups in mode %d\n",mode);63876388for(;;) {6389Getrow(line,in,FALSE);6390if( !strncmp(line," -1",6)) goto nextline;63916392cp = line;6393nogroup = next_int(&cp);6394maxelemtype = 0;6395minelemtype = 1000;6396for(i=1;i<=6;i++)6397dummy = next_int(&cp);6398noentities = next_int(&cp);63996400if(!allocated) {6401mingroup = MIN( mingroup, nogroup );6402maxgroup = MAX( maxgroup, nogroup );6403}6404else {6405nogroup += goffset;6406}64076408Getrow(line,in,FALSE);6409if( !strncmp(line," -1",6)) goto nextline;64106411/* Used for the empty group created by salome */6412/* if( mode == 2467 && !strncmp(line," ",12)) continue; */64136414group++;6415k = 0;6416if(allocated) {6417sscanf(line,"%s",entityname);6418if(!data->bodyname[nogroup]) data->bodyname[nogroup] = Cvector(0,MAXNAMESIZE);6419strcpy(data->bodyname[nogroup],entityname);6420data->bodynamesexist = TRUE;6421if(0) data->boundarynamesexist = TRUE;64226423if(info) printf("Reading %d:th group with index %d with %d entities: %s\n",6424group,nogroup,noentities,entityname);6425}6426if(noentities == 0) Getrow(line,in,FALSE);64276428for(i=0;i<noentities;i++) {6429if(i%2 == 0) {6430Getrow(line,in,FALSE);6431if( !strncmp(line," -1",6)) goto nextline;6432cp = line;6433}64346435grouptype = next_int(&cp);6436ind = next_int(&cp);6437dummy = next_int(&cp);6438dummy = next_int(&cp);64396440if(ind == 0) continue;64416442if( grouptype == 8 ) {6443if(allocated) {6444if(reorderelements) ind = u2eelem[ind];6445elemcode = data->elementtypes[ind];6446maxelemtype = MAX( maxelemtype, elemcode );6447minelemtype = MIN( minelemtype, elemcode );64486449if(data->material[ind] < 0 ) {6450if(data->material[ind] == -nogroup)6451noconf1++;6452else6453noconf2++;6454}64556456data->material[ind] = -nogroup;6457groupset++;6458}6459}6460else if(grouptype == 7) {6461nopoints += 1;64626463if(allocated) {6464elemcode = 101;6465if(data->material[noelements+nopoints] < 0 ) {6466if(data->material[noelements+nopoints] == -nogroup)6467noconf1++;6468else6469noconf2++;6470}64716472data->material[noelements+nopoints] = -nogroup;6473maxelemtype = MAX( maxelemtype, elemcode );6474minelemtype = MIN( minelemtype, elemcode );6475data->elementtypes[noelements+nopoints] = elemcode;6476data->topology[noelements+nopoints][0] = ind;6477groupset++;6478}6479}6480else {6481printf("unknown group type %d\n",grouptype);6482}6483}6484if(allocated && info) {6485printf("Element type range in group is [%d %d]\n",minelemtype,maxelemtype);6486}64876488}6489}64906491if( mode == 164 ) {6492if(!allocated) printf("Units dataset content is currently omitted!\n");6493for(;;) {6494Getrow(line,in,FALSE);6495if( !strncmp(line," -1",6))6496goto nextline;6497}6498}64996500}65016502end:65036504exit;6505if(0) printf("Done reading mesh\n");650665076508if(!allocated) {65096510if(reordernodes) {6511if(info) printf("Reordering %d nodes with indexes up to %d\n",noknots,maxnodeind);6512u2eind = Ivector(1,maxnodeind);6513for(i=1;i<=maxnodeind;i++) u2eind[i] = 0;6514}6515if(reorderelements) {6516if(info) printf("Reordering %d elements with indexes up to %d\n",noelements,maxelem);6517u2eelem = Ivector(1,maxelem);6518for(i=1;i<=maxelem;i++) u2eelem[i] = 0;6519}65206521if(noknots == 0 || noelements == 0 || maxnodes == 0) {6522printf("Invalid mesh consists of %d nodes and %d %d-node elements.\n",6523noknots,noelements,maxnodes);6524fclose(in);6525return(2);6526}65276528rewind(in);6529totknots = noknots;6530data->noknots = noknots;6531data->noelements = noelements + nopoints;6532data->maxnodes = maxnodes;6533data->dim = dim;65346535if(info) {6536printf("Allocating mesh with %d nodes and %d %d-node elements in %d dims.\n",6537noknots,noelements,maxnodes,dim);6538}6539AllocateKnots(data);6540allocated = TRUE;65416542/* Set an offset for physical indexes so that the defined groups and6543existing physical indexes won't mix confusingly */6544if(info) {6545printf("Physical index interval is [%d,%d]\n",minphys,maxphys);6546if( maxgroup ) printf("Group index interval is [%d,%d]\n",mingroup,maxgroup);6547}6548if(!mingroup) {6549printf("Applying group offset to 1!\n");6550goffset = 1;6551mingroup += 1;6552maxgroup += 1;6553}6554if(!minphys) {6555printf("Applying physical entity offset to 1!\n");6556poffset = 1;6557minphys += 1;6558maxphys += 1;6559}65606561goto omstart;6562}6563fclose(in);65646565if(noconf1) printf("Group given multiple times with same group: %d\n",noconf1);6566if(noconf2) printf("Group given multiple times but with different group index: %d\n",noconf2);65676568/* Rorder materials if there is an overlap between groups and physical entities, or6569if numbering uses also zero. */6570if( groupset) {6571int i1,i2,k2,ioffset;65726573if(info) printf("Group given for %d elements out of %d\n",groupset,noelements);6574i1=MIN(minphys,mingroup);6575i2=MAX(maxphys,maxgroup);65766577/* Give plenty of room for new indexes */6578i2=2*i2;65796580physmap = Ivector(i1,i2);6581for(i=i1;i<=i2;i++) physmap[i] = 0;65826583/* Give priority to group (negative index) */6584for(i=1;i<=data->noelements;i++) {6585j = data->material[i];6586if(j<0) physmap[-j] = -1;6587}6588/* Now check the physical index */6589for(i=1;i<=data->noelements;i++) {6590j = data->material[i];6591if(j>0) {6592if(physmap[j]==0) physmap[j] = -2;6593if(physmap[j]==-1) {6594if(info) printf("Physical index and group index collide: %d\n",j);6595physmap[j] = -3;6596}6597}6598}65996600for(i=i1;i<=i2;i++) {6601/* For tag -3 we need to find new index */6602if(physmap[i]==-3) {6603/* Find a free index and tag it with -4 when it has been used */6604for(j=i1;j<=i2;j++)6605if(!physmap[j]) break;6606physmap[i] = j;6607physmap[j] = -4;6608if(info) printf("Replacing physical index %d with free index %d\n",i,j);6609/* We may have some remnants that we remove since physical entity is not named */6610if(data->bodyname[j]) {6611printf("Removing name of an empty group: %s\n",data->bodyname[j]);6612free_Cvector(data->bodyname[j],0,MAXNAMESIZE);6613data->bodyname[j] = NULL;6614}6615}6616}6617/* Finally do the renumbering */6618k = 0;6619k2 = 0;6620for(i=1;i<=data->noelements;i++) {6621j = data->material[i];6622if(j<0)6623data->material[i] = -j;6624else {6625if(physmap[j] > 0) {6626data->material[i] = physmap[j];6627k2++;6628}6629else k++;6630}6631}6632if(k) printf("Using original physical entity index for %d elements\n",k);6633if(k2) printf("Using mapped physical entity index for %d elements\n",k2);66346635for(i=i1;i<=i2;i++) physmap[i] = 0;6636for(i=1;i<=data->noelements;i++)6637physmap[data->material[i]] += 1;6638for(i=i1;i<=i2;i++) {6639j = physmap[i];6640if(j) {6641if(data->bodyname[i])6642printf("Entity %d (%s) count is %d\n",i,data->bodyname[i],j);6643else6644printf("Entity %d count is %d\n",i,j);6645}6646}6647free_Ivector(physmap,i1,i2);6648}66496650/* Elmer likes that node indexes are given so that no integers are missed.6651If this is not the case we need to do renumbering of nodes. */6652if(reordernodes) {6653printf("Reordering nodes continuously\n");6654for(j=1;j<=noelements;j++)6655for(i=0;i<data->elementtypes[j]%100;i++)6656data->topology[j][i] = u2eind[data->topology[j][i]];6657free_Ivector(u2eind,1,maxnodeind);6658}6659if(reorderelements) {6660free_Ivector(u2eelem,1,maxelem);6661}66626663/* Do scaling if requested */6664if( doscaling ) {6665Real *coord;6666for(j=1;j<=3;j++) {6667if( j == 1 )6668coord = data->x;6669else if( j == 2 )6670coord = data->y;6671else6672coord = data->z;66736674if( fabs(scaling[j]-1.0) >= 1.0e-20 ) {6675for(i=1;i<=noknots;i++)6676coord[i] *= scaling[j];6677}6678}6679}66806681/* This is here for debugging of the nodal order */6682if(FALSE) for(j=1;j<=noelements;j++) {6683int elemtype = data->elementtypes[j];6684printf("element = %d\n",j);6685for(i=0;elemtype%100;i++) {6686k = data->topology[j][i];6687printf("node i=%d %.3le %.3le %.3le\n",i,data->x[k],data->z[k],data->y[k]);6688}6689}669066916692/* Until this far all elements have been listed as bulk elements.6693Now separate the lower dimensional elements to be boundary elements. */6694ElementsToBoundaryConditions(data,bound,TRUE,info);66956696if(info) printf("The Universal mesh was loaded from file %s.\n",filename);66976698return(0);6699}670067016702670367046705int LoadCGsimMesh(struct FemType *data,char *prefix,int info)6706/* Load the mesh from postprocessing format of CGsim */6707{6708int noknots,noelements,maxnodes,material,allocated,dim,debug,thismat,thisknots,thiselems;6709char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;6710int i,j,inds[MAXNODESD2],savedofs;6711Real dummyreal;6712FILE *in;671367146715strcpy(filename,prefix);6716if ((in = fopen(filename,"r")) == NULL) {6717AddExtension(prefix,filename,"plt");6718if ((in = fopen(filename,"r")) == NULL) {6719printf("LoadCGsimMesh: opening of the CGsim mesh file '%s' wasn't successful !\n",6720filename);6721return(1);6722}6723}67246725printf("Reading mesh from CGsim mesh file %s.\n",filename);6726InitializeKnots(data);67276728debug = FALSE;6729allocated = FALSE;6730savedofs = FALSE;67316732omstart:67336734maxnodes = 4;6735noknots = 0;6736noelements = 0;6737material = 0;6738dim = 2;6739thismat = 0;674067416742for(;;) {67436744if(Getrow(line,in,FALSE)) goto end;6745if(line[0]=='\0') goto end;67466747cp = strstr(line,"ZONE");6748if(!cp) continue;67496750thismat += 1;6751cp = strstr(line," N=");6752cp += 3;6753thisknots = next_int(&cp);67546755cp = strstr(line,",E=");6756cp += 3;6757thiselems = next_int(&cp);67586759if(debug) {6760printf("%s",line);6761printf("thismat = %d knots = %d elems = %d\n",thismat,thisknots,thiselems);6762}67636764for(i=1;i<=thisknots;i++) {6765GETLINE;67666767if(allocated) {6768cp = line;6769data->x[noknots+i] = next_real(&cp);6770data->y[noknots+i] = next_real(&cp);6771data->z[noknots+i] = 0.0;67726773if(savedofs == 1) {6774for(j=1;j<=4;j++)6775dummyreal = next_real(&cp);6776data->dofs[1][noknots+i] = next_real(&cp);6777}6778else if(savedofs == 5) {6779for(j=1;j<=5;j++)6780data->dofs[j][noknots+i] = next_real(&cp);6781}67826783}6784}67856786for(i=1;i<=thiselems;i++) {6787GETLINE;67886789if(allocated) {6790cp = line;6791for(j=0;j<4;j++)6792inds[j] = next_int(&cp);6793for(j=0;j<4;j++)6794data->topology[noelements+i][j] = inds[j]+noknots;6795if(inds[2] == inds[3])6796data->elementtypes[noelements+i] = 303;6797else6798data->elementtypes[noelements+i] = 404;6799data->material[noelements+i] = thismat;6800}6801}68026803noknots += thisknots;6804noelements += thiselems;6805}68066807end:68086809if(!allocated) {6810if(noknots == 0 || noelements == 0 || maxnodes == 0) {6811printf("Invalid mesh consists of %d knots and %d %d-node elements.\n",6812noknots,noelements,maxnodes);6813fclose(in);6814return(2);6815}68166817rewind(in);6818data->noknots = noknots;6819data->noelements = noelements;6820data->maxnodes = maxnodes;6821data->dim = dim;682268236824if(info) {6825printf("Allocating for %d knots and %d %d-node elements.\n",6826noknots,noelements,maxnodes);6827}6828AllocateKnots(data);68296830if(savedofs == 1) {6831CreateVariable(data,1,1,0.0,"Temperature",FALSE);6832}6833else if(savedofs == 5) {6834CreateVariable(data,1,1,0.0,"dTdX",FALSE);6835CreateVariable(data,2,1,0.0,"dTdY",FALSE);6836CreateVariable(data,3,1,0.0,"Qx",FALSE);6837CreateVariable(data,4,1,0.0,"Qy",FALSE);6838CreateVariable(data,5,1,0.0,"Temperature",FALSE);6839}68406841allocated = TRUE;6842goto omstart;6843}6844fclose(in);68456846if(info) printf("The CGsim mesh was loaded from file %s.\n\n",filename);6847return(0);6848}684968506851int FluxToElmerType(int nonodes, int dim) {6852int elmertype;68536854elmertype = 0;68556856if( dim == 2 ) {6857switch( nonodes ) {6858case 3:6859elmertype = 203;6860break;6861case 6:6862elmertype = 306;6863break;6864case 8:6865elmertype = 408;6866break;6867}6868}68696870if( !elmertype ) printf("FluxToElmerType could not deduce element type! (%d %d)\n",nonodes,dim);68716872return(elmertype);6873}687468756876687768786879int LoadFluxMesh(struct FemType *data,struct BoundaryType *bound,6880char *prefix,int info)6881/* Load the mesh from format of Flux Cedrat in TRA format. */6882{6883int noknots,noelements,maxnodes,dim,elmertype;6884int nonodes,matind,noregions,mode;6885int debug;6886int *elementtypes;6887char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;6888int i,j,k;6889char entityname[MAXNAMESIZE];6890FILE *in;689168926893strcpy(filename,prefix);6894if ((in = fopen(filename,"r")) == NULL) {6895AddExtension(prefix,filename,"TRA");6896if ((in = fopen(filename,"r")) == NULL) {6897printf("LoadFluxMesh: opening of the Flux mesh file '%s' wasn't successful !\n",6898filename);6899return(1);6900}6901}69026903printf("Reading 2D mesh from Flux mesh file %s.\n",filename);6904InitializeKnots(data);69056906debug = FALSE;6907linenumber = 0;6908dim = 2;6909noknots = 0;6910noelements = 0;6911mode = 0;6912maxnodes = 8;6913691469156916for(;;) {69176918if(0) printf("line: %d %s\n",mode,line);69196920if( Getrow(line,in,FALSE)) goto end;6921if(line[0]=='\0') goto end;69226923if( strstr(line,"Number of nodes")) mode = 1;6924else if( strstr(line,"Total number of elements")) mode = 2;6925else if( strstr(line,"Total number of regions")) mode = 3;69266927else if( strstr(line,"Description of elements")) mode = 10;6928else if( strstr(line,"Coordinates of the nodes")) mode = 11;6929else if( strstr(line,"Names of the regions")) mode = 12;69306931else if( strstr(line,"Neighbouring element table")) mode = 13;6932else if( strstr(line,"List of boundary nodes")) mode = 14;6933else if( strstr(line,"Physical properties")) mode = 15;6934else if( strstr(line,"Boundary conditions")) mode = 16;6935else {6936if(debug) printf("Unknown mode line %d: %s",linenumber,line);6937mode = 0;6938}69396940if(debug && mode) printf("Current mode is %d\n",mode);69416942switch( mode ) {6943case 1:6944noknots = atoi(line);6945break;69466947case 2:6948noelements = atoi(line);6949break;69506951case 3:6952noregions = atoi(line);6953break;695469556956case 10:6957if(info) {6958printf("Allocating mesh with %d nodes and %d %d-node elements in %d dims.\n",6959noknots,noelements,maxnodes,dim);6960}69616962data->noknots = noknots;6963data->noelements = noelements;6964data->maxnodes = maxnodes;6965data->dim = dim;6966AllocateKnots(data);69676968if(info) printf("Reading %d element topologies\n",noelements);6969for(i=1;i<=noelements;i++) {6970Getrow(line,in,FALSE);6971cp = line;6972j = next_int(&cp);6973if( i != j ) {6974printf("It seems that reordering of elements should be performed! (%d %d)\n",i,j);6975}6976nonodes = next_int(&cp);6977matind = abs( next_int(&cp) );69786979elmertype = FluxToElmerType( nonodes, dim );6980data->elementtypes[i] = elmertype;6981data->material[i] = matind;69826983Getrow(line,in,FALSE);6984cp = line;6985for(k=0;k<nonodes;k++) {6986data->topology[i][k] = next_int(&cp);6987}6988}6989break;69906991case 11:6992if(info) printf("Reading %d element nodes\n",noknots);6993for(i=1;i<=noknots;i++) {6994Getrow(line,in,FALSE);6995cp = line;6996j = next_int(&cp);6997if( i != j ) {6998printf("It seems that reordering of nodes should be performed! (%d %d)\n",i,j);6999}7000data->x[i] = next_real(&cp);7001data->y[i] = next_real(&cp);7002if(dim == 3) data->z[i] = next_real(&cp);7003}7004break;700570067007case 12:7008if(info) printf("Reading %d names of regions\n",noregions);7009for(i=1;i<=noregions;i++) {7010Getrow(line,in,FALSE);7011cp = line;7012j = next_int(&cp);7013if( i != j ) {7014printf("It seems that reordering of regions should be performed! (%d %d)\n",i,j);7015}7016sscanf(cp,"%s",entityname);7017if(!data->bodyname[i]) data->bodyname[i] = Cvector(0,MAXNAMESIZE);7018strcpy(data->bodyname[i],entityname);7019}7020data->bodynamesexist = TRUE;7021data->boundarynamesexist = TRUE;7022break;702370247025default:7026if(debug) printf("unimplemented mode: %d\n",mode );7027mode = 0;7028break;7029}7030}70317032end:7033fclose(in);70347035/* Until this far all elements have been listed as bulk elements.7036Now separate the lower dimensional elements to be boundary elements. */7037ElementsToBoundaryConditions(data,bound,TRUE,info);70387039if(info) printf("The Flux mesh was loaded from file %s.\n\n",filename);70407041return(0);7042}7043704470457046/* Mapping between the elemental node order of PF3 file format to7047Elmer file format. */7048static void PF3ToElmerPermuteNodes(int elemtype,int *topology)7049{7050int i=0, nodes=0, oldtopology[MAXNODESD2];7051int reorder, *porder;7052int debug;70537054int order303[] = {3,1,2}; //tri7055int order306[] = {3,1,2,6,4,5}; //tri^27056int order404[] = {3,4,1,2}; //quad7057int order408[] = {3,4,1,2,7,8,5,6}; //quad^27058int order504[] = {1,2,3,4}; //tetra7059int order510[] = {1,2,3,4,5,8,6,7,10,9};//tetra^27060int order605[] = {3,2,1,4,5}; //pyramid7061int order613[] = {3,2,1,4,5,7,6,9,8,12,11,10,13}; //pyramid^27062int order706[] = {6,4,5,3,1,2}; //wedge (prism)7063int order715[] = {6,4,5,3,1,2,12,10,11,9,7,8,15,13,14}; //wedge^2 (prism^2)7064int order808[] = {7,8,5,6,3,4,1,2}; //hexa7065int order820[] = {7,8,5,6,3,4,1,2,15,16,13,14,19,20,17,18,11,12,9,10}; //hexa^270667067debug = TRUE;70687069reorder = FALSE;70707071switch (elemtype) {70727073case 101:7074//nothing to change here7075break;70767077case 202:7078//nothing to change here7079break;70807081case 203:7082//nothing to change here7083break;70847085case 303:7086reorder = TRUE;7087porder = &order303[0];7088break;70897090case 306:7091reorder = TRUE;7092porder = &order306[0];7093break;70947095case 404:7096reorder = TRUE;7097porder = &order404[0];7098break;70997100case 408:7101reorder = TRUE;7102porder = &order408[0];7103break;71047105case 504:7106reorder = TRUE;7107porder = &order504[0];7108break;71097110case 510:7111reorder = TRUE;7112porder = &order510[0];7113break;71147115case 605:7116reorder = TRUE;7117porder = &order605[0];7118break;71197120case 613:7121reorder = TRUE;7122porder = &order613[0];7123break;71247125case 706:7126reorder = TRUE;7127porder = &order706[0];7128break;71297130case 715:7131reorder = TRUE;7132porder = &order715[0];7133break;71347135case 808:7136reorder = TRUE;7137porder = &order808[0];7138break;71397140case 820:7141reorder = TRUE;7142porder = &order820[0];7143break;71447145default:7146if(debug) printf("Warning : Unknown element type: %d\n",elemtype );7147break;7148}71497150if( reorder ) {7151nodes = elemtype % 100;7152for(i=0;i<nodes;i++)7153oldtopology[i] = topology[i];7154for(i=0;i<nodes;i++)7155topology[i] = oldtopology[porder[i]-1];7156}7157}715871597160int FluxToElmerType3D(int nonodes, int dim) {7161int elmertype;71627163elmertype = 0;71647165if( dim == 2 ) {7166switch( nonodes ) {7167case 3:7168elmertype = 303;7169break;7170case 4:7171elmertype = 404;7172break;7173case 6:7174elmertype = 306;7175break;7176case 8:7177elmertype = 408;7178break;7179}7180}71817182if( dim == 3 ) {7183switch( nonodes ) {7184case 4:7185elmertype = 504;7186break;7187case 5:7188elmertype = 605;7189break;7190case 6:7191elmertype = 706;7192break;7193case 8:7194elmertype = 808;7195break;7196case 10:7197elmertype = 510;7198break;7199case 13:7200elmertype = 613;7201break;7202case 15:7203elmertype = 715;7204break;7205case 20:7206elmertype = 820;7207break;7208}7209}72107211if( !elmertype ) printf("FluxToElmerType3D could not deduce element type! (%d %d)\n",nonodes,dim);72127213return(elmertype);7214}721572167217int LoadFluxMesh3D(struct FemType *data,struct BoundaryType *bound,7218char *prefix,int info)7219/* Load the mesh from format of Flux Cedrat in PF3 format. */7220{7221int noknots,noelements,maxnodes,dim,elmertype;7222int nonodes,matind,noregions,mode;7223int dimplusone, maxlinenodes, nodecnt;7224int debug;7225int *elementtypes;7226char filename[MAXFILESIZE],line[MAXLINESIZE],*cp;7227int i,j,k;7228char entityname[MAXNAMESIZE];7229FILE *in;72307231strcpy(filename,prefix);7232if ((in = fopen(filename,"r")) == NULL) {7233AddExtension(prefix,filename,"PF3");7234if ((in = fopen(filename,"r")) == NULL) {7235printf("LoadFluxMesh3D: opening of the Flux mesh file '%s' wasn't successful !\n",7236filename);7237return(1);7238}7239}72407241printf("Reading 3D mesh from Flux mesh file %s.\n",filename);7242InitializeKnots(data);72437244debug = FALSE;7245linenumber = 0;7246dim = 3;7247noknots = 0;7248noelements = 0;7249mode = 0;7250maxnodes = 20; // 15?7251maxlinenodes = 12; //nodes can be located at several lines72527253for(;;) {72547255if(0) printf("line: %d %s\n",mode,line);72567257if( Getrow(line,in,FALSE)) goto end;7258if(line[0]=='\0') goto end;7259if( strstr(line,"==== DECOUPAGE TERMINE")) goto end;72607261if( strstr(line,"NOMBRE DE DIMENSIONS DU DECOUPAGE")) mode = 1;7262else if( strstr(line,"NOMBRE D'ELEMENTS")) mode = 3;7263else if( strstr(line,"NOMBRE DE POINTS")) mode = 2;7264else if( strstr(line,"NOMBRE DE REGIONS")) mode = 4;72657266else if( strstr(line,"DESCRIPTEUR DE TOPOLOGIE DES ELEMENTS")) mode = 10;7267else if( strstr(line,"COORDONNEES DES NOEUDS")) mode = 11;7268else if( strstr(line,"NOMS DES REGIONS")) mode = 12;7269else {7270if(debug) printf("Unknown mode line %d: %s",linenumber,line);7271mode = 0;7272}72737274if(debug && mode) printf("Current mode is %d\n",mode);72757276switch( mode ) {7277case 1:7278dim = atoi(line);7279break;72807281case 2:7282if( strstr(line,"NOMBRE DE POINTS D'INTEGRATION")) break;/* We are looking for the total number of nodes */7283noknots = atoi(line);7284break;72857286case 3:7287i = atoi(line);7288noelements = MAX(i,noelements); /* We are looking for the total number of elements */7289break;72907291case 4:7292i = atoi(line);7293noregions = MAX(i,noregions); /* We are looking for the total number of regions */7294break;729572967297case 10:7298if(info) {7299printf("Allocating mesh with %d nodes and %d %d-node elements in %d dims.\n",7300noknots,noelements,maxnodes,dim);7301}73027303data->noknots = noknots;7304data->noelements = noelements;7305data->maxnodes = maxnodes;7306data->dim = dim;7307AllocateKnots(data);73087309if(info) printf("Reading %d element topologies\n",noelements);7310for(i=1;i<=noelements;i++)7311{7312Getrow(line,in,FALSE);7313cp = line;7314j = next_int(&cp);7315if( i != j ) {7316printf("It seems that reordering of elements should be performed! (%d %d)\n",i,j);7317}7318next_int(&cp); //2 internal element type description7319next_int(&cp); //3 internal element type description7320matind = next_int(&cp); //4 number of the belonging region7321dimplusone = next_int(&cp); //5 dimensionality 4-3D 3-2D7322next_int(&cp); //6 zero here always7323next_int(&cp); //7 internal element type description7324nonodes = next_int(&cp); //8 number of nodes73257326elmertype = FluxToElmerType3D( nonodes, dimplusone-1 );7327data->elementtypes[i] = elmertype;7328data->material[i] = matind;73297330Getrow(line,in,FALSE);7331cp = line;7332nodecnt = 0;7333for(k=0;k<nonodes;k++) {73347335if(nodecnt >= maxlinenodes) {7336nodecnt = 0;7337Getrow(line,in,FALSE);7338cp = line;7339}7340data->topology[i][k] = next_int(&cp);7341nodecnt+=1;7342}73437344PF3ToElmerPermuteNodes(elmertype,data->topology[noelements]);73457346}7347break;73487349case 11:7350if(info) printf("Reading %d element nodes\n",noknots);7351for(i=1;i<=noknots;i++) {7352Getrow(line,in,FALSE);7353cp = line;7354j = next_int(&cp);7355if( i != j ) {7356printf("It seems that reordering of nodes should be performed! (%d %d)\n",i,j);7357}7358data->x[i] = next_real(&cp);7359data->y[i] = next_real(&cp);7360data->z[i] = next_real(&cp);7361}7362break;736373647365case 12:7366if(info) printf("Reading %d names of regions\n",noregions);7367for(i=1;i<=noregions;i++) {7368Getrow(line,in,FALSE);73697370/* currently we just cycle through this and get a new row */7371if( strstr(line,"REGIONS SURFACIQUES")) Getrow(line,in,FALSE);7372if( strstr(line,"REGIONS VOLUMIQUES")) Getrow(line,in,FALSE);73737374sscanf(line,"%s",entityname);7375if(!data->bodyname[i]) data->bodyname[i] = Cvector(0,MAXNAMESIZE);7376strcpy(data->bodyname[i],entityname);7377}7378data->bodynamesexist = TRUE;7379data->boundarynamesexist = TRUE;7380break;738173827383default:7384if(debug) printf("unimplemented mode: %d\n",mode );7385mode = 0;7386break;7387}7388}73897390end:7391fclose(in);73927393/* Until this far all elements have been listed as bulk elements.7394Now separate the lower dimensional elements to be boundary elements. */7395ElementsToBoundaryConditions(data,bound,TRUE,info);73967397if(info) printf("The Flux 3D mesh was loaded from file %s.\n\n",filename);73987399return(0);7400}740174027403