Path: blob/devel/ElmerGUI/Application/plugins/egutils.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#include <stdio.h>26#include <stddef.h>27#include <stdlib.h>28#include <string.h>29#include <math.h>30#include <sys/types.h>31#include <time.h>3233/* Possible monitoring of memory usage, if supported */34#define MEM_USAGE 035#if MEM_USAGE36#include <sys/resource.h>37#endif3839#include "egutils.h"4041#define FREE_ARG char*42#define SHOWMEM 04344#if SHOWMEM45static int nfloat=0, nint=0, cumnfloat=0, cumnint=0, locnint, locnfloat;4647int MemoryUsage()48{49if(locnint > 1000 || locnfloat > 1000)50printf("Memory used real %d %d %d int %d %d %d\n",51nfloat,cumnfloat,locnfloat,nint,cumnint,locnint);52locnfloat = locnint = 0;53}54#endif555657/* The following routines are copied from the book58"Numerical Recipes in C, The art of scientific computing"59by Cambridge University Press and include the following6061Non-Copyright Notice: This appendix and its utility routines are62herewith placed into the public domain. Anyone may copy them freely63for any purpose. We of course accept no liability whatsoever for64any such use. */65666768void nrerror(const char error_text[])69/* standard error handler */70{71fprintf(stderr,"run-time error...\n");72fprintf(stderr,"%s\n",error_text);73fprintf(stderr,"...now exiting to system...\n");74exit(1);75}767778/* Vector initialization */7980float *vector(int nl,int nh)81/* allocate a float vector with subscript range v[nl..nh] */82{83float *v;8485v = (float*)malloc((size_t) (nh-nl+1+1)*sizeof(float));86if (!v) nrerror("allocation failure in vector()");87return(v-nl+1);88}89909192int *ivector(int nl,int nh)93/* Allocate an int vector with subscript range v[nl..nh] */94{95int *v;9697if( nh < nl ) {98printf("Allocation impossible in ivector: %d %d\n",nl,nh);99exit(1);100}101102v=(int*) malloc((size_t) (nh-nl+1+1)*sizeof(int));103if (!v) nrerror("allocation failure in ivector()");104105#if SHOWMEM106locnint = (nh-nl+1+1);107nint += locnint;108cumnint += locnint;109MemoryUsage();110#endif111112return(v-nl+1);113}114115116char *cvector(int nl,int nh)117/* allocate an char vector with subscript range v[nl..nh] */118{119char *v;120121v=(char *)malloc((size_t) (nh-nl+1+1)*sizeof(char));122if (!v) nrerror("allocation failure in cvector()");123return(v-nl+1);124}125126127unsigned long *lvector(int nl,int nh)128/* allocate an unsigned long vector with subscript range v[nl..nh] */129{130unsigned long *v;131132v=(unsigned long *)malloc((size_t) (nh-nl+1+1)*sizeof(unsigned long));133if (!v) nrerror("allocation failure in lvector()");134return(v-nl+1);135}136137138139double *dvector(int nl,int nh)140/* allocate a double vector with subscript range v[nl..nh] */141{142double *v;143144if( nh < nl ) {145printf("Allocation impossible in dvector: %d %d\n",nl,nh);146exit(1);147}148149v=(double *)malloc((size_t) (nh-nl+1+1)*sizeof(double));150if (!v) nrerror("allocation failure in dvector()");151152#if SHOWMEM153locnfloat = nh-nl+1+1;154nfloat += locnfloat;155cumnfloat += locnfloat;156MemoryUsage();157#endif158159return(v-nl+1);160}161162163/* Matrix initialization */164165float **matrix(int nrl,int nrh,int ncl,int nch)166/* allocate a float matrix with subscript range m[nrl..nrh][ncl..nch] */167{168int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;169float **m;170171/* allocate pointers to rows */172m=(float **) malloc((size_t) (nrow+1)*sizeof(float*));173if (!m) nrerror("allocation failure 1 in matrix()");174m += 1;175m -= nrl;176177/* allocate rows and set pointers to them */178m[nrl]=(float *) malloc((size_t)((nrow*ncol+1)*sizeof(float)));179if (!m[nrl]) nrerror("allocation failure 2 in matrix()");180m[nrl] += 1;181m[nrl] -= ncl;182183for(i=nrl+1;i<=nrh;i++)184m[i]=m[i-1]+ncol;185186return(m);187}188189190double **dmatrix(int nrl,int nrh,int ncl,int nch)191/* allocate a double matrix with subscript range m[nrl..nrh][ncl..nch] */192{193int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;194double **m;195196if( nrh < nrl || nch < ncl ) {197printf("Allocation impossible in dmatrix: %d %d %d %d\n",nrl,nrh,ncl,nch);198exit(1);199}200201202203/* allocate pointers to rows */204m=(double **) malloc((size_t) (nrow+1)*sizeof(double*));205if (!m) nrerror("allocation failure 1 in dmatrix()");206m += 1;207m -= nrl;208209210/* allocate rows and set pointers to them */211m[nrl]=(double *) malloc((size_t)((nrow*ncol+1)*sizeof(double)));212if (!m[nrl]) nrerror("allocation failure 2 in dmatrix()");213m[nrl] += 1;214m[nrl] -= ncl;215216for(i=nrl+1;i<=nrh;i++)217m[i]=m[i-1]+ncol;218219#if SHOWMEM220locnfloat = (nrow+1 + (nrow*ncol+1));221nfloat += locnfloat;222cumnfloat += locnfloat;223MemoryUsage();224#endif225226return(m);227}228229230int **imatrix(int nrl,int nrh,int ncl,int nch)231/* allocate an int matrix with subscript range m[nrl..nrh][ncl..nch] */232{233int i, nrow=nrh-nrl+1, ncol=nch-ncl+1;234int **m;235236if( nrh < nrl || nch < ncl ) {237printf("Allocation impossible in imatrix: %d %d %d %d\n",nrl,nrh,ncl,nch);238exit(1);239}240241/* allocate pointers to rows */242m=(int **) malloc((size_t) (nrow+1)*sizeof(int*));243if (!m) nrerror("allocation failure 1 in imatrix()");244m += 1;245m -= nrl;246247/* allocate rows and set pointers to them */248m[nrl]=(int *) malloc((size_t)((nrow*ncol+1)*sizeof(int)));249if (!m[nrl]) nrerror("allocation failure 2 in imatrix()");250m[nrl] += 1;251m[nrl] -= ncl;252253for(i=nrl+1;i<=nrh;i++)254m[i]=m[i-1]+ncol;255256#if SHOWMEM257locnint = (nrow+1 + (nrow*ncol+1));258nint += locnint;259cumnint += locnint;260MemoryUsage();261#endif262263return(m);264}265266267268float **submatrix(float **a,int oldrl,int oldrh,int oldcl,int oldch,int newrl,int newcl)269/* point a submatrix [newrl..][newcl..] to a[oldrl..oldrh][oldcl..oldch] */270{271int i,j, nrow=oldrh-oldrl+1, ncol=oldcl-newcl;272float **m;273274/* allocate array of pointers to rows */275m=(float **) malloc((size_t) ((nrow+1)*sizeof(float*)));276if (!m) nrerror("allocation failure in submatrix()");277m += 1;278m -= newrl;279280/* set pointers to rows */281for(i=oldrl,j=newrl;i<=oldrh;i++,j++)282m[j]=a[i]+ncol;283284return(m);285}286287/* Tensor initialization */288289double ***f3tensor(int nrl,int nrh,int ncl,int nch,int ndl,int ndh)290/* allocate a double 3tensor with range t[nrl..nrh][ncl..nch][ndl..ndh] */291{292int i,j,nrow=nrh-nrl+1,ncol=nch-ncl+1,ndep=ndh-ndl+1;293double ***t;294295t=(double***) malloc((size_t)((nrow+1)*sizeof(double***)));296if (!t) nrerror("allocation failure 1 in f3tensor()");297t += 1;298t -= nrl;299300t[nrl]=(double**) malloc((size_t)((nrow*ncol+1)*sizeof(double*)));301if(!t[nrl]) nrerror("allocation failure 2 in f3tensor()");302t[nrl] += 1;303t[nrl] -= ncl;304305t[nrl][ncl]=(double*) malloc((size_t)((nrow*ncol*ndep+1)*sizeof(double)));306if(!t[nrl][ncl]) nrerror("allocation failure 3 in f3tensor()");307t[nrl][ncl] += 1;308t[nrl][ncl] -= ndl;309310for(j=ncl+1;j<=nch;j++) t[nrl][j] = t[nrl][j-1]+ndep;311for(i=nrl+1;i<=nrh;i++) {312t[i] = t[i-1]+ncol;313t[i][ncl] = t[i-1][ncl]+ncol*ndep;314for(j=ncl+1;j<=nch;j++) t[i][j] = t[i][j-1]+ndep;315}316return(t);317}318319320/* Deallocation routines */321322void free_vector(float *v,int nl,int nh)323{324free((FREE_ARG) (v+nl-1));325}326327void free_ivector(int *v,int nl,int nh)328{329#if SHOWMEM330cumnint -= (nh-nl+1+1);331#endif332333free((FREE_ARG) (v+nl-1));334}335336void free_cvector(char *v,int nl,int nh)337{338free((FREE_ARG) (v+nl-1));339}340341void free_lvector(unsigned long *v,int nl,int nh)342{343free((FREE_ARG) (v+nl-1));344}345346347void free_dvector(double *v,int nl,int nh)348{349#if SHOWMEM350cumnfloat -= (nh-nl+1+1);351#endif352353free((FREE_ARG) (v+nl-1));354}355356void free_matrix(float **m,int nrl,int nrh,int ncl,int nch)357{358free((FREE_ARG) (m[nrl]+ncl-1));359free((FREE_ARG) (m+nrl-1));360}361362void free_dmatrix(double **m,int nrl,int nrh,int ncl,int nch)363{364#if SHOWMEM365int nrow=nrh-nrl+1;366int ncol=nch-ncl+1;367cumnfloat -= (nrow+1 + (nrow*ncol+1));368#endif369370free((FREE_ARG) (m[nrl]+ncl-1));371free((FREE_ARG) (m+nrl-1));372}373374void free_imatrix(int **m,int nrl,int nrh,int ncl,int nch)375{376#if SHOWMEM377int nrow=nrh-nrl+1;378int ncol=nch-ncl+1;379cumnint -= (nrow+1 + (nrow*ncol+1));380#endif381382free((FREE_ARG) (m[nrl]+ncl-1));383free((FREE_ARG) (m+nrl-1));384}385386void free_submatrix(float **b,int nrl,int nrh,int ncl,int nch)387{388free((FREE_ARG) (b+nrl-1));389}390391void free_f3tensor(double ***t,int nrl,int nrh,int ncl,int nch,int ndl,int ndh)392{393free((FREE_ARG) (t[nrl][ncl]+ndl-1));394free((FREE_ARG) (t[nrl]+ncl-1));395free((FREE_ARG) (t+nrl-1));396}397398399/* -------------------------------: common.c :----------------------------400Includes common operations for operating vectors and such. */401402403static Real timer_t0, timer_dt;404static int timer_active = FALSE;405static char timer_filename[600];406407void timer_init()408{409timer_active = FALSE;410}411412413void timer_activate(const char *prefix)414{415Real time;416timer_active = TRUE;417418time = clock() / (double)CLOCKS_PER_SEC;419420AddExtension(prefix,timer_filename,"time");421422printf("Activating timer (s): %.2f\n",time);423printf("Saving timer info to file %s\n",timer_filename);424425timer_dt = time;426timer_t0 = time;427}428429430void timer_show()431{432static int visited = 0;433Real time;434FILE *out;435#if MEM_USAGE436int who,ret;437Real memusage;438static struct rusage usage;439#endif440441if(!timer_active) return;442443time = clock() / (double)CLOCKS_PER_SEC;444printf("Elapsed time (s): %.2f %.2f\n",time-timer_t0,time-timer_dt);445446#if MEM_USAGE447who = RUSAGE_SELF;448ret = getrusage( who, &usage );449if( !ret ) {450printf("maxrss %ld\n",usage.ru_maxrss);451printf("ixrss %ld\n",usage.ru_ixrss);452printf("idrss %ld\n",usage.ru_idrss);453printf("isrss %ld\n",usage.ru_isrss);454455memusage = (double) 1.0 * usage.ru_maxrss;456}457else {458printf("Failed to obtain resource usage!\n");459memusage = 0.0;460}461#endif462463visited = visited + 1;464if( visited == 1 ) {465out = fopen(timer_filename,"w");466}467else {468out = fopen(timer_filename,"a");469}470471#if MEM_USAGE472fprintf(out,"%3d %12.4le %12.4le %12.4le\n",visited,time-timer_t0,time-timer_dt,memusage);473#else474fprintf(out,"%3d %12.4le %12.4le\n",visited,time-timer_t0,time-timer_dt);475#endif476477fclose(out);478479timer_dt = time;480}481482483484485void bigerror(const char error_text[])486{487fprintf(stderr,"***** ERROR: We cannot continue with this! *****\n");488fprintf(stderr,"***** %s\n",error_text);489fprintf(stderr,"***** ...now exiting to system!\n");490exit(1);491}492493494void smallerror(const char error_text[])495{496fprintf(stderr,"***** WARNING: This should not happen but we try to continue! *****\n");497fprintf(stderr,"***** %s\n",error_text);498}499500501502int FileExists(char *filename)503{504FILE *in;505506if((in = fopen(filename,"r")) == NULL)507return(FALSE);508else {509fclose(in);510return(TRUE);511}512}513514515Real Minimum(Real *vector,int first,int last)516/* Returns the smallest value of vector in range [first,last]. */517{518Real min;519int i;520521min=vector[first];522for(i=first+1;i<=last;i++)523if(min>vector[i]) min=vector[i];524525return(min);526}527528529int Minimi(Real *vector,int first,int last)530/* Returns the position of the smallest value of vector in range [first,last]. */531{532Real min;533int i,mini;534535mini=first;536min=vector[first];537for(i=first+1;i<=last;i++)538if(min>vector[i])539min=vector[(mini=i)];540541return(mini);542}543544545Real Maximum(Real *vector,int first,int last)546/* Returns the largest value of vector in range [first,last]. */547{548Real max;549int i;550551max=vector[first];552for(i=first+1;i<=last;i++)553if(max<vector[i]) max=vector[i];554555return(max);556}557558559int Maximi(Real *vector,int first,int last)560/* Returns the position of the largest value of vector in range [first,last]. */561{562Real max;563int i,maxi;564565maxi=-1;566max=vector[first];567for(i=first+1;i<=last;i++)568if(max<vector[i])569max=vector[(maxi=i)];570571return(maxi);572}573574575576void AddExtension(const char *fname1,char *fname2,const char *newext)577/* Changes the extension of a filename.578'fname1' - the original filename579'fname2' - the new filename580'newext' - the new extension581If there is originally no extension it's appended. In this case582there has to be room for the extension.583*/584{585char *ptr1,*ptr2;586587strcpy(fname2,fname1);588ptr1 = strrchr(fname2, '.');589590if (ptr1) {591int badpoint=FALSE;592ptr2 = strrchr(fname2, '/');593if(ptr2 && ptr2 > ptr1) badpoint = TRUE;594if(!badpoint) *ptr1 = '\0';595}596strcat(fname2, ".");597strcat(fname2,newext);598}599600601int StringToStrings(const char *buf,char args[10][15],int maxcnt,char separator)602/* Finds real numbers separated by a certain separator from a string.603'buf' - input string ending to a EOF604'dest' - a vector of real numbers605'maxcnt' - maximum number of real numbers to be read606'separator' - the separator of real numbers607The number of numbers found is returned in the function value.608*/609{610int i,cnt,totlen,finish;611char *ptr1 = (char *)buf, *ptr2;612613614totlen = strlen(buf);615finish = 0;616cnt = 0;617618if (!buf[0]) return 0;619620do {621ptr2 = strchr(ptr1,separator);622if(ptr2) {623for(i=0;i<15;i++) {624args[cnt][i] = ptr1[i];625if(ptr1 + i >= ptr2) break;626}627args[cnt][i] = '\0';628ptr1 = ptr2+1;629}630else {631for(i=0;i<15;i++) {632if(ptr1 + i >= buf+totlen) break;633args[cnt][i] = ptr1[i];634}635args[cnt][i] = '\0';636finish = 1;637}638639cnt++;640} while (cnt < maxcnt && !finish);641642return cnt;643}644645646int StringToReal(const char *buf,Real *dest,int maxcnt,char separator)647/* Finds real numbers separated by a certain separator from a string.648'buf' - input string ending to a EOF649'dest' - a vector of real numbers650'maxcnt' - maximum number of real numbers to be read651'separator' - the separator of real numbers652The number of numbers found is returned in the function value.653*/654{655int cnt = 0;656char *ptr1 = (char *)buf, *ptr2;657658if (!buf[0]) return 0;659do {660ptr2 = strchr(ptr1,separator);661if (ptr2) ptr2[0] = '\0';662dest[cnt++] = atof(ptr1);663if (ptr2) ptr1 = ptr2+1;664} while (cnt < maxcnt && ptr2 != NULL);665666return cnt;667}668669670int StringToInteger(const char *buf,int *dest,int maxcnt,char separator)671{672int cnt = 0;673char *ptr1 = (char *)buf, *ptr2;674int ival;675676if (!buf[0]) return 0;677do {678679ptr2 = strchr(ptr1,separator);680if (ptr2) ptr2[0] = '\0';681ival = atoi(ptr1);682683dest[cnt++] = ival;684685if (ptr2) ptr1 = ptr2+1;686} while (cnt < maxcnt && ptr2 != NULL);687688return cnt;689}690691int StringToIntegerNoZero(const char *buf,int *dest,int maxcnt,char separator)692{693int cnt = 0;694char *ptr1 = (char *)buf, *ptr2;695int ival;696697if (!buf[0]) return 0;698do {699700ptr2 = strchr(ptr1,separator);701if (ptr2) ptr2[0] = '\0';702ival = atoi(ptr1);703704if(ival == 0) break;705706dest[cnt++] = ival;707708if (ptr2) ptr1 = ptr2+1;709} while (cnt < maxcnt && ptr2 != NULL);710711return cnt;712}713714715int next_int(char **start)716{717int i;718char *end;719720i = strtol(*start,&end,10);721*start = end;722return(i);723}724725int next_int_n(char **start, int n)726{727int i;728char *end = *start+n;729char saved = *end;730731*end = '\0';732i = strtol(*start,NULL,10);733*end = saved;734*start = end;735return(i);736}737738Real next_real(char **start)739{740Real r;741char *end;742743r = strtod(*start,&end);744745*start = end;746return(r);747}748749750/*751* sort: sort an (double) array to ascending order, and move the elements of752* another (integer) array accordingly. the latter can be used as track753* keeper of where an element in the sorted order at position (k) was in754* in the original order (Ord[k]), if it is initialized to contain755* numbers (0..N-1) before calling sort.756*757* Parameters:758*759* N: int / number of entries in the arrays.760* Key: double[N] / array to be sorted.761* Ord: int[N] / change this accordingly.762*/763void SortIndex( int N, double *Key, int *Ord )764{765double CurrentKey;766767int CurrentOrd;768769int CurLastPos;770int CurHalfPos;771772int i;773int j;774775/* Initialize order */776for(i=1;i<=N;i++)777Ord[i] = i;778779CurHalfPos = N / 2 + 1;780CurLastPos = N;781while( 1 ) {782if ( CurHalfPos > 1 ) {783CurHalfPos--;784CurrentKey = Key[CurHalfPos];785CurrentOrd = Ord[CurHalfPos];786} else {787CurrentKey = Key[CurLastPos];788CurrentOrd = Ord[CurLastPos];789Key[CurLastPos] = Key[1];790Ord[CurLastPos] = Ord[1];791CurLastPos--;792if ( CurLastPos == 1 ) {793Key[1] = CurrentKey;794Ord[1] = CurrentOrd;795return;796}797}798i = CurHalfPos;799j = 2 * CurHalfPos;800while( j <= CurLastPos ) {801if ( j < CurLastPos && Key[j] < Key[j + 1] ) {802j++;803}804if ( CurrentKey < Key[j] ) {805Key[i] = Key[j];806Ord[i] = Ord[j];807i = j;808j += i;809} else {810j = CurLastPos + 1;811}812}813Key[i] = CurrentKey;814Ord[i] = CurrentOrd;815}816817}818819820821822823