From 8fe367ecf2cbda79960a68a052fdb84916427c0e Mon Sep 17 00:00:00 2001 From: tradke Date: Wed, 13 Sep 2000 13:49:13 +0000 Subject: Importing latest stuff from development repository git-svn-id: http://svn.cactuscode.org/arrangements/CactusExternal/FlexIO/trunk@2 21a6bef8-4479-4f54-8f8d-0db94a2919ef --- src/AMRPlus/AMRPlusConv.C | 168 +++++ src/AMRPlus/AMRTree.C | 27 + src/AMRPlus/AMRTree.h | 35 + src/AMRPlus/AMRfilereaderPlus.C | 175 +++++ src/AMRPlus/AMRfilereaderPlus.h | 74 ++ src/AMRPlus/AMRgridPlus.h | 21 + src/AMRPlus/AMRgridreaderPlus.C | 90 +++ src/AMRPlus/AMRgridreaderPlus.h | 41 ++ src/AMRPlus/AMRreaderPlus.C | 122 ++++ src/AMRPlus/AMRreaderPlus.h | 85 +++ src/AMRPlus/AMRwriterPlus.C | 48 ++ src/AMRPlus/AMRwriterPlus.h | 70 ++ src/AMRPlus/Dpndfile | 193 ++++++ src/AMRPlus/FlexSetTempl.h | 20 + src/AMRPlus/filereadtest.C | 43 ++ src/AMRPlus/flexarrays.h | 184 +++++ src/AMRPlus/flexmatrix.h | 20 + src/AMRPlus/flexset.C | 215 ++++++ src/AMRPlus/flexset.h | 209 ++++++ src/AMRPlus/gridreadtest.C | 40 ++ src/AMRPlus/jerror.h | 291 ++++++++ src/AMRPlus/makefile | 70 ++ src/AMRPlus/ordarrays.h | 23 + src/AMRPlus/readtest.C | 54 ++ src/AMRPlus/settst.C | 59 ++ src/AMRPlus/testread.C | 170 +++++ src/AMRPlus/tst.C | 42 ++ src/AMRwriter.cc | 473 +++++++++++++ src/AMRwriter.h | 47 ++ src/AMRwriter.hh | 288 ++++++++ src/AVSreadBNB.cc | 817 ++++++++++++++++++++++ src/AVSreadHLL.cc | 768 +++++++++++++++++++++ src/AVSreadIEEE.c | 95 +++ src/AVSreadcpp.cc | 216 ++++++ src/AmrFileReader.cc | 153 +++++ src/AmrFileReader.hh | 69 ++ src/AmrGrid.h | 24 + src/AmrGrid.hh | 11 + src/AmrGridReader.cc | 87 +++ src/AmrGridReader.hh | 29 + src/AmrNode.hh | 42 ++ src/AmrUcd.c | 70 ++ src/AmrUcdCompute.cc | 454 ++++++++++++ src/AmrUcdFileReader.cc | 27 + src/AmrUcdFileReader.hh | 38 ++ src/AmrUcdGridHierarchy.cc | 340 +++++++++ src/AmrUcdGridHierarchy.hh | 134 ++++ src/AppendTest.c | 69 ++ src/Arch.h | 74 ++ src/Bounds.cc | 29 + src/Bounds.hh | 18 + src/FlexArrayTmpl.H | 222 ++++++ src/FlexIO.cc | 55 ++ src/FlexIO.hh | 27 + src/GNUmakefile | 62 ++ src/H5IO.cc | 689 +++++++++++++++++++ src/H5IO.h | 12 + src/H5IO.hh | 130 ++++ src/H5IOwriter.cc | 84 +++ src/H5writer.c | 175 +++++ src/HDFIO.cc | 413 +++++++++++ src/HDFIO.h | 12 + src/HDFIO.hh | 79 +++ src/IEEEIO.cc | 1443 +++++++++++++++++++++++++++++++++++++++ src/IEEEIO.h | 13 + src/IEEEIO.hh | 709 +++++++++++++++++++ src/IEEEIOWinDllApi.h | 42 ++ src/IEEEIOslave.hh | 63 ++ src/IO.cc | 371 ++++++++++ src/IO.hh | 188 +++++ src/IOProtos.h | 63 ++ src/IOspeed.cc | 183 +++++ src/MPIO.cc | 199 ++++++ src/MPIO.fast.cc | 257 +++++++ src/MPIO.fast.hh | 66 ++ src/MPIO.h | 16 + src/MPIO.hh | 39 ++ src/MPIO.old.cc | 344 ++++++++++ src/MPIO.old.hh | 80 +++ src/MPIO.slow.cc | 202 ++++++ src/MPIO.slow.hh | 57 ++ src/MPIOspeed.cc | 201 ++++++ src/MPIutils.cc | 57 ++ src/MPIutils.hh | 389 +++++++++++ src/Makefile | 551 +++++++++++++++ src/Makefile.AVS | 58 ++ src/OrderedList.H | 116 ++++ src/Reader.cc | 126 ++++ src/Reader.hh | 87 +++ src/SampleAmrReader.cc | 74 ++ src/SlaveIO.cc | 169 +++++ src/SlaveIO.hh | 60 ++ src/SockIOreader.cc | 346 ++++++++++ src/SockIOreader.hh | 141 ++++ src/SockIOwriter.cc | 102 +++ src/SockIOwriter.hh | 181 +++++ src/Timer.cc | 44 ++ src/Timer.hh | 39 ++ src/Vec3f.hh | 278 ++++++++ src/WildWriter.cc | 609 +++++++++++++++++ src/WildWriter.h | 7 + src/WildWriter.hh | 142 ++++ src/WriteHLL.cc | 229 +++++++ src/WriteHLL.h | 32 + src/WriteHLL.hh | 52 ++ src/Writer.cc | 169 +++++ src/Writer.h | 23 + src/Writer.hh | 37 + src/boxinbox.cc | 156 +++++ src/chunkSpeed.cc | 179 +++++ src/convert2native.cc | 50 ++ src/copyperf.cc | 43 ++ src/ffio.c | 108 +++ src/ioconvert.cc | 94 +++ src/ioinfo.cc | 281 ++++++++ src/rawSpeed.cc | 83 +++ src/testBigWriter.cc | 158 +++++ src/testChunkWriter.cc | 64 ++ src/testSockread.cc | 29 + src/testSockwrite.cc | 21 + src/testWriter.cc | 80 +++ src/testallocation.cc | 82 +++ src/testhdfReader.cc | 72 ++ src/testio.cc | 112 +++ src/testllReader.cc | 75 ++ src/testllWriter.cc | 133 ++++ src/vatoi.cc | 22 + src/vatoi.hh | 6 + src/writef77.f | 17 + src/xmlview.cc | 272 ++++++++ 130 files changed, 19712 insertions(+) create mode 100644 src/AMRPlus/AMRPlusConv.C create mode 100644 src/AMRPlus/AMRTree.C create mode 100644 src/AMRPlus/AMRTree.h create mode 100644 src/AMRPlus/AMRfilereaderPlus.C create mode 100644 src/AMRPlus/AMRfilereaderPlus.h create mode 100644 src/AMRPlus/AMRgridPlus.h create mode 100644 src/AMRPlus/AMRgridreaderPlus.C create mode 100644 src/AMRPlus/AMRgridreaderPlus.h create mode 100644 src/AMRPlus/AMRreaderPlus.C create mode 100644 src/AMRPlus/AMRreaderPlus.h create mode 100644 src/AMRPlus/AMRwriterPlus.C create mode 100644 src/AMRPlus/AMRwriterPlus.h create mode 100644 src/AMRPlus/Dpndfile create mode 100644 src/AMRPlus/FlexSetTempl.h create mode 100644 src/AMRPlus/filereadtest.C create mode 100644 src/AMRPlus/flexarrays.h create mode 100644 src/AMRPlus/flexmatrix.h create mode 100644 src/AMRPlus/flexset.C create mode 100644 src/AMRPlus/flexset.h create mode 100644 src/AMRPlus/gridreadtest.C create mode 100644 src/AMRPlus/jerror.h create mode 100644 src/AMRPlus/makefile create mode 100644 src/AMRPlus/ordarrays.h create mode 100644 src/AMRPlus/readtest.C create mode 100644 src/AMRPlus/settst.C create mode 100644 src/AMRPlus/testread.C create mode 100644 src/AMRPlus/tst.C create mode 100644 src/AMRwriter.cc create mode 100644 src/AMRwriter.h create mode 100644 src/AMRwriter.hh create mode 100644 src/AVSreadBNB.cc create mode 100644 src/AVSreadHLL.cc create mode 100644 src/AVSreadIEEE.c create mode 100644 src/AVSreadcpp.cc create mode 100644 src/AmrFileReader.cc create mode 100644 src/AmrFileReader.hh create mode 100644 src/AmrGrid.h create mode 100644 src/AmrGrid.hh create mode 100644 src/AmrGridReader.cc create mode 100644 src/AmrGridReader.hh create mode 100644 src/AmrNode.hh create mode 100644 src/AmrUcd.c create mode 100644 src/AmrUcdCompute.cc create mode 100644 src/AmrUcdFileReader.cc create mode 100644 src/AmrUcdFileReader.hh create mode 100644 src/AmrUcdGridHierarchy.cc create mode 100644 src/AmrUcdGridHierarchy.hh create mode 100644 src/AppendTest.c create mode 100644 src/Arch.h create mode 100644 src/Bounds.cc create mode 100644 src/Bounds.hh create mode 100644 src/FlexArrayTmpl.H create mode 100644 src/FlexIO.cc create mode 100644 src/FlexIO.hh create mode 100644 src/GNUmakefile create mode 100644 src/H5IO.cc create mode 100644 src/H5IO.h create mode 100644 src/H5IO.hh create mode 100644 src/H5IOwriter.cc create mode 100644 src/H5writer.c create mode 100644 src/HDFIO.cc create mode 100644 src/HDFIO.h create mode 100644 src/HDFIO.hh create mode 100644 src/IEEEIO.cc create mode 100644 src/IEEEIO.h create mode 100644 src/IEEEIO.hh create mode 100644 src/IEEEIOWinDllApi.h create mode 100644 src/IEEEIOslave.hh create mode 100644 src/IO.cc create mode 100644 src/IO.hh create mode 100644 src/IOProtos.h create mode 100644 src/IOspeed.cc create mode 100644 src/MPIO.cc create mode 100644 src/MPIO.fast.cc create mode 100644 src/MPIO.fast.hh create mode 100644 src/MPIO.h create mode 100644 src/MPIO.hh create mode 100644 src/MPIO.old.cc create mode 100644 src/MPIO.old.hh create mode 100644 src/MPIO.slow.cc create mode 100644 src/MPIO.slow.hh create mode 100644 src/MPIOspeed.cc create mode 100644 src/MPIutils.cc create mode 100644 src/MPIutils.hh create mode 100644 src/Makefile create mode 100644 src/Makefile.AVS create mode 100644 src/OrderedList.H create mode 100644 src/Reader.cc create mode 100644 src/Reader.hh create mode 100644 src/SampleAmrReader.cc create mode 100644 src/SlaveIO.cc create mode 100644 src/SlaveIO.hh create mode 100644 src/SockIOreader.cc create mode 100644 src/SockIOreader.hh create mode 100644 src/SockIOwriter.cc create mode 100644 src/SockIOwriter.hh create mode 100644 src/Timer.cc create mode 100644 src/Timer.hh create mode 100644 src/Vec3f.hh create mode 100644 src/WildWriter.cc create mode 100644 src/WildWriter.h create mode 100644 src/WildWriter.hh create mode 100644 src/WriteHLL.cc create mode 100644 src/WriteHLL.h create mode 100644 src/WriteHLL.hh create mode 100644 src/Writer.cc create mode 100644 src/Writer.h create mode 100644 src/Writer.hh create mode 100644 src/boxinbox.cc create mode 100644 src/chunkSpeed.cc create mode 100644 src/convert2native.cc create mode 100644 src/copyperf.cc create mode 100644 src/ffio.c create mode 100644 src/ioconvert.cc create mode 100644 src/ioinfo.cc create mode 100644 src/rawSpeed.cc create mode 100644 src/testBigWriter.cc create mode 100644 src/testChunkWriter.cc create mode 100644 src/testSockread.cc create mode 100644 src/testSockwrite.cc create mode 100644 src/testWriter.cc create mode 100644 src/testallocation.cc create mode 100644 src/testhdfReader.cc create mode 100644 src/testio.cc create mode 100644 src/testllReader.cc create mode 100644 src/testllWriter.cc create mode 100644 src/vatoi.cc create mode 100644 src/vatoi.hh create mode 100644 src/writef77.f create mode 100644 src/xmlview.cc diff --git a/src/AMRPlus/AMRPlusConv.C b/src/AMRPlus/AMRPlusConv.C new file mode 100644 index 0000000..7785342 --- /dev/null +++ b/src/AMRPlus/AMRPlusConv.C @@ -0,0 +1,168 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.00 + +#include +#include +#include +#include +#include +#include "IEEEIO.hh" +#include "AmrFileReader.hh" +#include "AMRwriterPlus.h" +#include "AMRgridPlus.h" + + + +int main(int argc, char** argv) { + IObase *ifile, *ofile; + AMRwriterPlus *writer; + AmrGridReader *reader; + AmrFileReader *freader; + int maxlev; + + if (argc!=2){ + cerr<<"Usage: addscalars "<isValid()){ + cerr<nLevels(); + + reader=new AmrGridReader(*ifile); + if (reader==NULL){ + cerr<isValid()){ + cerr<<"Cannot create "<getNumGrids(); + unsigned long datasz; + + + //prime things: + reader->getGridInfo(grid, 0); + grid.data=malloc(grid.nbytes); + datasz=grid.nbytes; + FlexArray< AmrGrid> gridlist; + + + int tmin, tmax; + int numlev = freader->getNumLevels(); + FlexArray levmask; + int lcnt=numlev, tflag=2, tstep=0; + double t1, t2, tdiff=0, finetimeref=1.0; + int ts1; + levmask.setSize(numlev); + for(int ii=0;iigetGridInfo(grid, idx))!=NULL && (lcnt || tflag)){ + IObase::DataType atype; + int length; + int attrnum; + + if ((grid.level==0) && tflag){ + //Getll the time of root grid... + double tm; + attrnum=ifile->readAttributeInfo("time",atype,length); + if(attrnum>=0) ifile->readAttribute(attrnum,&tm); + if (tflag==2){ + t1=tm; + ts1=grid.timestep; + tflag=1; + } else { //tflag==1; + t2=tm; + tdiff=(t2-t1)/(grid.timestep-(float)ts1); + tstep=grid.timestep; + if (tdiff!=0) tflag=0; + } + + } + //If this is a level we havent already seen... + if (levmask[grid.level]==0){ + //Get all the refinement info... + attrnum=ifile->readAttributeInfo("time_refinement",atype,length); + if(attrnum>=0){ + ifile->readAttribute(attrnum,&(grid.timeref)); + } + attrnum=ifile->readAttributeInfo("spatial_refinement",atype,length); + if(attrnum>=0){ + ifile->readAttribute(attrnum,&(grid.spaceref)); + } + attrnum=ifile->readAttributeInfo("grid_placement_refinement",atype,length); + if(attrnum>=0){ + ifile->readAttribute(attrnum,&(grid.placeref)); + } + //feed the refinement info to the writer... + writer->setLevelRefinement(grid.level, + grid.timeref, grid.spaceref, grid.placeref); + //and mark the level as done. + + if (grid.level==numlev-1)finetimeref=grid.timeref; + levmask[grid.level]=1; + lcnt--; + } + idx++; + } + tdiff/=finetimeref; + + //Coarse steps should be composed of + if (finetimeref!=tstep &&(tstep!=0)){ + cout<<"Mismatch between max time refinement and timesteps"<getTimeRange(tmin, tmax); + ii=0; + + tgrid=reader->getGridInfo(grid, 0); + writer->setType((IObase::DataType)grid.datatype); + writer->setTopLevelParameters(grid.rank, grid.origin, grid.delta, tdiff, maxlev); + + + while (tgrid!=NULL){ + if (grid.nbytes>datasz) { + datasz=grid.nbytes; + grid.data=realloc(grid.data, datasz); + } + reader->getGridData(grid, ii); + if (fixtime) grid.timestep/=fixtimeval; + + + + writer->write(&grid, 1); //calc scalars & write + ii++; + tgrid=reader->getGridInfo(grid, ii); + + } + delete ifile; + delete ofile; + + +} diff --git a/src/AMRPlus/AMRTree.C b/src/AMRPlus/AMRTree.C new file mode 100644 index 0000000..9ab86d1 --- /dev/null +++ b/src/AMRPlus/AMRTree.C @@ -0,0 +1,27 @@ +#include "AMRTree.h" + +void AMRNode::AMRNode(AMRgridPlus *first){ + subtimes.setsize(first->timeref) +} +void AMRNode::buildtree(AMRTree *t, int &idx){ + AMRgridPlus *g=grids.getData+idx; + int clev=g->level; + int ctime=c->time; + while (g->level==clev && g->time=ctime){ + idxs.append(idx); + idx++; + } +} + + +AMRTree::AMRTree(GridArray *g): timenode{ + int numlevs=g[0].maxlevel+1; + int timeref=g[0].timerefinement; + int coarsestep=timeref< IntArray; + +typedef FlexArray GridArray + +typedef FlexArray IdxArray; + +class AMRTree; +struct AMRNode{ + IdxArray idxs; + AMRTree subtimes; +}; + +class AMRTree: protected FlexArray{ + void buildtree(AMRTree *t, int &idx); + public: + AMRTree(GridArray *); + ~AMRTree(); + + private: + AMRNode timenode; + GridArray grids; +}; + + +#endif diff --git a/src/AMRPlus/AMRfilereaderPlus.C b/src/AMRPlus/AMRfilereaderPlus.C new file mode 100644 index 0000000..17d0e45 --- /dev/null +++ b/src/AMRPlus/AMRfilereaderPlus.C @@ -0,0 +1,175 @@ +#include +#include +#include "AMRfilereaderPlus.h" +#include "FlexArrayTmpl.H" +void AMRfilereaderPlus::printGridInfo(AMRgridPlus &g){ + printf("Grid level=%u step=%u maxtime=%u\n",g.level,g.timestep,g.maxtime); + printf("\trank=%u dims[",g.rank); + for(int i=0;i(v))?(u):(v);} +#define MINIMIZE(u, v) {(u)=((u)<(v))?(u):(v);} + +void AMRfilereaderPlus::buildInfoTable(){ + // Load all grids Info + int index=0; + AMRgridPlus g; + while(getGridInfo(g,index++)){ + if(this->debug) printf("buildInfoTable: getGrid index=%u\n",index); + if(this->debug) printGridInfo(g); + int i=grids.getSize(); + g.data=0; // zero out the data + if(g.level>maxlevel) + maxlevel=g.level; + if(!i){ + smin=g.scalarmin; + smax=g.scalarmax; + mintime = g.timestep; + maxtime = g.timestep; + maxtimeres = g.timerefinement; + maxlevel= g.level; + bounds[0]=g.origin[0]; + bounds[1]=g.origin[0]+g.delta[0]*g.dims[0]; + bounds[2]=g.origin[1]; + bounds[3]=g.origin[1]+g.delta[1]*g.dims[1]; + bounds[4]=g.origin[2]; + bounds[5]=g.origin[2]+g.delta[2]*g.dims[2]; + } + else{ + MINIMIZE(smin, g.scalarmin); + MAXIMIZE(smax, g.scalarmax); + if (g.level==0){ + MINIMIZE(bounds[0], g.origin[0]); + MAXIMIZE(bounds[1], g.origin[0]+g.delta[0]*g.dims[0]); + MINIMIZE(bounds[2], g.origin[1]); + MAXIMIZE(bounds[3], g.origin[1]+g.delta[1]*g.dims[1]); + MINIMIZE(bounds[4], g.origin[2]); + MAXIMIZE(bounds[5], g.origin[2]+g.delta[2]*g.dims[2]); + } + } + if(g.timestepmaxtime) + maxtime=g.timestep; + if(g.timerefinement>maxtimeres) + maxtimeres=g.timerefinement; + grids.append(g); + } +} + +void AMRfilereaderPlus::loadGrids(){ + if(!gridloading) return; + for(int i=0;idebug) printf("buildInfoTable: getGrid index=%u activegridindex %u\n",i,activeGrids[i]); + if(this->debug) printGridInfo(grids[activeGrids[i]]); + getGridData(grids[activeGrids[i]],activeGrids[i]); + } +} + +void AMRfilereaderPlus::reclaimGrids(){ + if(!gridloading) return; + for(int i=0;imaxtime){ + printf("timestep %u is out of range %u:%u\n", + timestep,mintime,maxtime); + return; + } + activeGrids.purge(); + current_time=timestep; + if(this->debug) printf("setTime(%u): mintime=%u maxtime=%u\n",current_time,mintime,maxtime); + for(int i=0;idebug) printf("\tgrids[%u].timestep=%u maxtime=%u\n",i,grids[i].timestep, + grids[i].maxtime); + if(current_time>=grids[i].timestep && + current_timedebug) printf("\t\tAppendGrid number %u\n",i); + } + } + if(this->debug) puts("load grids"); + loadGrids(); + if(this->debug) puts("reclaim grids"); + reclaimGrids(); +} + +void AMRfilereaderPlus::showAllLevels(){ + for(int i=0;i &g){ + g.setSize(activeGrids.getSize()); + for(int i=0;i +#include +#include "AMRgridreaderPlus.h" +#include "FlexArrayTmpl.H" + +class AMRfilereaderPlus : public AMRgridreaderPlus { +protected: + int gridloading; + FlexArray activeGrids; + FlexArray grids; + FlexArray levelmask; + IObase::DataType datatype; + int maxlevel,maxtimeres,mintime,maxtime; + double smax, smin; + double bounds[6]; + int current_time; + // Internal Utility methods + void buildInfoTable(); + void loadGrids(); + void reclaimGrids(); + void purgeGrids(); + void printGridInfo(AMRgridPlus &g); +public: + int debug; + void printGridInfo(); + void printActiveGrids(); + AMRfilereaderPlus(IObase &f); + int getNumLevels(){ return maxlevel+1; } + void getTimeRange(int &min,int &max){ + min=mintime; + max=maxtime; + } + void getScalarRange(double &min, double &max){ + min=smin;max=smax; + } + void getBounds(double *bnds){for (int ii=0;ii<6;ii++){bnds[ii]=bounds[ii];}} + void setTime(int timestep); + // starts out with all selected + void showLevel(int level=-1){ // default is all (-1) + if(level>=levelmask.getSize() || level<0){ + printf("AmrConvert::showLevel(%u) : Level out of range 0:%u\n", + level,levelmask.getSize()-1); + } + else + levelmask[level]=1; + } + void showAllLevels(); + void hideAllLevels(){for (int ii=0;ii=levelmask.getSize() || level<0){ + printf("AmrConvert::showLevel(%u) : Level out of range 0:%u\n", + level,levelmask.getSize()-1); + } + else + levelmask[level]=0; + } + int nLevels(){ return maxlevel+1; } + IObase::DataType getDataType(){return datatype;} + // For C interface + int getNumGrids(){ // number of active grids + return activeGrids.getSize(); + } + int getActiveIndex(int ii){ return activeGrids[ii];} + int getGrids(AMRgridPlus *g); + // For C++ interface + int getGrids(FlexArray &g); + void setDataLoadingOff(){ gridloading=0; purgeGrids();} + void setDataLoadingOn(){ gridloading=1; loadGrids();} +}; + +#endif diff --git a/src/AMRPlus/AMRgridPlus.h b/src/AMRPlus/AMRgridPlus.h new file mode 100644 index 0000000..b8f866c --- /dev/null +++ b/src/AMRPlus/AMRgridPlus.h @@ -0,0 +1,21 @@ +#ifndef __AMR_GRID_HH_ +#define __AMR_GRID_HH_ +#include "AmrGrid.h" +#include "flexset.h" + +struct AMRgridPlus : public AmrGrid { + double time; + int timeref, spaceref[3], placeref[3]; + double scalarmin,scalarmax; +}; + +struct idxrec{ + int idx; + idxrec(int first=0){idx=first;} + int operator<(const idxrec &other)const {return idx IdxSet; +typedef flexarray GridArray; +#endif diff --git a/src/AMRPlus/AMRgridreaderPlus.C b/src/AMRPlus/AMRgridreaderPlus.C new file mode 100644 index 0000000..de131d3 --- /dev/null +++ b/src/AMRPlus/AMRgridreaderPlus.C @@ -0,0 +1,90 @@ +#include "AMRgridreaderPlus.h" +#include +#include +#include + + + + + +AMRgridPlus *AMRgridreaderPlus::getGridInfo(AMRgridPlus &g,int index){ + g.dataveclen=1; + if(file.seek(index)=0){ + int lev; // should be Int level + file.readAttribute(attrnum,&lev); + if(lev>g.maxlevel) g.maxlevel=lev; + g.level=lev; + } + attrnum=file.readAttributeInfo("time",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.time)); + }attrnum=file.readAttributeInfo("time_refinement",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.timerefinement)); + } + attrnum=file.readAttributeInfo("timestep",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.timestep)); + } + attrnum=file.readAttributeInfo("origin",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.origin)); + attrnum=file.readAttributeInfo("delta",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.delta)); + attrnum=file.readAttributeInfo("persistence",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.persistence)); + g.maxtime = g.timestep + g.persistence; + } + + attrnum=file.readAttributeInfo("time_refinement",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.timeref)); + } + attrnum=file.readAttributeInfo("spatial_refinement",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.spaceref)); + } + attrnum=file.readAttributeInfo("grid_placement_refinement",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.placeref)); + } + + attrnum=file.readAttributeInfo("range",atype,length); + if(attrnum>=0){ + double range[2]; + file.readAttribute(attrnum,&range); + g.scalarmin=range[0]; g.scalarmax=range[1]; + } + else { + cout<<"Please convert this file with AMRPlusConv"< +#include "AMRgridPlus.h" +#include "IEEEIO.hh" + + +class AMRgridreaderPlus { +protected: + IObase &file; + +public: + AMRgridreaderPlus(IObase &f) : file(f){}; + ~AMRgridreaderPlus(){}; + + /* + * Low level grid/info fetching routines + */ + AMRgridPlus *getGrid(AMRgridPlus &g,int index){ + if(file.seek(index)getGrid(*g,index); + } + + AMRgridPlus *getGridInfo(AMRgridPlus &g,int index); + AMRgridPlus *getGridData(AMRgridPlus &g,int index); + + + + +}; + + +#endif diff --git a/src/AMRPlus/AMRreaderPlus.C b/src/AMRPlus/AMRreaderPlus.C new file mode 100644 index 0000000..bc47e7b --- /dev/null +++ b/src/AMRPlus/AMRreaderPlus.C @@ -0,0 +1,122 @@ +#include "AMRreaderPlus.h" +#include +#include +#include +#include + + +AMRreaderPlus::AMRreaderPlus(IObase &f) : AMRgridreaderPlus(f), grids(), + activeset(), timemask(), levelmask(), realtimes() +{ + init(); + selectTimeStep(0); + for (int ii=0;ii<=maxlevel;ii++) showLevel(ii); + modflag=1; +} + + + +AMRreaderPlus::~AMRreaderPlus(){ + +} + + + +void AMRreaderPlus::init(){ + maxlevel=maxtimeres=maxtime=0; + smin=smax=0.0; + numgrids=0; + + build_info(); +} +void AMRreaderPlus::build_info(){ + AMRgridPlus *res, newg; + res=getGridInfo(newg, 0); + if (res==NULL) return; + maxlevel=0; + maxtime=0; + numgrids=0; + smin=newg.scalarmin; + smax=newg.scalarmax; + datatype=newg.datatype; + while (res!=NULL){ //Load all grid info + grids.append(newg); + realtimes.insert(newg.time); + maxlevel=(maxlevel>newg.level)?maxlevel:newg.level; + maxtime=(maxtime>newg.timestep)?maxtime:newg.timestep; + smax=smax>newg.scalarmax?smax:newg.scalarmax; + smin=smin (maxlevel+1, maxtime+1); + + AMRgridPlus *g= grids.getData(0); + for(int ii=0;iitimestep;jjtimestep+g->persistence;jj++){ + if (jj<=maxtime){ + idxrec trec(ii); + (*leveltimes)(g->level, jj).append(trec.idx); + } + } + g++; + } + + cout< +#include +#include +#include "AMRgridreaderPlus.h" +#include "IEEEIO.hh" + +#include "flexmatrix.h" +#include "flexset.h" +#define kNoData 0 +#define kHasData 1 + +/* Method for calculating scalar range - the global range, +range per fine timestep, per coarse, or per (current) root. */ +typedef enum {kGlobal,kFine,kCoarse,kRoot} ScalarMode; + +using namespace std; + + + +typedef flexarray IntArray; + + + +typedef flexarray IdxArray; + + +class AMRreaderPlus : public AMRgridreaderPlus { + public: + int datatype; + int numgrids; + int maxlevel,maxtimeres,maxtime; + double smin,smax; + int modflag; + + IdxSet activeset; + flexset realtimes; + flexmatrix *leveltimes; + GridArray grids; + IntArray levelmask, timemask; + + void init(); + void build_info(); + void build_active(); + void modify(); //Flag that tells when active set has changed +public: + AMRreaderPlus(IObase &f); + ~AMRreaderPlus(); + + int getNumLevels(){return maxlevel+1;} + int getNumTimesteps(){return maxtime+1;} + int getNumGrids(){return numgrids;} + int getDataType(){return datatype;} + + void showTimeStep(int ts){ + if (ts>=0 && ts<=maxtime) {timemask[ts]=1; modify();} + else cout<<"Timestep out of range: "<=0 && ts<=maxtime) {timemask[ts]=0; modify();} + else cout<<"Timestep out of range: "<=0 && lev<=maxlevel) {levelmask[lev]=1; modify();} + else cout<<"Level out of range: "<=0 && lev<=maxlevel) {levelmask[lev]=0; modify();} + else cout<<"Level out of range: "<dtypeID){ + case IObase::Byte:{ + char *dptr=(char *)data; + curscalarmin=curscalarmax=*dptr; + for (long kk=0;kk=dptr[kk])?curscalarmax:dptr[kk]; + } + } break; + case IObase::Float32:{ + float *fptr=(float *)data; + curscalarmin=curscalarmax=*fptr; + for (long jj=0;jj=fptr[jj])?curscalarmax:fptr[jj]; + } + } break; + case IObase::Float64:{ + double *dptr=(double *)data; + curscalarmin=curscalarmax=*dptr; + for (long kk=0;kk=dptr[kk])?curscalarmax:dptr[kk]; + } + } break; + } +} + + +void AMRwriterPlus::writePlusattributes(){ + double range[2]; + range[0]=curscalarmin; + range[1]=curscalarmax; + file.writeAttribute("range", IObase::Float64, 2, range); + scalarFlag=0; //reset the flag +} diff --git a/src/AMRPlus/AMRwriterPlus.h b/src/AMRPlus/AMRwriterPlus.h new file mode 100644 index 0000000..a3c47ff --- /dev/null +++ b/src/AMRPlus/AMRwriterPlus.h @@ -0,0 +1,70 @@ +#include "AMRwriter.hh" +#include "AMRgridPlus.h" + +/* + * AMRwriterPlus: + * A subclass of AMRwriter which adds a scalar range attribute + * to each dataset. The AMRwriter interface is unchanged, however + * for convenience, you can: + * + * Set the top level parameters or write a dataset by passing a + * pointer to an AMRgridPlus datastructure to ::setTopLevelParameters + * or ::write respectively + * + * Set the scalar range of the dataset explicitly (before writing) + * with ::setScalarRange. If this is not called, the scalar range will + * be computed from within ::write. Useful (and timesaving) if you + * have already computed the range. + */ + +class AMRwriterPlus : public AMRwriter{ + public: + AMRwriterPlus(IObase &descriptor); + + virtual void setTopLevelParameters(AMRgridPlus *g){ + AMRwriter::setTopLevelParameters(g->rank, g->origin, g->delta, \ + g->timestep, g->maxlevel); + } + + // CC forces me to re-overload this inherited method! + virtual void setTopLevelParameters(int rank,double *origin, + double *delta,double timestep,int maxdepth){ + AMRwriter::setTopLevelParameters(rank, origin, delta, timestep, maxdepth); + } + + void setScalarRange(double smin,double smax){ + curscalarmin=smin;curscalarmax=smax;scalarFlag=1;} + + void write(int *origin,int *dims,void *data){ + AMRwriter::write(origin, dims, data); + if (!scalarFlag) calcScalarRange(data); + writePlusattributes(); + } + void write(float *origin,int *dims,void *data){ + AMRwriter::write(origin, dims, data); + if (!scalarFlag) calcScalarRange(data); + writePlusattributes(); + } + void write(double *origin,int *dims,void *data){ + AMRwriter::write(origin, dims, data); + if (!scalarFlag) calcScalarRange(data); + writePlusattributes(); + } + + virtual void write(AMRgridPlus *g, int calcscalars=0){ + + setType((IObase::DataType)g->datatype); + setLevel(g->level); + setTime(g->timestep); + write(g->origin, g->dims, g->data); + } + + protected: + void writePlusattributes(); + + private: + void calcScalarRange(void *data); + + double curscalarmin, curscalarmax; + int scalarFlag; +}; diff --git a/src/AMRPlus/Dpndfile b/src/AMRPlus/Dpndfile new file mode 100644 index 0000000..1535d4b --- /dev/null +++ b/src/AMRPlus/Dpndfile @@ -0,0 +1,193 @@ +AMRwriterPlus.o: AMRwriterPlus.C AMRwriterPlus.h \ + /home/jshalf/Develop/FlexIO/AMRwriter.hh \ + /home/jshalf/Develop/FlexIO/Arch.h /usr/include/sys/types.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/gnu/stubs.h /usr/include/bits/types.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h \ + /usr/include/string.h /home/jshalf/Develop/FlexIO/IO.hh \ + /home/jshalf/Develop/FlexIO/IO.h \ + /home/jshalf/Develop/FlexIO/Writer.hh \ + /home/jshalf/Develop/FlexIO/Writer.h \ + /home/jshalf/Develop/FlexIO/FlexArrayTmpl.H \ + /home/jshalf/Develop/FlexIO/AMRwriter.h AMRgridPlus.h \ + /home/jshalf/Develop/FlexIO/AmrGrid.h flexset.h flexarrays.h \ + /usr/include/stdlib.h /usr/include/alloca.h +AMRgridreaderPlus.o: AMRgridreaderPlus.C AMRgridreaderPlus.h \ + /home/jshalf/Develop/FlexIO/IO.hh /home/jshalf/Develop/FlexIO/Arch.h \ + /usr/include/sys/types.h /usr/include/features.h \ + /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \ + /usr/include/bits/types.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/include/time.h /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h \ + /usr/include/string.h /home/jshalf/Develop/FlexIO/IO.h AMRgridPlus.h \ + /home/jshalf/Develop/FlexIO/AmrGrid.h flexset.h flexarrays.h \ + /usr/include/stdlib.h /usr/include/alloca.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.hh /usr/include/stdio.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stdarg.h \ + /usr/include/libio.h /usr/include/_G_config.h \ + /usr/include/bits/stdio_lim.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \ + /usr/include/getopt.h /usr/include/sys/file.h /usr/include/fcntl.h \ + /usr/include/bits/fcntl.h \ + /home/jshalf/Develop/FlexIO/IEEEIOWinDllApi.h \ + /home/jshalf/Develop/FlexIO/FlexArrayTmpl.H /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/strings.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/iostream.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/streambuf.h +AMRfilereaderPlus.o: AMRfilereaderPlus.C /usr/include/stdio.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/gnu/stubs.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stdarg.h \ + /usr/include/bits/types.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/bits/stdio_lim.h \ + /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \ + /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h \ + /usr/include/alloca.h AMRfilereaderPlus.h \ + /home/jshalf/Develop/FlexIO/IO.hh /home/jshalf/Develop/FlexIO/Arch.h \ + /usr/include/string.h /home/jshalf/Develop/FlexIO/IO.h \ + AMRgridreaderPlus.h AMRgridPlus.h \ + /home/jshalf/Develop/FlexIO/AmrGrid.h flexset.h flexarrays.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.hh /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \ + /usr/include/getopt.h /usr/include/sys/file.h /usr/include/fcntl.h \ + /usr/include/bits/fcntl.h \ + /home/jshalf/Develop/FlexIO/IEEEIOWinDllApi.h \ + /home/jshalf/Develop/FlexIO/FlexArrayTmpl.H /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/strings.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.h +flexset.o: flexset.C flexset.h flexarrays.h /usr/include/string.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/gnu/stubs.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/include/stdlib.h /usr/include/sys/types.h \ + /usr/include/bits/types.h /usr/include/time.h /usr/include/endian.h \ + /usr/include/bits/endian.h /usr/include/sys/select.h \ + /usr/include/bits/select.h /usr/include/bits/sigset.h \ + /usr/include/sys/sysmacros.h /usr/include/alloca.h +AMRreaderPlus.o: AMRreaderPlus.C AMRreaderPlus.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/set \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_tree.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_algobase.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_config.h \ + /usr/include/_G_config.h /usr/include/bits/types.h \ + /usr/include/features.h /usr/include/sys/cdefs.h \ + /usr/include/gnu/stubs.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_relops.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_pair.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/type_traits.h \ + /usr/include/string.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/limits.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/syslimits.h \ + /usr/include/limits.h /usr/include/bits/posix1_lim.h \ + /usr/include/bits/local_lim.h /usr/include/linux/limits.h \ + /usr/include/bits/posix2_lim.h /usr/include/stdlib.h \ + /usr/include/sys/types.h /usr/include/time.h /usr/include/endian.h \ + /usr/include/bits/endian.h /usr/include/sys/select.h \ + /usr/include/bits/select.h /usr/include/bits/sigset.h \ + /usr/include/sys/sysmacros.h /usr/include/alloca.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/new.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/new \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/exception \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/iostream.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/streambuf.h \ + /usr/include/libio.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stdarg.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_iterator.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_alloc.h \ + /usr/include/assert.h /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/bits/sched.h /usr/include/bits/time.h \ + /usr/include/signal.h /usr/include/bits/pthreadtypes.h \ + /usr/include/bits/sigthread.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_construct.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_function.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_set.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_multiset.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/vector \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_uninitialized.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_vector.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_bvector.h \ + /home/jshalf/Develop/FlexIO/IO.hh /home/jshalf/Develop/FlexIO/Arch.h \ + /home/jshalf/Develop/FlexIO/IO.h AMRgridreaderPlus.h AMRgridPlus.h \ + /home/jshalf/Develop/FlexIO/AmrGrid.h flexset.h flexarrays.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.hh /usr/include/stdio.h \ + /usr/include/bits/stdio_lim.h /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \ + /usr/include/getopt.h /usr/include/sys/file.h /usr/include/fcntl.h \ + /usr/include/bits/fcntl.h \ + /home/jshalf/Develop/FlexIO/IEEEIOWinDllApi.h \ + /home/jshalf/Develop/FlexIO/FlexArrayTmpl.H /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/strings.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.h flexmatrix.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/algorithm \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_tempbuf.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_algo.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_heap.h +readtest.o: readtest.C /usr/include/stdio.h /usr/include/features.h \ + /usr/include/sys/cdefs.h /usr/include/gnu/stubs.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stddef.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/stdarg.h \ + /usr/include/bits/types.h /usr/include/libio.h \ + /usr/include/_G_config.h /usr/include/bits/stdio_lim.h \ + /usr/include/stdlib.h /usr/include/sys/types.h /usr/include/time.h \ + /usr/include/endian.h /usr/include/bits/endian.h \ + /usr/include/sys/select.h /usr/include/bits/select.h \ + /usr/include/bits/sigset.h /usr/include/sys/sysmacros.h \ + /usr/include/alloca.h /usr/include/math.h \ + /usr/include/bits/huge_val.h /usr/include/bits/mathdef.h \ + /usr/include/bits/mathcalls.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/float.h \ + /usr/include/string.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/iostream.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/streambuf.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.hh /usr/include/unistd.h \ + /usr/include/bits/posix_opt.h /usr/include/bits/confname.h \ + /usr/include/getopt.h /usr/include/sys/file.h /usr/include/fcntl.h \ + /usr/include/bits/fcntl.h \ + /home/jshalf/Develop/FlexIO/IEEEIOWinDllApi.h \ + /home/jshalf/Develop/FlexIO/IO.hh /home/jshalf/Develop/FlexIO/Arch.h \ + /home/jshalf/Develop/FlexIO/IO.h \ + /home/jshalf/Develop/FlexIO/FlexArrayTmpl.H /usr/include/sys/stat.h \ + /usr/include/bits/stat.h /usr/include/strings.h \ + /home/jshalf/Develop/FlexIO/IEEEIO.h AMRreaderPlus.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/set \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_tree.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_algobase.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_config.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_relops.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_pair.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/type_traits.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/limits.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/syslimits.h \ + /usr/include/limits.h /usr/include/bits/posix1_lim.h \ + /usr/include/bits/local_lim.h /usr/include/linux/limits.h \ + /usr/include/bits/posix2_lim.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/new.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/new \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/include/exception \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_iterator.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_alloc.h \ + /usr/include/assert.h /usr/include/pthread.h /usr/include/sched.h \ + /usr/include/bits/sched.h /usr/include/bits/time.h \ + /usr/include/signal.h /usr/include/bits/pthreadtypes.h \ + /usr/include/bits/sigthread.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_construct.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_function.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_set.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_multiset.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/vector \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_uninitialized.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_vector.h \ + /usr/lib/gcc-lib/i586-mandrake-linux/2.95.2/../../../../include/g++-3/stl_bvector.h \ + AMRgridreaderPlus.h AMRgridPlus.h \ + /home/jshalf/Develop/FlexIO/AmrGrid.h flexset.h flexarrays.h \ + flexmatrix.h diff --git a/src/AMRPlus/FlexSetTempl.h b/src/AMRPlus/FlexSetTempl.h new file mode 100644 index 0000000..27f0d84 --- /dev/null +++ b/src/AMRPlus/FlexSetTempl.h @@ -0,0 +1,20 @@ +#ifndef FLEXSETTEMPL_H +#define FLEXSETTEMPL_H + +template +class FlexSetOrdered{ + FlexArray arr; + + FlexSetOrdered() : arr(){}; + + int insert(T &item){ + int a=0;b=getSize()-1, c; + if (arr[a]==item || arr[b]==item) return 0; + while (a!=b){ + c=(a+b)/2; + if (arr[c]==item) return 0; + if (arr[c] +#include +#include +#include +#include +#include "IEEEIO.hh" +#include "AMRfilereaderPlus.h" + + + +int main(int argc, char** argv) { + IObase *ifile, *ofile; + AMRfilereaderPlus *reader; + + if (argc!=2){ + cerr<<"Usage: "<isValid()){ + cerr<setTime(0); + for (ii=0;iigetNumGrids();ii++){ + reader->getGrid(grid, reader->getActiveIndex(ii)); + cout<<"Level: "< +#include +//For Shared Objects: +//#include "SafeList.h" +//#define TAG :public shObj +//#define GetMem CAVEMalloc +//#define FreeMem CAVEFree +//For Non-shared Objects: +#define TAG + +/* An flexarray is a dynamic flexarray of objecs. No upper limit, + * the ability to add and remove objects on the fly, etc. + * + * Rundown of routines: + * Constructor - initializes an empty flexarray with increment 10 + * Destructor - Deletes the flexarray. Does NOT delete objects in the flexarray + * copy constructor/ = :deep copy (override X::operator= if you need + * deep copies of the elements) + * + * Information: + * int getLength()/getSize() - returns #objects + * int getActualSize() - returns #slots allocated + * int getIncrement() - returns #slots allocated at a time + * int empty() - true if no elts + * + * Access: + * X& [idx] - return indexed reference, unsafe + * X* getData(idx) - Ptr to indexed elt. + * X* getDataConst - same as above, but everything is const qualified + * + * Manip: + * setIncrement(int) - + * clear() - empties the array + * fill(X&, N) - sets the array to N copies of the X + * setData(X&, idx) - change entry at index + * insertElement(X&, idx) - insert element BEFORE index + * (if index=-1, append element); + * append(X&) - duh. + * InsertElements(start, X*, N) - insert #elements before + * start... read values from X*. + * removeElements(start, N) - remove N elements starting with start + */ + +template +class flexarray TAG { + int Length, Size, Increment; + X* data; + + public: + flexarray(){Length=Size=0; Increment=10;data=NULL;} + flexarray(const flexarray &src){ + Length=src.Length;Size=src.Size;Increment=src.Increment; + if (Size==0) data=NULL; + else { + data=getNewArray(Size); + memcpy(this->data, src.data, this->Length*sizeof(X)); + } + } + ~flexarray(){if (data) delete[] data;} + + flexarray &operator=(const flexarray &src){ + if (data!=NULL) delete[] data; + Length=src.Length;Size=src.Size;Increment=src.Increment; + if (Size==0) data=NULL; + else { + data=getNewArray(Size); + memcpy(this->data, src.data, this->Length*sizeof(X)); + } + return *this; + } + + int getActualSize() const{return Size;} + int getSize() const{return Length;} + int getLength() const{return Length;} + int getIncrement() const{return Increment;} + int empty() const{return (Size==0);} + + + + const X & operator()(int idx) const{return data[idx];} + X & operator[](int idx) const{return data[idx];} + + X* getData(int idx)const{ + if (idx==-1) idx=Length-1; + if (idx>=0 && idx=0 && idx=0 && idxLength) return; + if (startidx==-1) startidx=Length; + if (this->data==NULL) data=getNewArray(Increment); + if (Size0) + memcpy(tflexarray, data, startidx*sizeof(X)); + if (startidx=Length) return; + if (startidx==-1) startidx=Length-1; + if (startidx+howmany>=Length) howmany=Length-startidx; + memcpy(data+startidx, data+startidx+howmany, + (Length-(startidx+howmany))*sizeof(X)); + Length-=howmany; + } + + + private: + X* getNewArray(int newSize){ + return new X [newSize]; + } + + void resizeArray(int startidx, int numelts){ + int NSize=Length+numelts; + if (NSize>Size){ + Size=Increment * (NSize/Increment +1); + X* tflexarray=getNewArray(Size); + if (startidx>0) + memcpy(tflexarray, data, startidx*sizeof(X)); + if (startidx + +template +class flexmatrix{ + X* data; + int M, N; + + public: + flexmatrix(int m, int n){ + M=m;N=n; if (M*N==0) cout<<"Serious Problem! "< +void setunion(const flexset &A, const flexset &B,flexset &result){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + + if (A.empty()) {result=B;return;} + if (B.empty()) {result=A;return;} + result.clear(); + do { + //I dont like to rely on shortcut boolean operators, so + //that's why I use double ifs + + X *whichadd=NULL; //1,2,3 (A,B, or both) + if (idxA +void setunion(flexset &A, const flexset &B){ + flexset tmp=A; + setunion(tmp, B, A); +} + + +template +void setintersection(const flexset &A, const flexset &B,flexset &result){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + + result.clear(); + if (A.empty() || B.empty()) return; //result={} + do { + //I dont like to rely on shortcut boolean operators, so + //that's why I use double ifs + + X *whichadd=NULL; //1,2,3 (A,B, or both) + if (idxA +void setsymmetricdifference(const flexset &A, const flexset &B,flexset &result){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + if (A.empty()) {result.clear(); return;} + if (B.empty()) {result=A;return;} + result.clear(); + do { + //I dont like to rely on shortcut boolean operators, so + //that's why I use double ifs + + X *whichadd=NULL; //1,2,3 (A,B, or both) + if (idxA +void setdifference(const flexset &A, const flexset &B,flexset &result){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + if (A.empty()) {result=A; return;} + if (B.empty()) {result=A;return;} + result.clear(); + do { + //I dont like to rely on shortcut boolean operators, so + //that's why I use double ifs + + X *whichadd=NULL; //1,2,3 (A,B, or both) + if (idxA +void setdifferences(const flexset &A, const flexset &B,flexset &AMB,flexset &BMA){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + if (A.empty()) {AMB.clear();BMA=B; return;} + if (B.empty()) {BMA.clear();AMB=A;return;} + AMB.clear(); + BMA.clear(); + do { + X *whichaddA=NULL; + X *whichaddB=NULL; + if (idxA +void setconvert(flexset &A, const flexset &B){ + int idxA=0, idxB=0; + int sizeA=A.getSize(), sizeB=B.getSize(); + if (A.empty()) {return;} + if (B.empty()) { + cout<<"SetConvert - UHOH! A is not contained in B!"< &x, int (* test)(X& y)) - creates a subset consisting + * of all elements in the set for which 'test' returns true. + * + * Operations: + * [all of form: set(X& A, X& B, X& result){ result= A B}] + * setunion(A=AUB, or C=AUB), setintersection, setdifference, setsymmetricdifference + * setdifferences (returns A-B and B-A in one go) + * NOTE: The result of intersection or difference will consist only + * of items taken from A. (Important if you are comparing sets with + * similar keys and dissimilar data + */ + +/* +class flexset; +template setiter{ + public: + setiter(flexset *nset){itsset=nset; idx=(nset->empty())?-1:0;} + + operator++(){idx++; if (idx>itsset->getSize()-1) idx=-1;} + operator--(){idx--; if (idx<0) idx=-1;} + int ok(){return idx!=-1;} + + X &operator*(){if (idx==-1) return itsset[0]; return itsset[idx];} + + private: + flexset *itsset; + int idx; +} +*/ + + +template +class flexset : protected flexarray{ + public: + flexset(): flexarray(){}; + flexset(const flexset &src): flexarray(src){}; + ~flexset(){}; + //by all accounts, this should inherit flexarray operator= + + int getSize() const{return flexarray::getSize();} + int findpos(const X &elt, int start=0, int end=-1) const{ + if (start<0) start=0; + if (end==-1) end=getLength()-1; + + int a=start, b=end, e; + if (empty()) return 0; + if (elt<(*this)(a)) return a; + if (elt==(*this)(a)) return a; //don't depend on <= being implemented + if (elt==(*this)(b)) return b; + if (!(elt<(*this)(b))) return b+1; //given above line, equiv to elt>data[b] + + if ((a+b)&1) e=(a+b+1)/2; //e odd + else e=(a+b)/2; + while ((b-a>1)){ + if (elt==(*this)(e)) return e; + + if (elt<(*this)(e)) b=e; + else a=e; + if ((a+b)&1) e=(a+b+1)/2; //e odd + else e=(a+b)/2; + } + if (elt<(*this)(e)) return e; + if (elt==(*this)(e)) return e; + else return e+1; + + } +//If elt is in the set, return its index, otherwise return -1 + int find(const X &elt, int start=0, int end=-1) const{ + if (empty()) return -1; + int result=findpos(elt, start, end); + if (result &iset) const{ + if (iset.empty()) return 1; //Empty set is in everything! + int a=find(iset(0)); + if (a<0)return 0; + for (int ii=1;ii::clear(); + } + + int empty() const {return flexarray::empty();} + + void buildSubset(flexset &A, int (* test)(const X&)){ + A.clear(); + for (int ii=0;ii=getSize()) return; + removeElements(idx, 1); + } + + void append(const X &elt){ + if (empty()) { + insertElement(elt, 0); + return; + } + X *tmp=&(*this)[getSize()-1]; + if ((*tmp) &A, const flexset &B,flexset &result); +friend +void setintersection(const flexset &A, const flexset &B,flexset &result); +friend +void setsymmetricdifference(const flexset &A, const flexset &B,flexset &result); +friend +void setdifference(const flexset &A, const flexset &B,flexset &result); +friend +void setdifferences(const flexset &A, const flexset &B,flexset &AMB,flexset &BMA); +friend +void setconvert(flexset &A, const flexset &B); +}; + +template +void setunion(const flexset &A, const flexset &B,flexset &result); + + +template +void setunion(flexset &A, const flexset &B); + +template +void setintersection(const flexset &A, const flexset &B,flexset &result); + + +template +void setsymmetricdifference(const flexset &A, const flexset &B,flexset &result); + +template +void setdifference(const flexset &A, const flexset &B,flexset &result); + +template +void setdifferences(const flexset &A, const flexset &B,flexset &AMB,flexset &BMA); + +template +void setconvert(flexset &A, const flexset &B); +#endif diff --git a/src/AMRPlus/gridreadtest.C b/src/AMRPlus/gridreadtest.C new file mode 100644 index 0000000..8321d2d --- /dev/null +++ b/src/AMRPlus/gridreadtest.C @@ -0,0 +1,40 @@ +// generated by Fast Light User Interface Designer (fluid) version 1.00 + +#include +#include +#include +#include +#include +#include "IEEEIO.hh" +#include "AMRgridreaderPlus.h" + + + +int main(int argc, char** argv) { + IObase *ifile, *ofile; + AMRgridreaderPlus *reader; + + if (argc!=2){ + cerr<<"Usage: "<isValid()){ + cerr<getGridInfo(grid, ii))!=NULL){ + cout<<"ScalarRange: "<err->msg_code = (code), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT3(cinfo,code,p1,p2,p3) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXIT4(cinfo,code,p1,p2,p3,p4) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (cinfo)->err->msg_parm.i[2] = (p3), \ + (cinfo)->err->msg_parm.i[3] = (p4), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) +#define ERREXITS(cinfo,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->error_exit) ((j_common_ptr) (cinfo))) + +#define MAKESTMT(stuff) do { stuff } while (0) + +/* Nonfatal errors (we can keep going, but the data is probably corrupt) */ +#define WARNMS(cinfo,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS1(cinfo,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) +#define WARNMS2(cinfo,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), -1)) + +/* Informational/debugging messages */ +#define TRACEMS(cinfo,lvl,code) \ + ((cinfo)->err->msg_code = (code), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS1(cinfo,lvl,code,p1) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS2(cinfo,lvl,code,p1,p2) \ + ((cinfo)->err->msg_code = (code), \ + (cinfo)->err->msg_parm.i[0] = (p1), \ + (cinfo)->err->msg_parm.i[1] = (p2), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) +#define TRACEMS3(cinfo,lvl,code,p1,p2,p3) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS4(cinfo,lvl,code,p1,p2,p3,p4) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS5(cinfo,lvl,code,p1,p2,p3,p4,p5) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMS8(cinfo,lvl,code,p1,p2,p3,p4,p5,p6,p7,p8) \ + MAKESTMT(int * _mp = (cinfo)->err->msg_parm.i; \ + _mp[0] = (p1); _mp[1] = (p2); _mp[2] = (p3); _mp[3] = (p4); \ + _mp[4] = (p5); _mp[5] = (p6); _mp[6] = (p7); _mp[7] = (p8); \ + (cinfo)->err->msg_code = (code); \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl)); ) +#define TRACEMSS(cinfo,lvl,code,str) \ + ((cinfo)->err->msg_code = (code), \ + strncpy((cinfo)->err->msg_parm.s, (str), JMSG_STR_PARM_MAX), \ + (*(cinfo)->err->emit_message) ((j_common_ptr) (cinfo), (lvl))) + +#endif /* JERROR_H */ diff --git a/src/AMRPlus/makefile b/src/AMRPlus/makefile new file mode 100644 index 0000000..56b24de --- /dev/null +++ b/src/AMRPlus/makefile @@ -0,0 +1,70 @@ +SRCS= \ + AMRwriterPlus.C \ + AMRgridreaderPlus.C \ + AMRfilereaderPlus.C \ + flexset.C \ + AMRreaderPlus.C + +OBJS = $(SRCS:.C=.o) +DEPEND = Dpndfile +#################### + +SHELL = /bin/sh + +IEEE_ROOT=/nfs/zeus/lcascr1/mahall/AmrProject/FlexIO + + +ALL_INC = -I$(IEEE_ROOT)/include -I$(HDF_ROOT)/include + + +DEFS = +CC = cc +#COMP_FLAGS = -n32 -mips4 -LNO -IPA -Ofast +COMP_FLAGS = -64 -mips4 -g + +CFLAGS = -c -float ${COMP_FLAGS} -DOPENGL \ + -I$(IEEE_ROOT)/include \ + -DVTK21 $(VTKINCD) -noinline -woff 1681-1682,3322 +CXXFLAGS = ${CFLAGS} + + +LINK = ${CPP} +LIBS = -L$(IEEE_ROOT)/lib -L$(HDF_ROOT)/lib -L. \ + -lhlio -lieeeio -lAMR \ + -lX11 -lm \ + -lGL -lICE -lXt + +.C: $@.o ${OBJS} + $(CXX) ${COMP_FLAGS} -o $@ \ + ${OBJS} $@.o $(LIBS) + + +include $(DEPEND) + +AMRPlusConv: AMRPlusConv.o libAMRPlus.a + $(CXX) ${COMP_FLAGS} -o $@ \ + $@.o -lAMRPlus $(LIBS) + +gridreadtest: gridreadtest.o libAMRPlus.a + $(CXX) ${COMP_FLAGS} -o $@ \ + $@.o -lAMRPlus $(LIBS) + +readtest: readtest.o libAMRPlus.a + $(CXX) ${COMP_FLAGS} -o $@ \ + $@.o -lAMRPlus $(LIBS) + +filereadtest:filereadtest.o libAMRPlus.a + $(CXX) ${COMP_FLAGS} -o $@ \ + $@.o -lAMRPlus $(LIBS) + +libAMRPlus.a: ${OBJS} + rm -f libAMRPlus + ar r libAMRPlus.a ${OBJS} + +dep: $(SRCS) + CC -M ${ALL_INC} $(SRCS) readtest.C > $(DEPEND) + smake + + +clean: + rm *.o diff --git a/src/AMRPlus/ordarrays.h b/src/AMRPlus/ordarrays.h new file mode 100644 index 0000000..b830984 --- /dev/null +++ b/src/AMRPlus/ordarrays.h @@ -0,0 +1,23 @@ +#include "arrays.h" + + + +template +class flexset : private array{ + public: + ordarray(): array(){}; + ~ordarray(){}; + int insert(const X &elt){ + int a=0, b=getLength()-1; + X* data=this->getData(0); + if (elt==data[0]) this->insertElement(elt, 0); + if (elt==data[b]) insertElement(elt, b); + int c=(a+b)/2; + while (elt!=data[c]){ + if (a==b) {insertElement(elt, a); return a;} + if (elt +#include +#include +#include +#include +#include "IEEEIO.hh" +#include "AMRreaderPlus.h" + + + +int main(int argc, char** argv) { + IObase *ifile, *ofile; + AMRreaderPlus *reader; + + if (argc!=2){ + cerr<<"Usage: "<isValid()){ + cerr<getActive(thegs); + + + for (int ii=0;iimaxlevel+1;jj++){ + cout<<"\nLevel #"<leveltimes)(jj, ii).getSize();kk++){ + cout<<" "<<(*reader->leveltimes)(jj, ii)[kk].idx; + } + } + } + */ + reader->loadData(); + delete ifile; + + + +} diff --git a/src/AMRPlus/settst.C b/src/AMRPlus/settst.C new file mode 100644 index 0000000..743791b --- /dev/null +++ b/src/AMRPlus/settst.C @@ -0,0 +1,59 @@ +#include +#include "flexset.h" +#include + +int iseven(const int &y){return !(y&1);} +struct orec; +struct irec{ + int key, data; + irec(int nkey=0, int ndata=0){key=nkey;data=ndata;} + int operator<(const irec &b) const{return key arr1, arr2, arr3, arr4, arr5; + flexset iarr1, iarr2; + irec tst; + int ii; + + for (ii=0;ii<20;ii++){ + tst.key=rand()%20; + tst.data=ii; + arr1.insert(tst); + } + + for (ii=0;ii<20;ii++){ + iarr1.insert(rand()%20); + } + + setdifferences(arr1, iarr1, arr2, iarr2); + for (ii=0;ii +#include +#include +#include +#include +#include "vtkAMRStructuredPointsReader.h" +vtkRenderer *renderer; +vtkRenderWindow* renWin; +vtkOutlineFilter *outline; +vtkContourFilter *contour; +vtkPolyDataMapper *outlineMapper; +vtkPolyDataMapper *contMapper; +vtkActor *outlineActor; +vtkActor *contActor; +vtkPolyData *t, *outlineOut, *contOut, *t1; +vtkStructuredPoints *temp, *out; +vtkAMRStructuredPointsReader* spr=0; + + + +int main(int argc, char** argv) { + // Make a window to put the rendering window in. FLTK interface. + // Fl_Window* w; + //{ Fl_Window* o = w = MainWin = + // new Fl_Window(500, 500, "AMRTest"); + // w = o; + // o->end(); + // } + //renWin = vtkFlRenderWindow::New(); + renderer = vtkRenderer::New(); + + // uncomment this to use the VTK rendering window + //renderer->SetBackground(0.5, 0.5, 0.5); + renWin = vtkRenderWindow::New(); + + renWin->AddRenderer(renderer); + + // uncomment this to use VTK event handler + vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); + iren->SetRenderWindow(renWin); + + //create a reader and open the file "amr.raw" + spr = vtkAMRStructuredPointsReader::New(); + spr->SetFileName("/nfs/zeus/lcascr1/pushkare/work/amr.raw"); + cout<<"NLevels: "<GetNumLevels()<GetNumTimeSteps()<1) nlevel=atoi(argv[1]); + spr->SelectLevel(nlevel); + spr->SelectTimeStep(0); + spr->Update(); + + int n = spr->GetNumDatasets(); + cout<<"NDataSets: "<SelectDataset(i); + spr->Update(); + out = spr->GetOutput(); + temp = (vtkStructuredPoints*)out->MakeObject(); + + temp->CopyStructure(out); + temp->GetPointData()->DeepCopy(out->GetPointData()); + temp->GetCellData()->DeepCopy(out->GetCellData()); + temp->ForceUpdate(); + + Data->AddItem(temp); + } + + int NContours = 0; + Data->InitTraversal(); + + + // This loop takes the grids from Data and processes them to get an outline + // and isosurface for each grid. The isovalue for the dataset is set to 0.86 + // for now. + for (int j=0; jGetNextItem(); + x1 = temp->GetPointData()->GetScalars()->GetRange(); + Iso = 0.86; + + //if the isovalue is out of bounds for a particular grid, then just + //ignore that grid. + if (Iso < x1[0] || Iso > x1[1]) + continue; + NContours++; + + //produce the isosurface and stick it into the PolyData collection. + contour->SetInput(temp); + contour->SetValue(0, Iso); + contour->Update(); + contOut = contour->GetOutput(); + + t = (vtkPolyData*)contOut->MakeObject(); + + t->CopyStructure(contOut); + t->GetPointData()->DeepCopy(contOut->GetPointData()); + t->GetCellData()->DeepCopy(contOut->GetCellData()); + t->ForceUpdate(); + + PolyData->AddItem(t); + + //produce a bounding box and put it into an Outlines collection + outline->SetInput(temp); + outline->Update(); + + outlineOut = outline->GetOutput(); + + t1 = (vtkPolyData*)outlineOut->MakeObject(); + t1->CopyStructure(outlineOut); + + Outlines->AddItem(t1); + + } + + PolyData->InitTraversal(); + Outlines->InitTraversal(); + + + //This loop takes care of the final mapper and actor steps of the pipeline + for (int k=0; kSetInput(PolyData->GetNextItem()); + contMapper->ImmediateModeRenderingOn(); + contActor = vtkActor::New(); + contActor->SetMapper(contMapper); + contActor->GetProperty()->SetRepresentationToSurface(); + renderer->AddActor(contActor); + + //produce and add the bounding box actor, which is colored RED + outlineMapper = vtkPolyDataMapper::New(); + outlineMapper->SetInput(Outlines->GetNextItem()); + outlineActor = vtkActor::New(); + outlineActor->SetMapper(outlineMapper); + outlineActor->GetProperty()->SetColor(1.0, 0.0, 0.0); + renderer->AddActor(outlineActor); + + } + + // this part makes sure that something actually does show up on the screen + // w->show(argc, argv); + // w->begin(); + // vtkwin = new Fl_vtk_Window( renWin, 1, 1, 498, 498); + // vtkwin->show(1, argv); + //w->end(); + + //return Fl::run(); + + //uncomment this and comment the FLTK stuff to use VTK window and event loop. + renWin->Render(); + iren->Start(); +} diff --git a/src/AMRPlus/tst.C b/src/AMRPlus/tst.C new file mode 100644 index 0000000..cdc9f03 --- /dev/null +++ b/src/AMRPlus/tst.C @@ -0,0 +1,42 @@ +#include +#include "flexset.h" + +void main(){ + flexset arr1, arr2; + int tst; + int ii; + + for (ii=0;ii<15;ii++){ + tst=rand() %10; + arr1.insert(tst); + } + for (ii=0;ii<15;ii++){ + tst=rand() %10; + arr2.insert(tst); + } + + flexset arr3; + for (ii=0;ii +#include +#include "AMRwriter.hh" +#include + +void AMRwriter::writeAMRattributes(){ + double origin[5],delta[5],ext[5],currenttime; + // OK, now we get to do the attribs thang... + // first compute the coorect origin and delta for this level. + //int i; + int level_timestep,persistence; + + /***** + Must compute the floating point time from the integer timestep. + The timestep is based on the finest computational level. + Should compute from level_timestep for less numerical error + *****/ + currenttime = (double)currentstep*basetimestep/(double)(levels[levels.getSize()-1].trefine); + // compute persistence + + persistence = levels[levels.getSize()-currentlevel-1].trefine; + level_timestep = currentstep/persistence; + // compute from min-ext... + // y-know... there is more point density near 0 in the float + // representation... so having sizes instead of extents would + // be smarter.... But viz systems generally use the extent... :( + // this is VERY inaccurate... Have to think about this more... + // Its OK for small subgrids, but inaccuracy is unbearable past + // 128 elements. Need to compute relative to basegrid extents!, + // but that isn't possible without dims for the basegrid! + // IObase::setOrigin(origin);// this will set the IObase:: basegrid origin :( + // IObase::setDelta(delta); + // Storage is in order of liklihood of that param being accessed. + // Less-frequently accessed params go to the end. + for(int i=0;i=levels.getSize()) levels.setSize(level+1); + levels[level].trefine=timerefinement; + for(int i=0;i0) + (levels[level]).prefine[i]=gridplacementrefinement[i]; + else + (levels[level]).prefine[i]=spatialrefinement[i]; + } +} + +void AMRwriter::setLevelRefinement(int level,int timerefinement, + int spatialrefinement, + int gridplacementrefinement){ + if(level>=levels.getSize()) levels.setSize(level+1); + levels[level].trefine=timerefinement; + for(int i=0;i0) + (levels[level]).prefine[i]=gridplacementrefinement; + else + (levels[level]).prefine[i]=spatialrefinement; + } +} + +void AMRwriter::setOrigin(int *origin){ + for(int i=0;isetType(IObase::Int2DataType(numbertype)); +} + +void AMRsetToplevelParameters(AMRFile afile,int rank, double *origin, + double *delta, double timestep,int maxdepth){ + AMRwriter *w = (AMRwriter*)afile; + w->setTopLevelParameters(rank,origin,delta,timestep,maxdepth); +} + +void AMRsetRefinement(AMRFile afile, + int timerefinement, + int *spatialrefinement, + int *gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + w->setRefinement(timerefinement,spatialrefinement,gridplacementrefinement); +} +void AMRsetScalarRefinement(AMRFile afile, + int timerefinement, + int spatialrefinement, + int gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + w->setRefinement(timerefinement,spatialrefinement,gridplacementrefinement); +} +void AMRsetLevelRefinement(AMRFile afile,int level, + int timerefinement, + int *spatialrefinement, + int *gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + w->setLevelRefinement(level,timerefinement,spatialrefinement,gridplacementrefinement); +} + + +/* using scalar values) */ +void AMRsetScalarLevelRefinement(AMRFile afile,int level, + int timerefinement, + int spatialrefinement, + int gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + w->setLevelRefinement(level,timerefinement,spatialrefinement,gridplacementrefinement); +} + +void AMRlevel(AMRFile afile,int level){ + AMRwriter *w = (AMRwriter*)afile; + w->setLevel(level); +} + +void AMRtime(AMRFile afile,int time){ + AMRwriter *w = (AMRwriter*)afile; + w->setTime(time); +} + +void AMRincrementTime(AMRFile afile){ + AMRwriter *w = (AMRwriter*)afile; + w->incrementTime(); +} + +void AMRwrite(AMRFile afile,int *origin,int *dims,void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); +} + +void AMRwriteFloat(AMRFile afile,float *origin,int *dims,void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); +} + +void AMRwriteDouble(AMRFile afile,double *origin,int *dims,void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); +} + +fAMRFile fAMRbeginFile(IOFile *descriptor){ + IObase *io = (IObase*)descriptor; + return (fAMRFile)(new FrameworkAMRwriter(*io)); +} + +void fAMRendFile(fAMRFile afile){ + FrameworkAMRwriter *w = (FrameworkAMRwriter*)afile; + delete w; +} + +void fAMRinit(fAMRFile afile, + int datatype, + int rank, + double *origin, + double *delta, + double timestep, + int interlevelRefinementRatio, + int nlevels){ + FrameworkAMRwriter *w = (FrameworkAMRwriter*)afile; + IObase::DataType dt = IObase::Int2DataType(datatype); + w->init(dt,rank,origin,delta,timestep,interlevelRefinementRatio,nlevels); +} +void fAMRsetParameters(fAMRFile afile, + int datatype, + int rank, + double *origin, + double *delta, + double timestep, + int interlevelRefinementRatio, + int nlevels){ + fAMRinit(afile,datatype,rank,origin,delta,timestep,interlevelRefinementRatio,nlevels); +} +inline void fAMRsetLevelParameters(fAMRFile afile, + int datatype, + int rank, + double *origin, + double *delta, + double timestep, + int interlevelRefinementRatio, + int nlevels){ + fAMRinit(afile,datatype,rank,origin,delta,timestep,interlevelRefinementRatio,nlevels); +} +void fAMRwrite(fAMRFile afile, + int level, + int globaltimestep, + int *origin, + int *dims, + void *data){ + FrameworkAMRwriter *w = (FrameworkAMRwriter*)afile; + w->write(level,globaltimestep,origin,dims,data); +} + +//===========F77/F90 Interface================================== + +Long8 f_amr_begin(Long8 *descriptor){ + IObase *io = (IObase*)descriptor; + return (Long8)(new AMRwriter(*io)); +} + +int f_amr_end(Long8 *afile){ + AMRwriter *w = (AMRwriter*)afile; + delete w; + return 1; +} + +int f_amr_settype(Long8 *afile,int *numbertype){ + AMRwriter *w = (AMRwriter*)afile; + w->setType(IObase::Int2DataType(*numbertype)); + return 1; +} + +int f_amr_setparams(Long8 *afile,int *rank,double *origin, + double *delta, double *timestep,int *maxdepth){ + AMRwriter *w = (AMRwriter*)afile; + w->setTopLevelParameters(*rank,origin,delta,*timestep,*maxdepth); + return 1; +} + +int f_amr_setref(Long8 *afile,int *veclen, + int *timerefinement, + int *spatialrefinement, + int *gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + if(*veclen==1) + w->setRefinement(*timerefinement, + *spatialrefinement,*gridplacementrefinement); + else + w->setRefinement(*timerefinement, + spatialrefinement,gridplacementrefinement); + return 1; +} + +int f_amr_setlref(Long8 *afile,int *level,int *veclen, + int *timerefinement, + int *spatialrefinement, + int *gridplacementrefinement){ + AMRwriter *w = (AMRwriter*)afile; + if(*veclen==1) + w->setLevelRefinement(*level,*timerefinement, + *spatialrefinement,*gridplacementrefinement); + else + w->setLevelRefinement(*level,*timerefinement, + spatialrefinement,gridplacementrefinement); + return 1; +} + +int f_amr_setlevel (Long8 *afile,int *level){ + AMRwriter *w = (AMRwriter*)afile; + w->setLevel(*level); + return 1; +} + +int f_amr_settime (Long8 *afile,int *timestep){ + AMRwriter *w = (AMRwriter*)afile; + w->setTime(*timestep); + return 1; +} + +int f_amr_incrtime(Long8 *afile){ + AMRwriter *w = (AMRwriter*)afile; + w->incrementTime(); + return 1; +} + +int f_amr_write(Long8 *afile,int *origin, int *dims, void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); + return 1; +} +int f_amr_writef(Long8 *afile,float *origin, int *dims, void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); + return 1; +} +int f_amr_writed(Long8 *afile,double *origin, int *dims, void *data){ + AMRwriter *w = (AMRwriter*)afile; + w->write(origin,dims,data); + return 1; +} diff --git a/src/AMRwriter.h b/src/AMRwriter.h new file mode 100644 index 0000000..21cae5b --- /dev/null +++ b/src/AMRwriter.h @@ -0,0 +1,47 @@ +#ifndef __AMRWRITER_H_ +#define __AMRWRITER_H_ + +#include "Arch.h" + +typedef IOFile AMRFile; /* its the same, but it is a different object underneath */ +AMRFile AMRbeginFile PROTO((IOFile descriptor)); +void AMRendFile PROTO((AMRFile afile)); +void AMRsetType PROTO((AMRFile afile,int numbertype)); +void AMRsetTopLevelParameters PROTO((AMRFile afile,int rank,double *origin, + double *delta, double timestep,int maxdepth)); +void AMRsetRefinement PROTO((AMRFile afile,int timerefinement, + int *spatialrefinement,int *gridplacementrefinement)); +void AMRsetScalarRefinement PROTO((AMRFile afile,int timerefinement, + int spatialrefinement,int gridplacementrefinement)); +void AMRsetLevelRefinement PROTO((AMRFile afile,int level,int timerefinement, + int *spatialrefinement,int *gridplacementrefinement)); +void AMRsetScalarLevelRefinement PROTO((AMRFile afile,int level,int timerefinement, + int spatialrefinement,int gridplacementrefinement)); +/* Stepping Methods */ +void AMRsetLevel PROTO((AMRFile afile,int level)); +void AMRsetTime PROTO((AMRFile afile,int timestep)); +void AMRincrementTime PROTO((AMRFile afile)); +void AMRwrite PROTO((AMRFile afile,int *origin, int *dims, void *data)); +void AMRwriteFloat PROTO((AMRFile afile,float *origin, int *dims, void *data)); +void AMRwriteDouble PROTO((AMRFile afile,double *origin, int *dims, void *data)); + +/*----------For the Framework AMR---------------*/ +typedef IOFile fAMRFile; +fAMRFile fAMRbeginFile PROTO((IOFile descriptor)); +void fAMRendFile PROTO((fAMRFile afile)); +void fAMRsetParameters PROTO((fAMRFile afile, + int datatype, + int rank, + double *origin, + double *delta, + double timestep, + int interlevelRefinementRatio, + int nlevels)); +void fAMRwrite PROTO((fAMRFile afile, + int level, + int globaltimestep, + int *origin, + int *dims, + void *data)); +#endif + diff --git a/src/AMRwriter.hh b/src/AMRwriter.hh new file mode 100644 index 0000000..61114ca --- /dev/null +++ b/src/AMRwriter.hh @@ -0,0 +1,288 @@ +// AMRwriter +#ifndef __AMRWRITER_HH_ +#define __AMRWRITER_HH_ + +#include "Arch.h" +#include "IO.hh" +#include "Writer.hh" +#include "FlexArrayTmpl.H" + +class AMRwriter : public Writer{ +protected: + struct LevelParams { + int srefine[3]; // grid refinement + int prefine[3]; // placement refinement + int trefine; // time refinement + }; + double basetimestep,currentorigin[3],currentdelta[3]; + FlexArray levels; + int iorigin[3]; + int currentlevel,currentstep; + + void writeAMRattributes(); +private: + virtual void setOrigin(int *origin); // logical origin + virtual void setOrigin(float *origin); // real origin + virtual void setOrigin(double *origin); // real origin + // virtual void setDelta(double *delta) { Writer::setOrigin(delta); } + virtual void setDims(int *dims) { Writer::setDims(dims);} + virtual void setDims(int rank, int *dims) { Writer::setDims(rank,dims); } + virtual void write(void *data); + virtual void setRank(int rank) {Writer::setRank(rank); } +public: //==================================================== + enum Flags {MaxDepth=-1}; + AMRwriter(IObase &descriptor); + virtual ~AMRwriter(); + //------------Initialization Methods------------------ + virtual void setType(IObase::DataType numbertype) { Writer::setType(numbertype); } + virtual void setTopLevelParameters(int rank,double *origin, + double *delta,double timestep,int maxdepth); + virtual void setRefinement(int timerefinement, + int *spatialrefinement, + int *gridplacementrefinement=0); + virtual void setRefinement(int timerefinement, + int spatialrefinement, + int gridplacementrefinement=1); + virtual void setLevelRefinement(int level, + int timerefinement, + int *spatialrefinement, + int *gridplacementrefinement=0); + virtual void setLevelRefinement(int level, + int timerefinement, + int spatialrefinement, + int gridplacementrefinement=1); + //-----------Stepping Parameters------------------ + virtual void setLevel(int level) { currentlevel=level; } + virtual void setTime(int timestep) { currentstep=timestep;} + virtual void incrementTime() {currentstep++;} + // virtual void setDeltaTime(double dt) {deltatime=dt;} + virtual void write(int *origin,int *dims,void *data){ + setOrigin(origin); + setDims(dims); + write(data); + } + virtual void write(float *origin,int *dims,void *data){ + setOrigin(origin); + setDims(dims); + write(data); + } + virtual void write(double *origin,int *dims,void *data){ + // create iorigin from origin... + setOrigin(origin); + setDims(dims); + write(data); + } +}; + + +class FrameworkAMRwriter : protected AMRwriter { + int nlevels; + int maxrefinement; + int refinement; +public: + /*@@ + @routine FrameworkAMRwriter::FrameworkAMRwriter + @date Tue Apr 15 14:23:32 1997 + @author John Shalf + @desc + Constructor for the FrameworkAMRwriter. It makes many assumptions about the + way that users of the framework would like to store their data. This eliminates + or hides most of the calls that AMRwriter:: would need to describe the AMR grid + heirarchy. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + + FrameworkAMRwriter(IObase &descriptor):AMRwriter(descriptor), + nlevels(1),maxrefinement(1),refinement(2){} + virtual ~FrameworkAMRwriter() {} + /* + This is set ONCE right after you open your AMR file. It is not + built into the constructor because you may not have the information + necessary to do this at the time of construction... + */ + /*@@ + @routine FrameworkAMRwriter::setParameters + @date Tue Apr 15 14:00:40 1997 + @author John Shalf + @desc This is set ONCE right after you open your AMR file. It is not + built into the constructor because you may not have the information + necessary to do this at the time of construction... + This sets parameters necessary do define the AMR heirarchy, namely + the refinement between levels and the floating-point parameters that + form the basis for locating the grids in 3-space in a visualization system. + @enddesc + @par rank + @pdesc The number of dimensions for the dataset + @ptype int + @pvalues 1-5 + @pcomment + This calls setRank() in the base Writer() class + @endpar + + @par origin + @pdesc The origin of the toplevel (coarsest) grid in REAL coordinates + @ptype double* + @endpar + + @par delta + @pdesc The inter-grid spacing at the toplevel (coarsest level) in REAL coordinates. + @ptype double + @pcomment + The inter-grid spacing is divided by the refinement factor for a particular level + to determine the real grid spacing for that nested grid. + This assumes you have a uniform grid delta (same delta in all spatial directions). + @endpar + + @par timestep + @pdesc The REAL size of a toplevel (coarsest) timestep + @ptype double + @pvalues + @endpar + + @par interlevelRefinementRatio + @pdesc The integer ratio of time refinement and spatial refinement between levels. + @ptype int + @pvalues Any positive integer > 0 + @pcomment + This ratio is used to determine the spatial refinement for a level. + So spatialrefinement_on_this_level = toplevel_delta / interlevelRefinementRatio^level + Where the levels are numbered from 0:nlevels-1. + This assumes that you have the same refinement factor in all spatial directions as + well as in time. + @endpar + + @par numLevels + @pdesc The maximum number of levels in the AMR heirarchy. + @ptype int + @pvalues Any positive integer > 0 + @pcomment + This is necessary to find out the resolution of the finest-grid for the + purposes of grid-placement in the AMR file. Otherwise we wouldn't be able + to interpret the above parameters. + @endpar + + @calls AMRwriter::setTopLevelParameters + @calledby + @history + @endhistory + +@@*/ + + virtual void init(int rank, // number of dimensions in the dataset + double *origin, // REAL origin or coarsest level grid + double *delta, // float grid spacing at coarsest level + double timestep, // float timestep at coarsest level + int interlevelRefinementRatio, //refinement ratio with + // between levels. This covers refinement of time stepping + // as well + int numLevels); // the maximum depth of the AMR grid heirarchy + virtual void init( IObase::DataType dt, // type for all data + int rank, // number of dimensions in the dataset + double *origin, // REAL origin or coarsest level grid + double *delta, // float grid spacing at coarsest level + double timestep, // float timestep at coarsest level + int interlevelRefinementRatio, //refinement ratio with + // between levels. This covers refinement of time stepping + // as well + int numLevels); + // This is called on every write + /*@@ + @routine FrameworkAMRwriter::write + @date Tue Apr 15 14:14:48 1997 + @author John Shalf + @desc + This is called on every write to set the parameters for a particular grid. + @enddesc + @calls AMRwriter::setGrid AMRwriter::write + @calledby + @par level + @pdesc The current AMR level for this grid + @ptype int + @pvalues 0 to nlevels-1 + @endpar + + @par globaltimestep + @pdesc The current global timestep (stepping at the finest resolution level) + @ptype int + @pvalues Any positive integer + @pcomment + So we step at finest time resolution instead of resolution relative to this level. + @endpar + + @par origin + @pdesc The integer origin of the grid using coordinates relative to the finest resolution grid in the heirarchy. + @ptype int* + @pvalues Any positive integer > 0 + @pcomment + So grid placement is with respect to the finest level integer coordinates. + @endpar + + @par dims + @pdesc The dimensions of the array (dims of the grid). + @ptype int* + @endpar + + @par data + @pdesc Pointer to the data array for the grid. + @ptype void* + @endpar + + + @history + + @endhistory + +@@*/ + + virtual void write(int level, + int globaltimestep, + int *origin, + int *dims, + void *data) { + AMRwriter::setLevel(level); + AMRwriter::setTime(globaltimestep); + AMRwriter::write(origin,dims,data); + } + +}; + +#define f_amr_begin F77NAME(amr_begin_,amr_begin,AMR_BEGIN) +#define f_amr_end F77NAME(amr_end_,amr_end,AMR_END) +#define f_amr_settype F77NAME(amr_settype_,amr_settype,AMR_SETTYPE) +#define f_amr_setparams F77NAME(amr_setparams_,amr_setparams,AMR_SETPARAMS) +#define f_amr_setref F77NAME(amr_setref_,amr_setref,AMR_SETREF) +#define f_amr_setlref F77NAME(amr_setlref_,amr_setlref,AMR_SETLREF) +#define f_amr_setdims F77NAME(amr_setdims_,amr_setdims,AMR_SETDIMS) +#define f_amr_setlevel F77NAME(amr_setlevel_,amr_setlevel,AMR_SETLEVEL) +#define f_amr_settime F77NAME(amr_settime_,amr_settime,AMR_SETTIME) +#define f_amr_incrtime F77NAME(amr_incrtime_,amr_incrtime,AMR_INCRTIME) +#define f_amr_write F77NAME(amr_write_,amr_write,AMR_WRITE) + +extern "C" { +#include "AMRwriter.h" +Long8 f_amr_begin (Long8 *descriptor); +int f_amr_end (Long8 *afile); +int f_amr_settype (Long8 *afile,int *numbertype); +int f_amr_setparams (Long8 *afile,int *rank,double *origin, + double *delta, double *timestep,int maxdepth); +int f_amr_setref (Long8 *afile,int veclen, + int *timerefinement, + int *spatialrefinement,int *gridplacementrefinement); +int f_amr_setlref (Long8 *afile,int *level,int *veclen, + int *timerefinement, + int *spatialrefinement,int *gridplacementrefinement); +int f_amr_setlevel (Long8 *afile,int *level); +int f_amr_settime (Long8 *afile,int *timestep); +int f_amr_incrtime (Long8 *afile); +int f_amr_write (Long8 *afile,int *origin,int *dims,void *data); + int f_amr_writef (Long8 *afile,float *origin,int *dims,void *data); + int f_amr_writed (Long8 *afile,double *origin,int *dims,void *data); +} + +#endif diff --git a/src/AVSreadBNB.cc b/src/AVSreadBNB.cc new file mode 100644 index 0000000..b964cc4 --- /dev/null +++ b/src/AVSreadBNB.cc @@ -0,0 +1,817 @@ +/*-----------------------------------------------------* + * AVSreadHLL: Reads Tom's libHLL data into AVS UCD * + * format. This is based on the AVS readUCD.cc * + * code snippet. * + *-----------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include "IEEEIO.hh" +#include "WriteHLL.hh" +#include "FlexArrayTmpl.H" +#include "AmrNode.hh" +#include "AmrUcdFileReader.hh" +#define buffer_size 200 +#define NUM_CELL_TYPES 8 + +extern char *AVSstatic; + +typedef struct _ucd_stats { + int size; + } Ucd_Stats_Type; + +typedef struct _ctype_struct { + int id, mat, n, cell_type; + } Ctype; + +typedef struct _ntype_struct { + int n, node_list[20]; + } Ntype; + +typedef struct _model_stats { + char node_data_labels[100], cell_data_labels[100], model_data_labels[100], + node_data_units[100], cell_data_units[100], model_data_units[100]; + + int num_nodes, num_cells, num_node_data, num_cell_data, num_model_data, + node_active_list[20], cell_active_list[20], model_active_list[20], + num_node_comp, node_comp_list[20], num_cell_comp, cell_comp_list[20], + num_model_comp, model_comp_list[20], num_nlist_nodes; + } Mtype; + +/* ANSI-C/C++ expect functions to be declared before being used and checks + argument compatibility */ + +AVS_STATIC(void add_cell, (UCD_structure **model, int cell, int ucd_cell_type, int n, + int *rnode_list, int mat_id)); +AVS_STATIC(int read_binary, (AmrFileReader *file, + Ctype **pcells, int **pcell_nlists, + Mtype *model, float **pxc, float **pyc, float **pzc, + float **pnode_data, float **pcell_data, float **pmodel_data, + float **pmin_node_data, float **pmax_node_data, + float **pmin_cell_data, float **pmax_cell_data, + float **pmin_model_data, float **pmax_model_data)); + +int read_bnb( UCD_structure** output, + const char* file_name, + int TimeStep, + int cell_con, /* Not used! */ + const char* td1, /* Not used! */ + const char* contour, /* Not used! */ + const char* td2, /* Not used! */ + const char* cell_sel, /* Not used! */ + const char* td3, /* Not used! */ + const char* model_sel /* Not used! */ ) + { + + char string[40], *model_name, tmp_str[80]; + static IEEEIO *io=0; + static AmrFileReader *file=0; + float x, y, z, + xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0, zmin = 0.0, zmax = 0.0, + min_extent[3], max_extent[3]; + + int node, cell, n, i, util_flag, j, ucd_flags, cell_tsize, node_csize; + + Ctype *cells; + + float *xc, *yc, *zc, *node_data, *cell_data, *model_data, + *min_node_data, *max_node_data, *min_cell_data, + *max_cell_data, *min_model_data, *max_model_data; + + int num_nodes, num_cells, num_node_data, num_cell_data, num_model_data, + *bcell_nlists; + + Mtype model_stats; + + Ntype *cell_nlists; + + static int clist[] = {1, 2, 3, 4}; + + Ucd_Stats_Type *ucd_stats; + + int recompute=0; + + /************** + *** body *** + **************/ + + if (!file_name) + return(1); + + if (AVSstatic == NULL) { + ucd_stats = (Ucd_Stats_Type *)malloc(sizeof(Ucd_Stats_Type)); + AVSstatic = (char *) ucd_stats; + } + else + ucd_stats = (Ucd_Stats_Type *)AVSstatic; + if(AVSparameter_changed("read file")){ + io = new IEEEIO(file_name,IObase::Read); + if(!io->isValid()) + return (0); + file = new AmrFileReader(*io); + int mintime,maxtime; + file->getTimeRange(mintime,maxtime); + if((maxtime-mintime)<=1){ + AVSmodify_parameter("TimeStep",AVS_VALUE|AVS_MINVAL|AVS_MAXVAL, + mintime,mintime,maxtime+1); + AVSparameter_visible("TimeStep",0); + } + else { + AVSmodify_parameter("TimeStep",AVS_MINVAL|AVS_MAXVAL|AVS_VALUE, + mintime,mintime,maxtime); + AVSparameter_visible("TimeStep",1); + } + // select current grid + file->showAllLevels(); + file->setTime(mintime); + recompute=1; + } + else if(AVSparameter_changed("TimeStep")){ + file->setTime(TimeStep); + recompute=1; + } + else + recompute=0; + + if (recompute){ + if (*output) UCDstructure_free (*output); + cell_nlists = NULL; + bcell_nlists = NULL; + /* check to see if file is binary or ascii. */ + if (!read_binary (file, &cells, &bcell_nlists, &model_stats, &xc, + &yc, &zc, &node_data, &cell_data, &model_data, + &min_node_data, &max_node_data, &min_cell_data, + &max_cell_data, &min_model_data, &max_model_data)) { + AVSerror (" Error in read_bnb: can't open bin file. \n"); + return (0); + } + + + + /* set the model statistics: + + num_nodes - the number of nodes in the model. + + num_cells - the number of cells (elements) in the model. + + num_node_data - the total number of data values per node. if you + wanted to store three scalars and one 3-vector per + node then num_node_data would be set to six. + + num_cell_data - the total number of data values per cell. + + num_model_data - model data is used for values which apply to the + the model as a whole, not just nodes or cells. + for example, the locations of loads could be stored + here. + + + */ + util_flag = 0; + num_nodes = model_stats.num_nodes; + num_cells = model_stats.num_cells; + num_node_data = model_stats.num_node_data; + num_cell_data = model_stats.num_cell_data; + num_model_data = model_stats.num_model_data; + strcpy (tmp_str, file_name); + + model_name = (char *)(strrchr(tmp_str, '/')); + + if (model_name) model_name++; /* go to the next character */ + + for (i = strlen(model_name); model_name[i] != '.'; i--); + model_name[i] = '\0'; + + + /* 'cell_tsize' is the size of all of the cell topology (number of + nodes per cell) lists. it is used to allocate space for the node + lists for each cell. if all the cells were hexahedra (without + mid-edge nodes) then this would be set to num_cells*eight, if all + the cells were tetrahedra (without mid-edge nodes) then this would + be set to num_cells*four. + + 'node_csize' is the size all of the node connectivity lists (the list + of cells connected to a node). for a model constructed from all + hexahedra this would be less than num_cells*eight. + + both 'cell_tsize' and 'node_csize' are computed when the model is + read (in the read_ascii or the read_bin functions) and are always + equal. + + 'ucd_flags' specifies how labels for cells and nodes will be stored + and whether material id's and cell types will be stored for each cell. + the following is a list of flags which can be or'ed together: + + UCD_MATERIAL_IDS - material id's for each cell will be stored. + UCD_NODE_NAMES - node names will be stored. + UCD_CELL_NAMES - cell names will be stored. + UCD_CELL_TYPES - user defined cell type will be stored. + UCD_MID_EDGES - cells will have mid-side edges. + UCD_CHAR - node/cell labels are character strings. + UCD_INT - node/cell labels are integers. */ + + cell_tsize = node_csize = model_stats.num_nlist_nodes; + ucd_stats->size = cell_tsize; + + ucd_flags = UCD_INT | UCD_MATERIAL_IDS | UCD_NODE_NAMES | UCD_CELL_NAMES | + UCD_CELL_TYPES | UCD_MID_EDGES; + + printf("Allocating output structure for nnodedata=%u numcells=%u numnodes=%u\n", + num_node_data,num_cells,num_nodes); + *output = (UCD_structure *)UCDstructure_alloc (model_name, + num_model_data, ucd_flags, num_cells, cell_tsize, + num_cell_data, num_nodes, node_csize, num_node_data, util_flag); + + + /* store nodal coordinates. */ + + for (node = 0; node < num_nodes; node++) { + x = xc[node], y = yc[node], z = zc[node]; + + if (node) { + xmin = (x < xmin ? x : xmin), xmax = (x > xmax ? x : xmax); + ymin = (y < ymin ? y : ymin), ymax = (y > ymax ? y : ymax); + zmin = (z < zmin ? z : zmin), zmax = (z > zmax ? z : zmax); + } + else { + xmin = xmax = x; + ymin = ymax = y; + zmin = zmax = z; + } + + if (!UCDnode_set_information (*output, node, (char *) (node + 1), 0, clist)) { + AVSerror ("Error in read_bnb: can't set node %d info.\n", node); + return (0); + } + } + + UCDstructure_set_node_positions (*output, xc, yc, zc); + + + /* store the model's extent (max/min dimensions). */ + + min_extent[0] = xmin, min_extent[1] = ymin, min_extent[2] = zmin; + max_extent[0] = xmax, max_extent[1] = ymax, max_extent[2] = zmax; + + UCDstructure_set_extent (*output, min_extent, max_extent); + + + /* store cell type, topology. */ + + if (bcell_nlists) { /* if read in as binary file. */ + for (cell = 0, j = 0; cell < num_cells; cell++, j += n) { + n = cells[cell].n; + + add_cell (output, cell, cells[cell].cell_type, n, &bcell_nlists[j], + cells[cell].mat); + } + } + else + for (cell = 0; cell < num_cells; cell++) + add_cell (output, cell, cells[cell].cell_type, cell_nlists[cell].n, + cell_nlists[cell].node_list, cells[cell].mat); + + + /* store nodal data. + + data at nodes is separated into components. successive nodes of a + component are stored contiguously. for example, if you wish to + store two scalars and one 3-vector then this would be three + components and would be stored as (given n nodes in the model): + + 0 node 0, component 1 + 1 node 1, component 1 + . + . + . + n node n, component 1 + n+1 node 0, component 2 + n+2 node 1, component 2 + . + . + . + 2n node n, component 2 + 2n+1 node 0, component 3, 1st vector component + 2n+2 node 0, component 3, 2nd vector component + 2n+3 node 0, component 3, 3rd vector component + 2n+4 node 1, component 3, 1st vector component + + 2n+5 node 1, component 3, 2nd vector component + 2n+6 node 1, component 3, 3rd vector component + . + . + . + 5n-2 node n, component 3, 1st vector component + 5n-1 node n, component 3, 2nd vector component + 5n node n, component 3, 3rd vector component + + + the node component list has an entry for each compoment. each + entry specifies the dimensionality for each component. for example, + a scalar component would have an entry of one and a 3-vector would + have an entry of three. + + the node active list can be used to specify which data type is + currently active (being used to display results). the list has + an entry for each data component. if that entry is not zero + then it is active. currently, this functionality is not used by + any modules. + + node labels specify the user defined name of each data component. + + node units specify the user defined units of each data component. + + node minmax specifies the maximum and minimum values for each + data component. this has no meaning for vector components although + the max/min magnitude of the vector could be used. + + */ + + if (num_node_data) { + puts("Set Node Data!"); + printf("Num node data=%u\n",num_node_data); + UCDstructure_set_node_components (*output, model_stats.node_comp_list, + model_stats.num_node_comp); + + + UCDstructure_set_node_active (*output, model_stats.node_active_list); + + UCDstructure_set_node_labels (*output, model_stats.node_data_labels, "."); + + UCDstructure_set_node_units (*output, model_stats.node_data_units, "."); + + if (model_stats.num_node_comp > 1) { + for (i = 0; model_stats.node_data_labels[i] != '.'; i++) + string[i] = model_stats.node_data_labels[i]; + string[i] = '\0'; + } + else + strcpy (string, model_stats.node_data_labels); + + AVSmodify_parameter ("Node Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.node_data_labels, "."); + + printf("Set node minmax %f, %f\n",*min_node_data,*max_node_data); + UCDstructure_set_node_minmax (*output, min_node_data, max_node_data); + + if (!UCDstructure_set_node_data (*output, node_data)) { + AVSerror ("Error in read_bnb: can't set node data.\n"); + return (0); + } + } + else + AVSmodify_parameter ("Node Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + + + /* store cell data. */ + + if (num_cell_data) { + UCDstructure_set_cell_components (*output, model_stats.cell_comp_list, + model_stats.num_cell_comp); + + UCDstructure_set_cell_active (*output, model_stats.cell_active_list); + + UCDstructure_set_cell_labels (*output, model_stats.cell_data_labels, "."); + + for (i = 0; model_stats.cell_data_labels[i] != '.'; i++) + string[i] = model_stats.cell_data_labels[i]; + string[i] = '\0'; + + AVSmodify_parameter ("Cell Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.cell_data_labels, "."); + + if (!UCDstructure_set_cell_data (*output, cell_data)) { + AVSerror ("Error in read_bnb: can't set cell data.\n"); + return (0); + } + } + else { + AVSmodify_parameter ("Cell Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + } + + + /* store model data. */ + + if (num_model_data) { + UCDstructure_set_data_labels (*output, model_stats.model_data_labels, "."); + + for (i = 0; model_stats.model_data_labels[i] != '.'; i++) + string[i] = model_stats.model_data_labels[i]; + string[i] = '\0'; + + AVSmodify_parameter ("Model Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.model_data_labels, "."); + + if (!UCDstructure_set_data (*output, model_data)) { + AVSerror ("Error in read_bnb: can't set model data.\n"); + return (0); + } + } + else + AVSmodify_parameter ("Model Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + + if (*output) { + free (xc); + free (yc); + free (zc); + + if (num_node_data) { + free (node_data); + free (min_node_data); + free (max_node_data); + } + + if (num_cell_data) { + free (cell_data); + free (min_cell_data); + free (max_cell_data); + } + + if (num_model_data) { + free (model_data); + free (min_model_data); + free (max_model_data); + } + + free (cells); + + if (cell_nlists) + free (cell_nlists); + + if (bcell_nlists) + free (bcell_nlists); + } + } + return(1); + } + + +/*-----------------------------------------------------* + * * + * **** add_cell **** * + * * + * add a cell topology to the ucd structure. * + *-----------------------------------------------------*/ + +static void add_cell( UCD_structure** model, int cell, int ucd_cell_type, int n, + int* rnode_list, int mat_id ) + { + + static char *cell_type[] = {"pt", "line", "tri", "quad", "tet", + "pyr", "prism", "hex"}; + + int i, num_me_nodes, num_nodes, /* Not used: cell_found, */ + me_flag, node_list[40]; + + /************** + *** body *** + **************/ + + if (ucd_cell_type < NUM_CELL_TYPES) { + me_flag = 0; + num_nodes = UCD_num_nodes[ucd_cell_type]; + + + /* if the number of nodes read (n) is equal to the number of + nodes without mid-side nodes then send the read node list. + else set the mid-edge flag to indicate which edges have + mide-edge nodes. */ + + for (i = 0; i < num_nodes; i++) + node_list[i] = rnode_list[i] - 1; + + if (n != num_nodes) { + for (i = num_nodes, num_me_nodes = 0; i < n; i++) + if (rnode_list[i] != 0) { + node_list[num_nodes + num_me_nodes] = rnode_list[i] - 1; + me_flag = me_flag | (0x1 << (i - num_nodes)); + num_me_nodes++; + } + } + + UCDcell_set_information (*model, cell, (char *) (cell + 1), + cell_type[ucd_cell_type], + mat_id - 1, ucd_cell_type, me_flag, node_list); + } + } + +static int add_grid(AmrGrid &g,float *data, + int &pindex,int &cindex, + float *x,float *y,float *z,int *cells, + float &min_node_data,float &max_node_data){ + int edgemapx[8]={0,0,1,1,0,0,1,1}; + int edgemapy[8]={0,1,1,0,0,1,1,0}; + int edgemapz[8]={0,0,0,0,1,1,1,1}; + int edgemap[8]; + for(int i=0;i<8;i++) + edgemap[i] = edgemapx[i] + g.dims[0]*(edgemapy[i] + edgemapz[i]*g.dims[1]); + printf("edgemap=%u:%u:%u:%u:%u:%u:%u:%u\n", + edgemap[0],edgemap[1],edgemap[2],edgemap[3], + edgemap[4],edgemap[5],edgemap[6],edgemap[7]); + // compute edge map based on dims + if(g.datatype==IObase::Float64) // for double precision data + for(int didx=0,idx=pindex,k=0,klast=g.dims[2];kmax_node_data) max_node_data=dt; + if(dtmax_node_data) max_node_data=dt; + if(dtgetNumGrids(); + FlexArray grid; + file->getGrids(grid); // get the AMR grids + /************** + *** body *** + **************/ + + node_data = cell_data = model_data = NULL; + max_cell_data = min_cell_data =max_model_data=min_model_data=NULL; + + int i,ndims, cellsz, celltype,largest_grid=0; + model->num_cell_data=model->num_node_data=model->num_model_data=0; + + // Go through and count up how many cells are required + // Count up how many nodes are required + for(i=0,model->num_nodes=0,model->num_cells=0;inum_nodes += g_npts; + model->num_cells += g_ncls; + } + model->num_node_data=1; // always + model->num_cell_data=0; + model->num_model_data=0; + ndims=3; // hardcoded + switch(ndims){ + case 0: + cellsz=1; + celltype=UCD_POINT; + break; + case 1: + cellsz=2; + celltype=UCD_LINE; + break; + case 2: + cellsz=4; + celltype=UCD_QUADRILATERAL; + break; + case 3: + cellsz=8; + celltype=UCD_HEXAHEDRON; + break; + } + model->num_nlist_nodes=cellsz*model->num_cells; // hexahedral cells + // fill out basic parameters + num_nodes = model->num_nodes; + num_cells = model->num_cells; + num_node_data = model->num_node_data; + num_cell_data = model->num_cell_data; + num_model_data = model->num_model_data; + num_nlist_nodes = model->num_nlist_nodes; + + printf("Allocating %u cell storage structures. total=%lu\n", num_cells, sizeof(Ctype)*num_cells); + cells = (Ctype *)malloc(sizeof(Ctype) * num_cells); + printf("cells pointer=%lu\n",(unsigned long)cells); + printf("Allocating %u points for cell connectivity storage\n", num_nlist_nodes); + cell_nlists = (int *)malloc(sizeof(int) * num_nlist_nodes); + + printf("Init cell info structures\n"); + for(i=0;inode_active_list[0]=1; + sprintf(model->node_data_labels,"bnbdata"); + sprintf(model->node_data_units,"unity"); + model->node_comp_list[0]=1; + model->num_node_comp=1; + + *pxc = xc, *pyc = yc, *pzc = zc; + *pcells = cells; + *pcell_nlists = cell_nlists; + *pnode_data = node_data; + *pcell_data = cell_data = 0; + *pmodel_data = model_data = 0; + + model->num_nodes = num_nodes; + model->num_cells = num_cells; + model->num_node_data = num_node_data; + model->num_cell_data = num_cell_data; + model->num_model_data = num_model_data; + + *pmax_node_data = max_node_data; + *pmin_node_data = min_node_data; + *pmax_cell_data = max_cell_data; + *pmin_cell_data = min_cell_data; + *pmax_model_data = max_model_data; + *pmin_model_data = min_model_data; + + return(1); + } + +/*-----------------------------------------------------* + * * + * **** read_bnb_init **** * + * * + *-----------------------------------------------------*/ + +static void +read_bnb_init() + { + AVSstatic = (char *)0; + } + + +/*-----------------------------------------------------* + * * + * **** read_bnb_finis **** * + * * + *-----------------------------------------------------*/ + +static void +read_bnb_finis() + { + if (AVSstatic == NULL) return; + + free (AVSstatic); + } + + +static void +read_bnb_desc() + { + int param; + + static char *choices = "...."; + + /************** + *** body *** + **************/ + + AVSset_module_name ("Read BNB", MODULE_DATA); + + AVScreate_output_port ("tet output", "ucd"); + + param = AVSadd_parameter ("read file", "string", 0, 0, ".ieee"); + AVSconnect_widget (param, "browser"); + AVSadd_parameter("TimeStep", "integer", 0, 0, 1); + AVSadd_parameter("Cell Connect", "boolean", 0, 0, 1); + + param = AVSadd_parameter("Node Data", "string", "Node Data", "Node Data", + NULL); + AVSconnect_widget(param, "text"); + + AVSadd_parameter ("Node Type", "choice", "", choices, "."); + + param = AVSadd_parameter("Cell Data", "string", "Cell Data", "Cell Data", + NULL); + AVSconnect_widget (param, "text"); + + AVSadd_parameter ("Cell Type", "choice", "", choices, "."); + + param = AVSadd_parameter("Model Data", "string", "Model Data", "Model Data", + NULL); + AVSconnect_widget (param, "text"); + + AVSadd_parameter ("Model Type", "choice", "", choices, "."); + + AVSset_init_proc ((AVS_FNCP) read_bnb_init); + + AVSset_destroy_proc ((AVS_FNCP) read_bnb_finis); + + AVSset_compute_proc ((AVS_FNCP) read_bnb); + } + +#if __cplusplus +extern "C" { +#endif + +void +AVSinit_modules() + { + AVSmodule_from_desc ((AVS_FNCP) read_bnb_desc); + } + +#if __cplusplus +} +#endif + diff --git a/src/AVSreadHLL.cc b/src/AVSreadHLL.cc new file mode 100644 index 0000000..f55e32e --- /dev/null +++ b/src/AVSreadHLL.cc @@ -0,0 +1,768 @@ +/*-----------------------------------------------------* + * AVSreadHLL: Reads Tom's libHLL data into AVS UCD * + * format. This is based on the AVS readUCD.cc * + * code snippet. * + *-----------------------------------------------------*/ + +#include +#include +#include +#include +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" +#include "WriteHLL.hh" + +#define buffer_size 200 +#define NUM_CELL_TYPES 8 + +extern char *AVSstatic; + +typedef struct _ucd_stats { + int size; + } Ucd_Stats_Type; + +typedef struct _ctype_struct { + int id, mat, n, cell_type; + } Ctype; + +typedef struct _ntype_struct { + int n, node_list[20]; + } Ntype; + +typedef struct _model_stats { + char node_data_labels[100], cell_data_labels[100], model_data_labels[100], + node_data_units[100], cell_data_units[100], model_data_units[100]; + + int num_nodes, num_cells, num_node_data, num_cell_data, num_model_data, + node_active_list[20], cell_active_list[20], model_active_list[20], + num_node_comp, node_comp_list[20], num_cell_comp, cell_comp_list[20], + num_model_comp, model_comp_list[20], num_nlist_nodes; + } Mtype; + +/* ANSI-C/C++ expect functions to be declared before being used and checks + argument compatibility */ + +AVS_STATIC(void add_cell, (UCD_structure **model, int cell, int ucd_cell_type, int n, + int *rnode_list, int mat_id)); +AVS_STATIC(int read_binary, (const char *file_name, Ctype **pcells, int **pcell_nlists, + Mtype *model, float **pxc, float **pyc, float **pzc, + float **pnode_data, float **pcell_data, float **pmodel_data, + float **pmin_node_data, float **pmax_node_data, + float **pmin_cell_data, float **pmax_cell_data, + float **pmin_model_data, float **pmax_model_data)); + +int read_hll( UCD_structure** output, + const char* file_name, + int cell_con, /* Not used! */ + const char* td1, /* Not used! */ + const char* contour, /* Not used! */ + const char* td2, /* Not used! */ + const char* cell_sel, /* Not used! */ + const char* td3, /* Not used! */ + const char* model_sel /* Not used! */ ) + { + + char string[40], *model_name, tmp_str[80]; + + float x, y, z, + xmin = 0.0, xmax = 0.0, ymin = 0.0, ymax = 0.0, zmin = 0.0, zmax = 0.0, + min_extent[3], max_extent[3]; + + int node, cell, n, i, util_flag, j, ucd_flags, cell_tsize, node_csize; + + Ctype *cells; + + float *xc, *yc, *zc, *node_data, *cell_data, *model_data, + *min_node_data, *max_node_data, *min_cell_data, + *max_cell_data, *min_model_data, *max_model_data; + + int num_nodes, num_cells, num_node_data, num_cell_data, num_model_data, + *bcell_nlists; + + Mtype model_stats; + + Ntype *cell_nlists; + + static int clist[] = {1, 2, 3, 4}; + + Ucd_Stats_Type *ucd_stats; + + /************** + *** body *** + **************/ + + if (!file_name) + return(1); + + if (AVSstatic == NULL) { + ucd_stats = (Ucd_Stats_Type *)malloc(sizeof(Ucd_Stats_Type)); + AVSstatic = (char *) ucd_stats; + } + else + ucd_stats = (Ucd_Stats_Type *)AVSstatic; + + if (AVSparameter_changed("read file")) { + if (*output) UCDstructure_free (*output); + + cell_nlists = NULL; + bcell_nlists = NULL; + + + /* check to see if file is binary or ascii. */ + + if (!read_binary (file_name, &cells, &bcell_nlists, &model_stats, &xc, + &yc, &zc, &node_data, &cell_data, &model_data, + &min_node_data, &max_node_data, &min_cell_data, + &max_cell_data, &min_model_data, &max_model_data)) { + AVSerror (" Error in read_hll: can't open bin file. \n"); + return (0); + } + + + + /* set the model statistics: + + num_nodes - the number of nodes in the model. + + num_cells - the number of cells (elements) in the model. + + num_node_data - the total number of data values per node. if you + wanted to store three scalars and one 3-vector per + node then num_node_data would be set to six. + + num_cell_data - the total number of data values per cell. + + num_model_data - model data is used for values which apply to the + the model as a whole, not just nodes or cells. + for example, the locations of loads could be stored + here. + + + */ + util_flag = 0; + num_nodes = model_stats.num_nodes; + num_cells = model_stats.num_cells; + num_node_data = model_stats.num_node_data; + num_cell_data = model_stats.num_cell_data; + num_model_data = model_stats.num_model_data; + strcpy (tmp_str, file_name); + + model_name = (char *)(strrchr(tmp_str, '/')); + + if (model_name) model_name++; /* go to the next character */ + + for (i = strlen(model_name); model_name[i] != '.'; i--); + model_name[i] = '\0'; + + + /* 'cell_tsize' is the size of all of the cell topology (number of + nodes per cell) lists. it is used to allocate space for the node + lists for each cell. if all the cells were hexahedra (without + mid-edge nodes) then this would be set to num_cells*eight, if all + the cells were tetrahedra (without mid-edge nodes) then this would + be set to num_cells*four. + + 'node_csize' is the size all of the node connectivity lists (the list + of cells connected to a node). for a model constructed from all + hexahedra this would be less than num_cells*eight. + + both 'cell_tsize' and 'node_csize' are computed when the model is + read (in the read_ascii or the read_bin functions) and are always + equal. + + 'ucd_flags' specifies how labels for cells and nodes will be stored + and whether material id's and cell types will be stored for each cell. + the following is a list of flags which can be or'ed together: + + UCD_MATERIAL_IDS - material id's for each cell will be stored. + UCD_NODE_NAMES - node names will be stored. + UCD_CELL_NAMES - cell names will be stored. + UCD_CELL_TYPES - user defined cell type will be stored. + UCD_MID_EDGES - cells will have mid-side edges. + UCD_CHAR - node/cell labels are character strings. + UCD_INT - node/cell labels are integers. */ + + cell_tsize = node_csize = model_stats.num_nlist_nodes; + ucd_stats->size = cell_tsize; + + ucd_flags = UCD_INT | UCD_MATERIAL_IDS | UCD_NODE_NAMES | UCD_CELL_NAMES | + UCD_CELL_TYPES | UCD_MID_EDGES; + + *output = (UCD_structure *)UCDstructure_alloc (model_name, + num_model_data, ucd_flags, num_cells, cell_tsize, + num_cell_data, num_nodes, node_csize, num_node_data, util_flag); + + + /* store nodal coordinates. */ + + for (node = 0; node < num_nodes; node++) { + x = xc[node], y = yc[node], z = zc[node]; + + if (node) { + xmin = (x < xmin ? x : xmin), xmax = (x > xmax ? x : xmax); + ymin = (y < ymin ? y : ymin), ymax = (y > ymax ? y : ymax); + zmin = (z < zmin ? z : zmin), zmax = (z > zmax ? z : zmax); + } + else { + xmin = xmax = x; + ymin = ymax = y; + zmin = zmax = z; + } + + if (!UCDnode_set_information (*output, node, (char *) (node + 1), 0, clist)) { + AVSerror ("Error in read_hll: can't set node %d info.\n", node); + return (0); + } + } + + UCDstructure_set_node_positions (*output, xc, yc, zc); + + + /* store the model's extent (max/min dimensions). */ + + min_extent[0] = xmin, min_extent[1] = ymin, min_extent[2] = zmin; + max_extent[0] = xmax, max_extent[1] = ymax, max_extent[2] = zmax; + + UCDstructure_set_extent (*output, min_extent, max_extent); + + + /* store cell type, topology. */ + + if (bcell_nlists) { /* if read in as binary file. */ + for (cell = 0, j = 0; cell < num_cells; cell++, j += n) { + n = cells[cell].n; + + add_cell (output, cell, cells[cell].cell_type, n, &bcell_nlists[j], + cells[cell].mat); + } + } + else + for (cell = 0; cell < num_cells; cell++) + add_cell (output, cell, cells[cell].cell_type, cell_nlists[cell].n, + cell_nlists[cell].node_list, cells[cell].mat); + + + /* store nodal data. + + data at nodes is separated into components. successive nodes of a + component are stored contiguously. for example, if you wish to + store two scalars and one 3-vector then this would be three + components and would be stored as (given n nodes in the model): + + 0 node 0, component 1 + 1 node 1, component 1 + . + . + . + n node n, component 1 + n+1 node 0, component 2 + n+2 node 1, component 2 + . + . + . + 2n node n, component 2 + 2n+1 node 0, component 3, 1st vector component + 2n+2 node 0, component 3, 2nd vector component + 2n+3 node 0, component 3, 3rd vector component + 2n+4 node 1, component 3, 1st vector component + + 2n+5 node 1, component 3, 2nd vector component + 2n+6 node 1, component 3, 3rd vector component + . + . + . + 5n-2 node n, component 3, 1st vector component + 5n-1 node n, component 3, 2nd vector component + 5n node n, component 3, 3rd vector component + + + the node component list has an entry for each compoment. each + entry specifies the dimensionality for each component. for example, + a scalar component would have an entry of one and a 3-vector would + have an entry of three. + + the node active list can be used to specify which data type is + currently active (being used to display results). the list has + an entry for each data component. if that entry is not zero + then it is active. currently, this functionality is not used by + any modules. + + node labels specify the user defined name of each data component. + + node units specify the user defined units of each data component. + + node minmax specifies the maximum and minimum values for each + data component. this has no meaning for vector components although + the max/min magnitude of the vector could be used. + + */ + + if (num_node_data) { + UCDstructure_set_node_components (*output, model_stats.node_comp_list, + model_stats.num_node_comp); + + + UCDstructure_set_node_active (*output, model_stats.node_active_list); + + UCDstructure_set_node_labels (*output, model_stats.node_data_labels, "."); + + UCDstructure_set_node_units (*output, model_stats.node_data_units, "."); + + if (model_stats.num_node_comp > 1) { + for (i = 0; model_stats.node_data_labels[i] != '.'; i++) + string[i] = model_stats.node_data_labels[i]; + string[i] = '\0'; + } + else + strcpy (string, model_stats.node_data_labels); + + AVSmodify_parameter ("Node Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.node_data_labels, "."); + + UCDstructure_set_node_minmax (*output, min_node_data, max_node_data); + + if (!UCDstructure_set_node_data (*output, node_data)) { + AVSerror ("Error in read_hll: can't set node data.\n"); + return (0); + } + } + else + AVSmodify_parameter ("Node Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + + + /* store cell data. */ + + if (num_cell_data) { + UCDstructure_set_cell_components (*output, model_stats.cell_comp_list, + model_stats.num_cell_comp); + + UCDstructure_set_cell_active (*output, model_stats.cell_active_list); + + UCDstructure_set_cell_labels (*output, model_stats.cell_data_labels, "."); + + for (i = 0; model_stats.cell_data_labels[i] != '.'; i++) + string[i] = model_stats.cell_data_labels[i]; + string[i] = '\0'; + + AVSmodify_parameter ("Cell Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.cell_data_labels, "."); + + if (!UCDstructure_set_cell_data (*output, cell_data)) { + AVSerror ("Error in read_hll: can't set cell data.\n"); + return (0); + } + } + else { + AVSmodify_parameter ("Cell Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + } + + + /* store model data. */ + + if (num_model_data) { + UCDstructure_set_data_labels (*output, model_stats.model_data_labels, "."); + + for (i = 0; model_stats.model_data_labels[i] != '.'; i++) + string[i] = model_stats.model_data_labels[i]; + string[i] = '\0'; + + AVSmodify_parameter ("Model Type", AVS_MINVAL | AVS_VALUE, string, + model_stats.model_data_labels, "."); + + if (!UCDstructure_set_data (*output, model_data)) { + AVSerror ("Error in read_hll: can't set model data.\n"); + return (0); + } + } + else + AVSmodify_parameter ("Model Type", AVS_MINVAL | AVS_VALUE, " ", + "", "."); + + if (*output) { + free (xc); + free (yc); + free (zc); + + if (num_node_data) { + free (node_data); + free (min_node_data); + free (max_node_data); + } + + if (num_cell_data) { + free (cell_data); + free (min_cell_data); + free (max_cell_data); + } + + if (num_model_data) { + free (model_data); + free (min_model_data); + free (max_model_data); + } + + free (cells); + + if (cell_nlists) + free (cell_nlists); + + if (bcell_nlists) + free (bcell_nlists); + } + } + return(1); + } + + +/*-----------------------------------------------------* + * * + * **** add_cell **** * + * * + * add a cell topology to the ucd structure. * + *-----------------------------------------------------*/ + +static void add_cell( UCD_structure** model, int cell, int ucd_cell_type, int n, + int* rnode_list, int mat_id ) + { + + static char *cell_type[] = {"pt", "line", "tri", "quad", "tet", + "pyr", "prism", "hex"}; + + int i, num_me_nodes, num_nodes, /* Not used: cell_found, */ + me_flag, node_list[40]; + + /************** + *** body *** + **************/ + + if (ucd_cell_type < NUM_CELL_TYPES) { + me_flag = 0; + num_nodes = UCD_num_nodes[ucd_cell_type]; + + + /* if the number of nodes read (n) is equal to the number of + nodes without mid-side nodes then send the read node list. + else set the mid-edge flag to indicate which edges have + mide-edge nodes. */ + + for (i = 0; i < num_nodes; i++) + node_list[i] = rnode_list[i] - 1; + + if (n != num_nodes) { + for (i = num_nodes, num_me_nodes = 0; i < n; i++) + if (rnode_list[i] != 0) { + node_list[num_nodes + num_me_nodes] = rnode_list[i] - 1; + me_flag = me_flag | (0x1 << (i - num_nodes)); + num_me_nodes++; + } + } + + UCDcell_set_information (*model, cell, (char *) (cell + 1), + cell_type[ucd_cell_type], + mat_id - 1, ucd_cell_type, me_flag, node_list); + } + } + + +/*-----------------------------------------------------* + * * + * **** read_binary **** * + * * + * read a ucd binary file. * + *-----------------------------------------------------*/ + +static int read_binary( const char* file_name, + Ctype** pcells, + int** pcell_nlists, + Mtype* model, + float** pxc, + float** pyc, + float** pzc, + float** pnode_data, + float** pcell_data, + float** pmodel_data, + float** pmin_node_data, + float** pmax_node_data, + float** pmin_cell_data, + float** pmax_cell_data, + float** pmin_model_data, + float** pmax_model_data ) + { + + //char magic; + + Ctype *cells; + + // FILE *fp; + + float *xc, *yc, *zc, *node_data, *cell_data, *model_data, + *min_node_data, *max_node_data, *min_cell_data, *max_cell_data, + *min_model_data, *max_model_data; + + int num_nodes, num_cells, num_node_data, + num_cell_data, num_model_data, *cell_nlists, num_nlist_nodes; + + /************** + *** body *** + **************/ + + node_data = cell_data = model_data = NULL; + max_cell_data = min_cell_data =max_model_data=min_model_data=NULL; + + //if (!(fp = fopen (file_name, "r"))) + // return (0); + + IEEEIO *file = new IEEEIO(file_name,IObase::Read); + if(!file->isValid()) + return (0); + ReadHLL *hll = new ReadHLL(*file); + int ndims, cellsz, celltype; + model->num_cell_data=model->num_node_data=model->num_model_data=0; + hll->selectDataset(0/*index*/, + ndims, + model->num_nodes,model->num_cells,model->num_node_data); + model->num_nlist_nodes=8*model->num_cells; // hexahedral cells + + switch(ndims){ + case 0: + cellsz=1; + celltype=UCD_POINT; + break; + case 1: + cellsz=2; + celltype=UCD_LINE; + break; + case 2: + cellsz=4; + celltype=UCD_QUADRILATERAL; + break; + case 3: + cellsz=8; + celltype=UCD_HEXAHEDRON; + break; + } + model->num_nlist_nodes=cellsz*model->num_cells; // hexahedral cells + // fill out basic parameters + num_nodes = model->num_nodes; + num_cells = model->num_cells; + num_node_data = model->num_node_data; + num_cell_data = model->num_cell_data; + num_model_data = model->num_model_data; + num_nlist_nodes = model->num_nlist_nodes; + + cells = (Ctype *)malloc(sizeof(Ctype) * num_cells); + cell_nlists = (int *)malloc(sizeof(int) * num_nlist_nodes); + + //fread ((char *)cells, sizeof(Ctype), num_cells, fp); + for(int i=0;ireadConnectivity(cell_nlists); + + xc = (float *)malloc(sizeof(float) * num_nodes); + yc = (float *)malloc(sizeof(float) * num_nodes); + zc = (float *)malloc(sizeof(float) * num_nodes); + + //fread ((char *)xc, sizeof(float), num_nodes, fp); + //fread ((char *)yc, sizeof(float), num_nodes, fp); + //fread ((char *)zc, sizeof(float), num_nodes, fp); + hll->readCoords(xc,yc,zc); + + if (num_node_data) { + int nm=0; + // Now read in information about the node data + char **names=new char*[num_node_data]; + for(nm=0;nmreadDataInfo(names,datatypes,veclens); + + node_data = (float *)malloc(sizeof(float) * num_nodes * num_node_data); + min_node_data = (float *)malloc(sizeof(float) * num_node_data); + max_node_data = (float *)malloc(sizeof(float) * num_node_data); + for(nm=0;nm1) { + printf("node_data[%u] has veclen %u which is too large to store in this implementation\n", + nm,veclens[nm]); + continue; + } + switch(datatypes[nm]){ + case IObase::Float32: + hll->readData(names[nm],node_data+(nm*num_nodes)); + break; + case IObase::Float64: + { double *data=new double[num_nodes]; + hll->readData(names[nm],data); + for(int idx=0,offset=num_nodes*nm;idxreadData(names[nm],data); + for(int idx=0,offset=num_nodes*nm;idxreadData(names[nm],data); + for(int idx=0,offset=num_nodes*nm;idxreadData(names[nm],data); + for(int idx=0,offset=num_nodes*nm;idxmax) max=pt; + if(ptnum_nodes = num_nodes; + model->num_cells = num_cells; + model->num_node_data = num_node_data; + model->num_cell_data = num_cell_data; + model->num_model_data = num_model_data; + + *pmax_node_data = max_node_data; + *pmin_node_data = min_node_data; + *pmax_cell_data = max_cell_data; + *pmin_cell_data = min_cell_data; + *pmax_model_data = max_model_data; + *pmin_model_data = min_model_data; + + // fclose (fp); + delete hll; + delete file; + + return(1); + } + +/*-----------------------------------------------------* + * * + * **** read_hll_init **** * + * * + *-----------------------------------------------------*/ + +static void +read_hll_init() + { + AVSstatic = (char *)0; + } + + +/*-----------------------------------------------------* + * * + * **** read_hll_finis **** * + * * + *-----------------------------------------------------*/ + +static void +read_hll_finis() + { + if (AVSstatic == NULL) return; + + free (AVSstatic); + } + + +static void +read_hll_desc() + { + int param; + + static char *choices = "...."; + + /************** + *** body *** + **************/ + + AVSset_module_name ("Read HLL", MODULE_DATA); + + AVScreate_output_port ("tet output", "ucd"); + + param = AVSadd_parameter ("read file", "string", 0, 0, ".inp"); + AVSconnect_widget (param, "browser"); + + AVSadd_parameter("Cell Connect", "boolean", 0, 0, 1); + + param = AVSadd_parameter("Node Data", "string", "Node Data", "Node Data", + NULL); + AVSconnect_widget(param, "text"); + + AVSadd_parameter ("Node Type", "choice", "", choices, "."); + + param = AVSadd_parameter("Cell Data", "string", "Cell Data", "Cell Data", + NULL); + AVSconnect_widget (param, "text"); + + AVSadd_parameter ("Cell Type", "choice", "", choices, "."); + + param = AVSadd_parameter("Model Data", "string", "Model Data", "Model Data", + NULL); + AVSconnect_widget (param, "text"); + + AVSadd_parameter ("Model Type", "choice", "", choices, "."); + + AVSset_init_proc ((AVS_FNCP) read_hll_init); + + AVSset_destroy_proc ((AVS_FNCP) read_hll_finis); + + AVSset_compute_proc ((AVS_FNCP) read_hll); + } + +#if __cplusplus +extern "C" { +#endif + +void +AVSinit_modules() + { + AVSmodule_from_desc ((AVS_FNCP) read_hll_desc); + } + +#if __cplusplus +} +#endif + diff --git a/src/AVSreadIEEE.c b/src/AVSreadIEEE.c new file mode 100644 index 0000000..9289c59 --- /dev/null +++ b/src/AVSreadIEEE.c @@ -0,0 +1,95 @@ +/* mod_gen Version 1 */ +/* Module Name: "Read IEEE" (Input) (Subroutine) */ +/* Author: John Shalf,50,50,none */ +/* Date Created: Wed Mar 26 13:49:06 1997 */ +/* */ +/* This file is automatically generated by the Module Generator (mod_gen)*/ +/* Please do not modify or move the contents of this comment block as */ +/* mod_gen needs it in order to read module sources back in. */ +/* */ +/* output 0 "out" field */ +/* param 0 "Filename" browser "" "" ":" */ +/* param 1 "RecordNumber" idial 0 0 1 */ +/* End of Module Description Comments */ + +#include +#include +#include +#include + +/* *****************************************/ +/* Module Description */ +/* *****************************************/ +int Read_IEEE_desc() +{ + + int in_port, out_port, param, iresult; + extern int Read_IEEE_compute(); + + AVSset_module_name("Read IEEE", MODULE_DATA); + + /* Output Port Specifications */ + out_port = AVScreate_output_port("out", "field"); + + /* Parameter Specifications */ + param = AVSadd_parameter("Filename", "string", "", "", ":"); + AVSconnect_widget(param, "browser"); + param = AVSadd_parameter("RecordNumber", "integer", 0, 0, 1); + AVSconnect_widget(param, "idial"); + + /* + param = AVSadd_parameter("SetExtents","boolean",0,0,0); + AVSconnect_widget(param,"toggle"); + param = AVSadd_parameter("SetCoordinates","choice", + "Set Min/Max", + "Set Min/Max:Set Edges:Set None", + ":"); + AVSconnect_widget(param,"radio_buttons"); + */ + + AVSset_compute_proc(Read_IEEE_compute); + return(1); +} + +/* *****************************************/ +/* Module Compute Routine */ +/* *****************************************/ +int Read_IEEE_compute(out,Filename,RecordNumber,SetExtents,SetCoordinates) + AVSfield **out; + char *Filename; + int RecordNumber; + int SetExtents; + char *SetCoordinates; +{ + /* + Its a pain to integrate C++ directly into the Read_IEEE code and + yet so much nicer to use the C++ interface than the C interface. + So we'll just call a c++ compute subroutine that is located in + another object file, "AVSreadcpp.cc". + + There is a version of this same thing in AVSreadhlcpp.cc which + makes use of the even higher level (and hence more convenient) + user interface. However there is some concern that it will be + harder to debug IEEEIO if we layer the interface too much so + its back to the low-level interface again. + */ + extern int readIEEE(); + return readIEEE(out,Filename,RecordNumber,1,"Set Edges"); + /* return readIEEE(out,Filename,RecordNumber,SetExtents,SetCoordinates); */ +} + +/* ***********************************************************************/ +/* Initialization for modules contained in this file. */ +/* ***********************************************************************/ +static int ((*mod_list[])()) = { + Read_IEEE_desc +}; +#define NMODS (sizeof(mod_list) / sizeof(char *)) + +AVSinit_modules() +{ + AVSinit_from_module_list(mod_list, NMODS); +} + +/* ----> START OF USER-SUPPLIED CODE SECTION #4 (SUBROUTINES, FUNCTIONS, UTILITY ROUTINES)*/ +/* <---- END OF USER-SUPPLIED CODE SECTION #4 */ diff --git a/src/AVSreadcpp.cc b/src/AVSreadcpp.cc new file mode 100644 index 0000000..eb5f139 --- /dev/null +++ b/src/AVSreadcpp.cc @@ -0,0 +1,216 @@ +#include +#include +#include +#include +/* John's Includes */ +#include +#include +#include +#include +/* Local Includes */ +#include +#include +#ifdef WITH_HDF +#include +#endif +// #include // an even higher level interface, but must skip for now + +extern "C" { +int readIEEE(AVSfield **out,char *Filename,int RecordNumber, + int SetExtents,char *SetCoordinates); +} + +int readIEEE(AVSfield **out,char *Filename,int RecordNumber, + int SetExtents,char *SetCoordinates){ + static IObase *infile=0; + // Handle case where Filename has changed + if(AVSparameter_changed("Filename") || !infile){ + // Filename has changed, so close any currently open data files + // (this is done by delete'ing here.) + if(infile) delete infile; + infile=0; + // Just in case the new file is bogus, hide the dial widgets so + // that they can't be messed with if the data isn't valid. + AVSparameter_visible("RecordNumber",0); +#ifdef WITH_HDF + if(strstr(strchr(Filename,','),"hdf")) + infile = new HDFIO(Filename,IObase::Read); + else +#endif + infile = new IEEEIO(Filename,IObase::Read); // open the datafile + + if(!infile->isValid()){ // if the file is not IEEEIO, exit + delete infile; + infile=0; + fprintf(stderr,"%s is not an IEEEIO file",Filename); + return 0; + } + if(infile->nDatasets()>1){// don't set widget dial for min=max=0 + AVSmodify_parameter("RecordNumber",AVS_VALUE|AVS_MAXVAL, + 0,0,infile->nDatasets()-1); + AVSparameter_visible("RecordNumber",1); + } // so dial widget remains hidden if dataset contains 1 or fewer datasets + RecordNumber=0; + } + // Failsafe sanity check (things are really hosed if this check fails) + if(!infile) { + puts("Not an IEEEIO file"); + AVSparameter_visible("RecordNumber",0); + return 0; + } + + // now do memory allocation for AVS + char AllocationDescription[64]; + char *typname; + IObase::DataType datatype; + int rank,dims[5]; + int nelements; + + infile->seek(RecordNumber); // seek to desired record + infile->readInfo(datatype,rank,dims); // get info about the dataset + // we are building the AVS memory description text string to do the allocation. + switch(datatype){ + case IObase::Float32: + puts("Data Type float"); + typname="float"; + break; + case IObase::Float64: + puts("Data Type double"); + typname="double"; + break; + case IObase::Int32: + typname="integer"; + break; + case IObase::uChar: + case IObase::Int8: + typname="byte"; + break; + } + + if(!strcmp("Set Edges",SetCoordinates)) + sprintf(AllocationDescription,"field %uD %u-space scalar rectilinear %s", + rank,rank,typname); // put it all together into the allocation string + else + sprintf(AllocationDescription,"field %uD %u-space scalar uniform %s", + rank,rank,typname); // put it all together into the allocation string + + //printf("AVS allocating %s\n",AllocationDescription); + //printf("With dims[0]=%d dims[1]=%d dims[2]=%d\n",dims[0],dims[1],dims[2]); + if(*out) AVSfield_free(*out); // free old memory if its still around + *out = (AVSfield *)AVSdata_alloc(AllocationDescription,dims); // and allocate! + if(!*out){ + fprintf(stderr,"Allocation of %s failed\n", + AllocationDescription); + return 0; // allocation failed + } + + /*--- + Note: So if this read doesn't work, you'll need to use a switch statement + with exact casts to the proper datatypes. + I skipped using the switch statement because it looks really stupid + but its necessary for some machines which align vectors + differently depending on the size of the type the vector + points to. (yes folks... this is what the "align" keyword is about) + Hopefully we won't use such poorly designed machines. + + This need not be done for the parameters though since that field + of the avsfld is always float. + ---*/ + AVSfield_float *fld=(AVSfield_float*)(*out); + puts("Preparing to read data"); + infile->read(fld->data); // read the data + puts("read data"); + int minindex,maxindex; + /*--- + In this section we are just setting the extents and edge points information + for AVS (the physical size of the dataset in floating point coordinates). + There are just two Attribute pairs that it will recognize to do this. + + 1) min_ext,max_ext + These are vectors of size which contain the + coordinates of the minimum and maximum corners of the bounding box. + 2) origin,delta + The GR people seem to like this. Its the origin (same as the min_ext) + of the dataset and then the delta (or "dx") between grid points in the + dataset. + + It is now able to handle these parameters as Float32 or Float64 data. + Integer is ignored. The dataset will simply be ranged from 0-dim[x] + if the above Attributes are not found. + ---*/ + { + float min_ext[5],max_ext[5]; + + if((minindex=infile->readAttributeInfo("min_ext",datatype,nelements))>0 && + (maxindex=infile->readAttributeInfo("max_ext",datatype,nelements))>0 && + (datatype==IObase::Float32 || datatype==IObase::Float64)) { + if(datatype==IObase::Float32){ + infile->readAttribute(maxindex,min_ext); + infile->readAttribute(minindex,max_ext); + } + else if(datatype==IObase::Float64){ + double maxext[5],minext[5]; + infile->readAttribute(maxindex,maxext); + infile->readAttribute(minindex,minext); + for(int i=0;ireadAttributeInfo("origin",datatype,nelements))>0 && + (maxindex=infile->readAttributeInfo("delta",datatype,nelements))>0 && + (datatype==IObase::Float32 || datatype==IObase::Float64)) { + if(datatype==IObase::Float32){ + infile->readAttribute(maxindex,fld->min_extent); + infile->readAttribute(minindex,fld->max_extent); + for(int i=0;ireadAttribute(maxindex,maxext); + infile->readAttribute(minindex,minext); + for(int i=0;imin_extent[i]=min_ext[i]; + fld->max_extent[i]=max_ext[i]; + } + } + if(!strcmp("Set Min/Max",SetCoordinates)){ + for(int i=0;ipoints[i*2]=min_ext[i]; + fld->points[i*2 + 1]=max_ext[i]; + } + } + else if(!strcmp("Set Edges",SetCoordinates)){ + for(int index=0,i=0;idimensions[i])); + printf("SetEdges[%u]: dx=%lf\n",i,dx); + for(int j=0;jdimensions[i];j++,index++){ + fld->points[index] = min_ext[i] + ((double)j)*dx; + } + } + } + } + return 1; // for now +} + + diff --git a/src/AmrFileReader.cc b/src/AmrFileReader.cc new file mode 100644 index 0000000..6047ce0 --- /dev/null +++ b/src/AmrFileReader.cc @@ -0,0 +1,153 @@ +#include +#include +#include "AmrFileReader.hh" +#include "FlexArrayTmpl.H" +void AmrFileReader::printGridInfo(AmrGrid &g){ + printf("Grid level=%u step=%u maxtime=%u\n",g.level,g.timestep,g.maxtime); + printf("\trank=%u dims[",g.rank); + for(int i=0;idebug) printf("buildInfoTable: getGrid index=%u\n",index); + if(this->debug) printGridInfo(g); + int i=grids.getSize(); + g.data=0; // zero out the data + grids.append(g); + if(g.level>maxlevel) + maxlevel=g.level; + if(!i){ + mintime = g.timestep; + maxtime = g.timestep; + maxtimeres = g.timerefinement; + maxlevel= g.level; + } + if(g.timestepmaxtime) + maxtime=g.timestep; + if(g.timerefinement>maxtimeres) + maxtimeres=g.timerefinement; + } +} + +void AmrFileReader::loadGrids(){ + if(!gridloading) return; + for(int i=0;idebug) printf("buildInfoTable: getGrid index=%u activegridindex %u\n",i,activeGrids[i]); + if(this->debug) printGridInfo(grids[activeGrids[i]]); + gridreader.getGridData(grids[activeGrids[i]],activeGrids[i]); + } +} + +void AmrFileReader::reclaimGrids(){ + if(!gridloading) return; + for(int i=0;imaxtime){ + printf("timestep %u is out of range %u:%u\n", + timestep,mintime,maxtime); + return; + } + activeGrids.purge(); + current_time=timestep; + if(this->debug) printf("setTime(%u): mintime=%u maxtime=%u\n",current_time,mintime,maxtime); + for(int i=0;idebug) printf("\tgrids[%u].timestep=%u maxtime=%u\n",i,grids[i].timestep, + grids[i].maxtime); + if(current_time>=grids[i].timestep && + current_timedebug) printf("\t\tAppendGrid number %u\n",i); + } + } + if(this->debug) puts("load grids"); + loadGrids(); + if(this->debug) puts("reclaim grids"); + reclaimGrids(); +} + +void AmrFileReader::showAllLevels(){ + for(int i=0;i &g){ + g.setSize(activeGrids.getSize()); + for(int i=0;i +#include +#include "AmrGridReader.hh" +#include "FlexArrayTmpl.H" + +class AmrFileReader { +protected: + int gridloading; + AmrGridReader gridreader; + FlexArray activeGrids; + FlexArray grids; // perhaps use a hashtable to find grids? + // Change to AmrGridFile structures + FlexArray levelmask; + IObase::DataType datatype; + int maxlevel,maxtimeres,mintime,maxtime; + int current_time; + // Internal Utility methods + void buildInfoTable(); + void loadGrids(); + void reclaimGrids(); + void purgeGrids(); + void printGridInfo(AmrGrid &g); +public: + int debug; + void printGridInfo(); + void printActiveGrids(); + AmrFileReader(IObase &f); + int getActiveIndex(int ii){ return activeGrids[ii];} + int getNumLevels(){ return maxlevel+1; } + void getTimeRange(int &min,int &max){ + min=mintime; + max=maxtime; + } + void setTime(int timestep); + // starts out with all selected + void showLevel(int level=-1){ // default is all (-1) + if(level>=levelmask.getSize() || level<0){ + printf("AmrConvert::showLevel(%u) : Level out of range 0:%u\n", + level,levelmask.getSize()-1); + } + else + levelmask[level]=1; + } + void showAllLevels(); + void hideLevel(int level=-1){ // default is all (-1) + if(level>=levelmask.getSize() || level<0){ + printf("AmrConvert::showLevel(%u) : Level out of range 0:%u\n", + level,levelmask.getSize()-1); + } + else + levelmask[level]=0; + } + int nLevels(){ return maxlevel+1; } + IObase::DataType getDataType(){return datatype;} + // For C interface + int getNumGrids(){ // number of active grids + return activeGrids.getSize(); + } + int getGrids(AmrGrid *g); + // For C++ interface + int getGrids(FlexArray &g); + void setDataLoadingOff(){ gridloading=0; purgeGrids();} + void setDataLoadingOn(){ gridloading=1; loadGrids();} +}; + +#endif diff --git a/src/AmrGrid.h b/src/AmrGrid.h new file mode 100644 index 0000000..cfa411f --- /dev/null +++ b/src/AmrGrid.h @@ -0,0 +1,24 @@ +#ifndef __AMR_GRID_H_ +#define __AMR_GRID_H_ +/* + Definition of the AMR grid structure for C + Defined so that the structure will be flat. +*/ +typedef struct AmrGrid { + int level; + int maxlevel; + int maxtime,timestep,persistence; /* at finest-level timestep */ + int rank,dims[3]; /* hardcode to 3D maximum dims */ + double delta[3],origin[3]; /* stored in file as delta and origin */ + // + double minext[3],maxext[3]; + int timerefinement,spatialrefinement[3]; + int nbytes; + int dataveclen; + int datatype; + int iorigin[3]; + int gridplacementrefinement[3]; + void *data; +} AmrGrid; + +#endif diff --git a/src/AmrGrid.hh b/src/AmrGrid.hh new file mode 100644 index 0000000..b29ec63 --- /dev/null +++ b/src/AmrGrid.hh @@ -0,0 +1,11 @@ +#ifndef __AMR_GRID_HH_ +#define __AMR_GRID_HH_ +/* + Definition of the AMR grid structure for C +*/ + +struct AmrGrid : public AmrGridT { + IObase::DataType datatype; +}; + +#endif diff --git a/src/AmrGridReader.cc b/src/AmrGridReader.cc new file mode 100644 index 0000000..3ea8f90 --- /dev/null +++ b/src/AmrGridReader.cc @@ -0,0 +1,87 @@ +// AmrGridReader +#include "AmrGridReader.hh" +#include +#include + +// Other stuff +AmrGrid *AmrGridReader::getGridInfo(AmrGrid &g,int index){ + g.dataveclen=1; + if(file.seek(index)=0){ + int lev; // should be Int level + file.readAttribute(attrnum,&lev); + if(lev>g.maxlevel) g.maxlevel=lev; + g.level=lev; + } + // check for existence of attribute named "time_refinement" + attrnum=file.readAttributeInfo("time_refinement",atype,length); + // "time_refinement" exists, so lets read it into the member g.timerefinement + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.timerefinement)); + } + // check for existence of the attribute named "spatial_refinement" + attrnum=file.readAttributeInfo("spatial_refinement",atype,length); + // it exists, so lets read it into the datastruct member g.spatialrefinement + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.spatialrefinement)); + } + + attrnum=file.readAttributeInfo("timestep",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.timestep)); + } + + attrnum=file.readAttributeInfo("origin",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.origin)); + + attrnum=file.readAttributeInfo("delta",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.delta)); + + attrnum=file.readAttributeInfo("min_ext",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.minext)); + + attrnum=file.readAttributeInfo("max_ext",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,(g.maxext)); + + attrnum=file.readAttributeInfo("persistence",atype,length); + if(attrnum>=0){ + file.readAttribute(attrnum,&(g.persistence)); + g.maxtime = g.timestep + g.persistence; + } + + attrnum=file.readAttributeInfo("iorigin",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,&(g.iorigin)); + + attrnum=file.readAttributeInfo("grid_placement_refinement",atype,length); + if(attrnum>=0) + file.readAttribute(attrnum,&(g.gridplacementrefinement)); + + g.data=0; + return &g; +} // done + +AmrGrid *AmrGridReader::getGridData(AmrGrid &g,int index){ + IObase::DataType atype; + // if(data) free(data); data=0; // make certain it is empty first + g.data = malloc(g.nbytes); + file.seek(index); + file.readInfo(atype,g.rank,g.dims); + g.datatype=atype; + file.read(g.data); + return &g; +} diff --git a/src/AmrGridReader.hh b/src/AmrGridReader.hh new file mode 100644 index 0000000..4c7e84c --- /dev/null +++ b/src/AmrGridReader.hh @@ -0,0 +1,29 @@ +#ifndef __AMRGRIDREADER_HH_ +#define __AMRGRIDREADER_HH_ + +#include +#include "AmrGrid.h" + +class AmrGridReader { + IObase &file; +public: + AmrGridReader(IObase &f):file(f){} + // get specific grid + AmrGrid *getGrid(AmrGrid &g,int index){ + if(file.seek(index)getGrid(*g,index); + } + // Other stuff + AmrGrid *getGridInfo(AmrGrid &g,int index); + AmrGrid *getGridData(AmrGrid &g,int index); +}; + + +#endif // __AMRGRIDREADER_HH_ diff --git a/src/AmrNode.hh b/src/AmrNode.hh new file mode 100644 index 0000000..9765939 --- /dev/null +++ b/src/AmrNode.hh @@ -0,0 +1,42 @@ +#ifndef __AMRNODE_HH_ +#define __AMRNODE_HH_ + +//#include "config.h" +#include "Bounds.hh" +#include + +struct sPoint { double x,y,z; }; +union pPoint { + double array[3]; + sPoint cartesian; +}; + +struct AmrNode { + pPoint location; + struct AmrNode *parent,*child; + int index; + int gridID; + int level; + float *data; + /* + IObase::DataType datatype; + union { + void *vdata; + float *fdata; + double *ddata; + int *idata; + char *cdata; + short *sdata; + }; */ + // DATATYPE data; + // my local ref to data... + // The grid is going to need the smarts to assign this... + // So data segment length is important. + // Or we need a struct with a copy operator + void setIndex(int i){ + index=i; + if(parent) parent->setIndex(i); + } +}; + +#endif diff --git a/src/AmrUcd.c b/src/AmrUcd.c new file mode 100644 index 0000000..b8067c6 --- /dev/null +++ b/src/AmrUcd.c @@ -0,0 +1,70 @@ +/* *****************************************/ +/* Includes and Global Defs */ +/* *****************************************/ +#include +#include +/* IAC CODE CHANGE : #include */ +#include + +#include +#include +#include +#include +#include +#include +/*#include "sds.h"*/ + +typedef union Coord { + struct { + int x,y,z; + } axis; + int vect[3]; +} Coord; + +int debug=0; + +int amrucd_desc (){ + int in_port, out_port, param, iresult; + extern int amrucd_compute(); + extern int amrucd_destroy(); + /*extern int amrucd_destroy();*/ + + AVSset_module_name("AMR-UCD Reader", MODULE_DATA); + + /* Output Port Specifications */ + out_port = AVScreate_output_port("Output", "ucd" ); + /* out_port = AVScreate_output_port("output","field uniform");*/ + /* Parameter Specifications */ + + + param = AVSadd_parameter("Filename", "string", "", "", ":"); + AVSconnect_widget(param, "browser"); + + param = AVSadd_parameter("Hold","boolean",0,0,1); + AVSconnect_widget(param,"toggle"); + + param = AVSadd_parameter("Threshold","boolean",1,0,1); + AVSconnect_widget(param,"toggle"); + + param = AVSadd_parameter("Generate Level Data","boolean",1,0,1); + AVSconnect_widget(param,"toggle"); + + param = AVSadd_parameter("Step", "integer", 0, 0, 1); + AVSconnect_widget(param, "idial"); + + param = AVSadd_float_parameter("Min",0.0,FLOAT_UNBOUND,FLOAT_UNBOUND); + param = AVSadd_float_parameter("Max",1.0,FLOAT_UNBOUND,FLOAT_UNBOUND); + + param = AVSadd_parameter("VisibleLevels","choice","","",":"); + AVSconnect_widget(param,"choice"); + + AVSset_compute_proc(amrucd_compute); + AVSset_destroy_proc(amrucd_destroy); + + return 1; +} + +AVSinit_modules() +{ + AVSmodule_from_desc (amrucd_desc); +} diff --git a/src/AmrUcdCompute.cc b/src/AmrUcdCompute.cc new file mode 100644 index 0000000..6eae19c --- /dev/null +++ b/src/AmrUcdCompute.cc @@ -0,0 +1,454 @@ +/* *****************************************/ +/* Includes and Global Defs */ +/* *****************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +// #include "config.h" +#include "FlexArrayTmpl.H" +#include +#include "AmrNode.hh" +// #include "AmrConvert.hh" +#include "AmrUcdFileReader.hh" +void DumpUCD(UCD_structure *u); + +extern "C" +{ + int amrucd_compute(UCD_structure **Output,char *Filename,int Hold,int Threshold, + int GenerateLevelData, int Step,float *Min,float *Max, + char *VisibleLevels); + void amrucd_destroy(); +} + +void amrucd_destroy(){ + puts("Destroyed AmrUcd"); // erase UCD datastructures? +} + +void GenerateFakeUCD(int Step,FlexArray &nodes,FlexArray &cells){ + float data[128]; + int i,index; + + //********* Generate some fake data (nsds quads in the z direction) + for(i=0;i<128;i++) data[i]=(float)i; + for(index=index=i=0;ilocation.cartesian.x=(float)x; + node->location.cartesian.y=(float)y; + node->location.cartesian.z=-(float)z; + node->data = data+index; + node->index=index; + nodes.append(node); + } + } + } + for(index=i=0;ilocation.cartesian.x, + (nodes[i])->location.cartesian.y, + (nodes[i])->location.cartesian.z); + } + for(i=0;i VisibleLevelString; + // must be pointers to nodes because some are possibly shared... + FlexArray nodes; // the nodes with their data values + FlexArray cells; // connectivity between the nodes + //AVSfield *GenerateFakeData(); + //AVSfield *ReadHDF(); + UCD_structure *ConvertToUCD(FlexArray &,FlexArray &,int); + if(AVSparameter_changed("Filename")){ + int mintime,maxtime; + IObase *newfile = new IEEEIO(Filename,IObase::Read); + if(!newfile->isValid()){ + printf("AmrUcd: Error opening datafile %s\n",Filename); + delete newfile; + return 0; + } + if(datafile) delete datafile; + datafile=newfile; // make current file + if(convertor) delete convertor; + convertor = new AmrUcdFileReader(*datafile); + // convertor->printGridInfo(); + convertor->getTimeRange(mintime,maxtime); + if((maxtime-mintime)<=1){ + AVSmodify_parameter("Step",AVS_VALUE|AVS_MINVAL|AVS_MAXVAL,mintime,mintime,maxtime+1); + AVSparameter_visible("Step",0); + } + else { + AVSmodify_parameter("Step",AVS_MINVAL|AVS_MAXVAL|AVS_VALUE,mintime,mintime,maxtime); + AVSparameter_visible("Step",1); + } + Step=mintime; + + // Now setup the VisibleLevelString + if(VisibleLevelString.getSize()>0) + VisibleLevelString.purge(); + for(int i=0;inLevels();i++){ + char buffer[12]; + sprintf(buffer,"*Level %2u:",i); + + // Only display first 3 levels + if(i>=3) { + *buffer='.'; + convertor->hideLevel(i); + } + + buffer[10]='\0'; + VisibleLevelString.append(buffer,10); + } + VisibleLevelString[convertor->nLevels()*10 - 1]='\0'; // cap the string off + // Now assign the string for the choice widget + AVSmodify_parameter("VisibleLevels",AVS_MINVAL|AVS_MAXVAL|AVS_VALUE, + "*Level 0",VisibleLevelString.getData(),":"); + } + if(!datafile || !convertor){ + puts("No valid datafile or convertor exists. No action taken."); + return 0; + } + + if(AVSparameter_changed("VisibleLevels")){ + int choicenum = AVSchoice_number("VisibleLevels",VisibleLevels) - 1; + if(choicenum>=0){ + if(VisibleLevelString[choicenum*10]=='*'){ // toggle off + VisibleLevelString[choicenum*10]='.'; + convertor->hideLevel(choicenum); + } + else { + VisibleLevelString[choicenum*10]='*'; + convertor->showLevel(choicenum); + } + AVSmodify_parameter("VisibleLevels",AVS_VALUE|AVS_MINVAL|AVS_MAXVAL, + VisibleLevels,VisibleLevelString.getData(),":"); + } + } + if(Hold) return 0; // no change as of yet + // GenerateFakeUCD(Step,nodes,cells); + if(*Output){ + puts("FREE UCD"); + DumpUCD(*Output); + UCDstructure_free(*Output); + } + // *Output=NULL; + convertor->setTime(Step); + convertor->getUcd(nodes,cells); + *Output=ConvertToUCD(nodes,cells,GenerateLevelData); // final gen of output + if(!*Output) return 0; + // Now if thresholding is there + if(Threshold){ + int idx; + if(GenerateLevelData) idx=1; + else idx=0; + (*Output)->min_node_data[idx]=*Min; + (*Output)->max_node_data[idx]=*Max; + for(int n=0;n<(*Output)->node_veclen;n++){ + printf("Component[%u] min/max data=%f:%f\n", + n,(*Output)->min_node_data[n],(*Output)->max_node_data[n]); + } + } + //for(int i=0;i &nodes,FlexArray &cells, + int GenerateLevelData){ + int i,j,k; + int util_flag,ucd_flags;/* define which components will be availible in structure */ + int num_cells,num_nodes; + char model_name[65]; + int cell_tsize, node_csize; + int num_model_data, num_cell_data, num_node_data; + int node_comp_list[10], num_node_comp,nodelist[8],active_node_list[10]; + float min_ext[3],max_ext[3],node_data_max[10],node_data_min[10],*xc,*yc,*zc; + int cell,node; + UCD_structure *output; + + printf("Convert to UCD\n"); + strcpy(model_name,"AMRUCD model"); + /*********************************/ + /* establish the UCD structure */ + /*********************************/ + /* Options: UCD_INT | UCD_MATERIAL_IDS | UCD_NODE_NAMES + | UCD_CELL_NAMES | UCD_CELL_TYPES */ + ucd_flags = UCD_INT; + num_cells = cells.getSize()/8; + num_nodes = nodes.getSize(); + printf("So numcells=%u and numnodes=%u\n",num_cells,num_nodes); + /* node connectivity, and only scalar nodal data */ + num_model_data = 0; + num_cell_data = 0; /* scalar cell data */ + util_flag = 0; /* no cell-edge connectivity */ + + /* or should it be total size */ + cell_tsize = num_cells*8; // This is tested to be correct (will warn) + node_csize = 0; // no node connectivity + if(GenerateLevelData){ + num_node_data = 2; /* how much ??? */ + node_comp_list[0]=1; + node_comp_list[1]=1; + num_node_comp = 2; /* no nodal data */ + } + else{ + num_node_data = 1; /* how much ??? */ + node_comp_list[0]=1; + node_comp_list[1]=0; + num_node_comp = 1; + } + + printf("Allocate UCD structure\n"); + printf("Params:\n\tmodel_name: %s\n\t\ +num_model_data: %u\n\t\ +ucd_flags: %u\n\t\ +num_cells: %u\n\t\ +cell_tsize: %u\n\t\ +num_cell_data: %u\n\t\ +num_nodes: %u\n\t\ +node_csize: %u\n\t\ +num_node_data: %u\n\t\ +util_flag: %u\n",model_name, + num_model_data, + ucd_flags, + num_cells, + cell_tsize, + num_cell_data, + num_nodes, + node_csize, + // num_node_data, + num_node_comp, + util_flag); + + output = (UCD_structure *)UCDstructure_alloc (model_name, + num_model_data, + ucd_flags, + num_cells, + cell_tsize, + num_cell_data, + num_nodes, + node_csize, + num_node_data, + util_flag); + DumpUCD(output); + if(!output){ + puts("AmrUcdCompute: UCD structure Allocation Failed!!!!"); + return 0; + } + // printf("Address of struct is %u\n",(unsigned)output); + // should copy directly + xc = new float[num_nodes]; + yc = new float[num_nodes]; + zc = new float[num_nodes]; + puts("Set Node connectivity and coords"); + for(i=0;i<3;i++) + min_ext[i]=max_ext[i]=(nodes[0])->location.array[i]; + + for(node=0;node < nodes.getSize();node++){ + float x,y,z; + int clist[8]={0,0,0,0,0,0,0,0}; + AmrNode *n=nodes[node]; + xc[node]=x=n->location.cartesian.x; + if(xmax_ext[0]) max_ext[0]=x; + yc[node]=y=n->location.cartesian.y; + if(ymax_ext[1]) max_ext[1]=y; + zc[node]=z=n->location.cartesian.z; + if(zmax_ext[2]) max_ext[2]=z; + // was (char *) node+1 + if(!UCDnode_set_information(output,node,(char *)(node+1),0,clist)){ + puts("Error setting node information!!!!"); + } + } + printf("need to store %u positions\n",node); + printf("set positions in 3-space minext=%f:%f:%f\tmaxext=%f:%f:%f\n", + min_ext[0],min_ext[1],min_ext[2], + max_ext[0],max_ext[1],max_ext[2]); + //for(i=0;i<3;i++) min_ext[i]=max_ext[i]=0.0; + if(!UCDstructure_set_node_positions(output,xc,yc,zc)){ + puts("Error setting node positions!!!!"); + } + //printf("Now free the pointers"); + //for(i=0;i %u\n", + UCDstructure_set_extent(output,min_ext,max_ext)); + /* now cell topology */ + puts("Set cell connectivity"); + int cellidx; + for(cell=cellidx=0;cell=num_cells || cell>=cells.getSize()) puts("Error!!!! Too many Cells"); + } + puts("now set the data"); + /* Order of operations + for each node position + UCDnode_set_information(*output,nodenumber,nodenumber+1,*/ + /* Now Set the node/vertex data */ + /* nodedata is in the field */ + printf("set node Data numcomp=%u compsize=%u:%u\n", + num_node_comp,node_comp_list[0],node_comp_list[1]); + UCDstructure_set_node_components(output,node_comp_list,num_node_comp); + + // Just manually set stuff in the data structure + printf("util_flag=%u\n",output->util_flag); + printf("max_ext[2]=%u\n",output->max_extent[2]); + + active_node_list[0]=1; active_node_list[1]=0; + UCDstructure_set_node_active(output,active_node_list); + int dataindex; + if(GenerateLevelData){ + UCDstructure_set_node_labels(output,"level.data","."); + node_data_min[0]=node_data_max[0]=(float)((nodes[0])->level); + node_data_min[1]=node_data_max[1]=(float)((nodes[0])->data[0]); + dataindex=1; + } + else { + UCDstructure_set_node_labels(output,"data","."); + //node_data_min[0]=node_data_max[0]=(float)((nodes[0])->level); + node_data_min[0]=node_data_max[0]=(float)((nodes[0])->data[0]); + dataindex=0; + } + // KLUDGE!!! Possibly redundant malloc + + float *node_data = new float[nodes.getSize()*num_node_data]; + // Crash!! + printf("Num Node Data= %u floats\n",nodes.getSize()); + int index=0; + // Colorize by GridID??? wah? + if(GenerateLevelData){ + for(i=0,index=0;ilevel); // need level later!!! + // printf("index[%u] valI=%u val=%f\n",i,nodes[i]->gridID,val); + if(node_data_max[0]val) node_data_min[0]=val; + if(val>6) printf("index[%u] valI=%u val=%f\n",i,nodes[i]->gridID,val); + node_data[index]=val; + } // Crash here + printf("node_data_max[0]=%f node_data_min[0]=%f\n",node_data_max[0],node_data_min[0]); + puts("done setting levelinfo"); + } + + for(i=0;idata; + //printf("DataPtr[%u]=%lu val=%f\r",i,valptr,*valptr); + float val = *valptr; + if(node_data_max[dataindex]val) node_data_min[dataindex]=val; + node_data[index]=val; + } + puts("\nset node data"); + printf("UCDstructure_set_node_data->%u\n", + UCDstructure_set_node_data(output,node_data)); + + printf("After set node data util_flag=%u\n",output->util_flag); + printf("max_ext[2]=%u\n",output->max_extent[2]); + + printf("UCDstructure_set_node_minmax->%u\n", + UCDstructure_set_node_minmax(output,node_data_min,node_data_max)); + printf("Set Data min:max %f:%f %f:%f\n", + node_data_min[0],node_data_max[0], + node_data_min[1],node_data_max[1]); + // for(i=0;iutil_flag); + printf("max_ext[2]=%u\n",output->max_extent[0]); + //output->util_flag=0; + DumpUCD(output); + return output; +} + + +void DumpUCD(UCD_structure *u){ + if(u->name) printf("UCD_Structure: name=%s\n",u->name); + else printf("UCD_Structure: \n"); + printf("\tnameflag=%u util_flag=%u ncells=%u nnodes=%u\n", + u->name_flag,u->util_flag, + u->ncells,u->nnodes); + printf("\tmin:max extent %f,%f,%f:%f,%f,%f\n", + u->min_extent[0], u->min_extent[1], u->min_extent[2], + u->max_extent[0], u->max_extent[1], u->max_extent[2]); + printf("\tStructure data=%lu\n",(unsigned long)(u->data)); + if(u->cell_name) printf("Has Cell Names\n"); + else printf("\n"); + printf("\tCell: veclen=%u, node_conn_size=%u last_cell=%u\n", + u->cell_veclen,u->node_conn_size,u->ucd_last_cell); + if(u->node_conn_size){ + if(u->node_list) { + printf("\thas cell list %lu\n",u->node_list); + } + if(u->node_list_ptr){ + printf("\thas node list pointer %lu\n",u->node_list_ptr); + printf("\tFirstNode %u:%u ++ %u:%u 8th node = %u:%u\n", + u->node_list[0],u->node_list_ptr[0], + u->node_list[1],u->node_list_ptr[1], + u->node_list[8],u->node_list_ptr[8]); + } + } + if(u->node_name) printf("\tHas Node Names\n"); + else printf("\t\n"); + printf("\tNode: veclen=%u, cell__conn_size=%u last_node=%u\n", + u->node_veclen,u->cell_conn_size,u->ucd_last_node); + if(u->cell_conn_size){ + if(u->cell_list) { + printf("\thas cell list %lu\n",u->cell_list); + } + if(u->cell_list_ptr){ + printf("\thas cell list pointer %lu\n",u->cell_list_ptr); + printf("\tFirstCell %u:%u ++ %u:%u 8th cell = %u:%u\n", + u->cell_list[0],u->cell_list_ptr[0], + u->cell_list[1],u->cell_list_ptr[1], + u->cell_list[8],u->cell_list_ptr[8]); + } + } + printf("\trefcount=%u shm_base=%lu\n",u->refcnt,(unsigned long)(u->shm_base)); +} diff --git a/src/AmrUcdFileReader.cc b/src/AmrUcdFileReader.cc new file mode 100644 index 0000000..9057f8f --- /dev/null +++ b/src/AmrUcdFileReader.cc @@ -0,0 +1,27 @@ +#include +#include +#include "AmrUcdFileReader.hh" + +void AmrUcdFileReader::getUcd(FlexArray &nodes, + FlexArray &cells){ + genUCD.purge(); // Auto-Purges AmrNode's + for(int i=0;ilevel, grid->origin, grid->dx, grid->rank, + // grid->dims, (float *)(grid->data)); + genUCD.addGrid(grids[activeGrids[i]]); + } + else { + //printf("Grid is active, but level mask is OFF for grid [%u] level %u\n", + // activeGrids[i],lev); + } + } + printf("****buildNodeHierarchy\n"); + genUCD.buildNodeHierarchy(); + printf("****buildUCD\n"); + genUCD.buildUCD(nodes,cells); + printf("nnodes = %u ncells = %u\n",nodes.getSize(),cells.getSize()); + puts("*** done ucd build"); +} diff --git a/src/AmrUcdFileReader.hh b/src/AmrUcdFileReader.hh new file mode 100644 index 0000000..9e10496 --- /dev/null +++ b/src/AmrUcdFileReader.hh @@ -0,0 +1,38 @@ +/* + Code objects with attibutes for behavior on instantiation + For example + Array + fast indexing + slow copy + button + texturemapped + +*/ + +#ifndef __AMRUCDFILEREADER_HH_ +#define __AMRUCDFILEREADER_HH_ +#include +#include "AmrFileReader.hh" +#include "AmrUcdGridHierarchy.hh" + +/* + It appears that AmrUcdGrid should not be an + external data structure. + + It should be hidden inside of the AmrGridHierarchy +*/ +class AmrUcdFileReader : public AmrFileReader { +protected: + AmrUcdGridHierarchy genUCD; + // feed the AmrUcdGrid's to the hierarchy + // but reclaimation of those grids is questionable. + + // However, the amrgridhierarchy should accept a + // reference to AmrGrid as input. +public: + AmrUcdFileReader(IObase &f):AmrFileReader(f){ + } + void getUcd(FlexArray &nodes, FlexArray &cells); +}; + +#endif diff --git a/src/AmrUcdGridHierarchy.cc b/src/AmrUcdGridHierarchy.cc new file mode 100644 index 0000000..adaf8e5 --- /dev/null +++ b/src/AmrUcdGridHierarchy.cc @@ -0,0 +1,340 @@ +#include +#include +#include "AmrUcdGridHierarchy.hh" + +void AmrUcdGridHierarchy::AmrUcdGrid::copyFromAmrGrid(AmrGrid &g){ + level = g.level; + dataveclen=g.dataveclen; + rank = g.rank; + datatype = IObase::Int2DataType(g.datatype); + // Perhaps should do floating point only + vdata = g.data; + // copy to float datatype + printf("AmrUcdGridHierarchy:: dataveclen=%u\n",dataveclen); + if(g.data){ + int nelements = IObase::nElements(g.rank,g.dims); + register int i; + //if(datatype!=IObase::Float32) + data = new float[nelements]; + switch(datatype){ + case IObase::Float32: + printf("AmrUcdGridHierarchy:: Original data is float use directly\n"); + printf("\tpointerbase=%lu last=%lu\n",data,(data+nelements)); + //data=(float*)g.data; + for(i=0;i=dims[i] && i<2;i++){ + mindex[i]=0; + (mindex[i+1])++; + } + // assign using correct type (could put outside of loop to optimize) + n->data = data+dataindex; + n->level = level; // semiredunant, but necessary for AVS + /* + if(datatype==IObase::Float32) + n->fdata=fdata+dataindex; + else if(IObase::Float64) + n->ddata=ddata+dataindex; + else if(IObase::Int32 || IObase::uInt32) + n->idata=idata+dataindex; + else if(IObase::Int16 || IObase::uInt16) + n->sdata=sdata+dataindex; + else if(IObase::Int8 || IObase::uInt8) + n->cdata=cdata+dataindex; + */ + n->child=n->parent=0; // for now (will fix this up later) + n->index=-1; // nil index for now + n->gridID = gridID; + for(i=0;i<3;i++) + n->location.array[i] = origin[i] + delta[i]*(double)(mindex[i]); + // assumes f77 order for arrays + } +} + + +AmrUcdGridHierarchy::~AmrUcdGridHierarchy() { purge(); } + +void AmrUcdGridHierarchy::purge(){ + for(int l=0;l0){ // make grid hierarchy (eg. assign parents) (perhaps doubly-link) + // compare the bounding box to all grids in parent level + FOREACH(parent,grids[g.level-1]){ // OrderedList needs copy constructor + if(parent->bounds.contains(grid->bounds)){ // compared + grid->parent=parent; + parent->children.append(grid);// do forward ref + break; + } + } + } + grids[g.level].add(grid); +} + +void AmrUcdGridHierarchy::buildNodeHierarchy(){ + int i; + levelinfo.setSize(grids.getSize()); + for(i=0;idelta); + else{ + double fakedelta[5]={1,1,1,1,1}; + printf("AmrUcdGridHierarchy::buildNodeHierarchy(): Using Fake delta for level %u (shouldn't do that)\n",i); + levelinfo[i].setDelta(fakedelta); + } + } + for(i=0;i<(levelinfo.getSize()-1);i++) + levelinfo[i].setStride(levelinfo[i+1].delta); + // cycle through each level and find parent nodes for each node + //-------------Node Parenting Cycle---------------------------- + puts("node parenting cycle"); + for(i=1;iparent; + if(!parent) continue; // failsafe for NULL parent + // stride through the parent doing replacement + // first compute the strides through the parent grid + // as well as the origin in parent coordinates + for(int j=0;j<3;j++){ + register double dp=parent->origin[j]; + register double dc=grid->origin[j]; + register double dx=dc-dp; // difference between origins + dx /= parent->delta[j]; // if diff > .5 then use it? + if(j==0) printf("dparent=%lf dchild=%lf dx=%lf\n",dp,dc,dx); + // (no just need to round it) + origin[j]=(int)(dx+0.5); // this is a marginally bogus way to round up. + stride[j]=levelinfo[i-1].childstride[j]; + } + printf("NodeParenting L%u: origin=%u:%u:%u stride=%u\n",i,origin[0],origin[1],origin[2],stride[0]); + int px,x,py,y,pz,z; + // typedef DATATYPE AmrNode; + FlexArray *pnodes=&(parent->points); + FlexArray *nodes=&(grid->points); + for(z=0,pz=origin[2];zdims[2];z+=stride[2],pz++){ + int zi=grid->dims[1]*z; + int pzi=parent->dims[1]*pz; + for(y=0,py=origin[1];ydims[1];y+=stride[1],py++){ + int yi=(zi+y)*grid->dims[0]; + int pyi=(pzi+py)*parent->dims[0]; + for(x=0,px=origin[0];xdims[0];x+=stride[0],px++){ + register int pindex=px+pyi; + register int cindex=x+yi; + // ugh! finally we get to assign parents to the nodes + (*pnodes)[pindex].child=&((*nodes)[cindex]); + (*nodes)[cindex].parent=&((*pnodes)[pindex]); + } + } + } + } + } +} + +void AmrUcdGridHierarchy::print(){ + //************Print Some Results*********************** + for(int i=0;igridID); + int x,y,index; + + printf("=====: "); + for(x=0;xdims[0];x++){ + // print a row + printf("%5u ",x); + } + + //puts("-----------------------------") + for(y=0,index=0;ydims[1];y++,index+=grid->dims[0]){ + printf("\n[%3u]X: ",y); + for(x=0;xdims[0];x++){ + // print a row + printf("%5.3f ",grid->points[index+x].location.cartesian.x); + } + printf("\n Y: "); + for(x=0;xdims[0];x++){ + // print a row + printf("%5.3f ",grid->points[index+x].location.cartesian.y); + } + printf("\n Z: "); + for(x=0;xdims[0];x++){ + // print a row + printf("%5.3f ",grid->points[index+x].location.cartesian.z); + } + printf("\n P: "); + for(x=0;xdims[0];x++){ + if(grid->points[index+x].parent) + printf("%5u ",grid->points[index+x].parent->gridID); + else + printf("None "); + } + printf("\n C: "); + for(x=0;xdims[0];x++){ + if(grid->points[index+x].child) + printf("%5u ",grid->points[index+x].child->gridID); + else + printf(" None "); + } + } + printf("\n"); + } + } +} + +void AmrUcdGridHierarchy::buildUCD(FlexArray &nodes,FlexArray &cells){ + // OK, first build pointlist by adding only cells without children + // for each one added to list, set its index member + // also set index for all parents recursively. (have recursive setindex in + // as a static member function of each node) + int ctr,i; + //**** Init all node indexes to -1 + printf("AmrUcdGridHierarchy::buildUCD(): Initialize UCD\n"); + for(i=0;ipoints.getData(); + for(long idx=0;idxnelements;idx++) + points[i].index=-1; + } + } + // print(); + //**** Top-down assignment of indices for each node without child + // If a node has a child, then the child will be superceding it + // for indices + printf("\ttop-down assign indices\n"); + for(i=levelinfo.getSize()-1;i>=0;--i){ + printf("\tLevel[%u]\n",i); + AmrUcdGrid *grid; + FOREACH(grid,grids[i]){ + AmrNode *points=grid->points.getData(); + for(long idx=0;idxnelements;idx++){ + if(!points[idx].child){ // if no child + // then assign unique index + points[idx].setIndex(nodes.getSize()); + nodes.append(points+idx); // append to nodelist + } + } + } + } + printf("Number of nodes in all = %u\n",nodes.getSize()); + // OK, nows the time in schprockets when we dance... + //**** Top-down building of Hexahedral cells + //printf("now build hexahedral cells\n"); + for(i=levelinfo.getSize()-1;i>=0;i--){ + printf("\tL%u\n",i); + AmrUcdGrid *grid; + int nodeindices[8],mapped[8]; + FOREACH(grid,grids[i]){ + AmrNode *points=grid->points.getData(); + // verify that at least one point doesn't have a child + // if all have children then continue + int x,y,z; + int *dims=grid->dims; + int zstep=dims[1]*dims[0]; + int ystep=dims[0]; // xstep=1 + int idx; + // setup the cell indices + for(idx=0;idx<8;idx++){ + nodeindices[idx]=0; + } + for(idx=0;idx<4;idx++) { + nodeindices[idx]+=zstep; + } + for(idx=0;idx<=4;idx+=4){ + nodeindices[idx+2]+=1; + nodeindices[idx+3]+=1; + nodeindices[idx]+=ystep; + nodeindices[idx+3]+=ystep; + } + //***** Build the Cell list + for(z=0;z<(dims[2]-1);z++){ + //printf("\t\tZ%u\n",z); + for(y=0;y<(dims[1]-1);y++){ + for(x=0;x<(dims[0]-1);x++){ + // OK, now we find the real indices and + for(idx=0;idx<8;idx++){ + mapped[idx]=points[nodeindices[idx]].index; + if(mapped[idx]>nodes.getSize()){ + printf("indexing error at grid %u, position %u,%u,%u idx[%u]=%u\n", + grid->gridID,x,y,z,idx,mapped[idx]); + } + } + // append to cells list + cells.append(mapped,8); // copies the mapped array? + // now we save this sequence; + for(idx=0;idx<8;idx++) (nodeindices[idx])++; + } + for(idx=0;idx<8;idx++) (nodeindices[idx])++; + } + for(idx=0;idx<8;idx++) (nodeindices[idx])+=ystep; + } + } + } +} diff --git a/src/AmrUcdGridHierarchy.hh b/src/AmrUcdGridHierarchy.hh new file mode 100644 index 0000000..94835a3 --- /dev/null +++ b/src/AmrUcdGridHierarchy.hh @@ -0,0 +1,134 @@ +#ifndef __AMRUCDGRIDHIERARCHY_HH_ +#define __AMRUCDGRIDHIERARCHY_HH_ + +#include "FlexArrayTmpl.H" +#include "OrderedList.H" +#include "AmrNode.hh" +#include "Bounds.hh" +#include "IO.hh" +#include "AmrGrid.h" +#include "Vec3f.hh" + +class AmrUcdGridHierarchy { + struct AmrUcdGrid { + int level; + int rank; + int dims[3]; + double origin[3],delta[3]; + IObase::DataType datatype; + union { + void *vdata; + int *idata; + float *fdata; + double *ddata; + short *sdata; + char *cdata; + }; + float *data; // local data + // Attributes + long nelements; + int gridID,complete; + // DATATYPE data; // assume f77 order (should be void*) + int dataveclen; + Bounds bounds; + FlexArray points; // assume f77 order + AmrUcdGrid *parent; + FlexArray children; + // Constructors + AmrUcdGrid(AmrGrid &g):complete(0),parent(0){ + copyFromAmrGrid(g); + regenPoints(); + } + ~AmrUcdGrid(){ + if(fdata!=data) delete data; + data=0; + } + private: + // utilities + void copyFromAmrGrid(AmrGrid &g); + void regenPoints(); + }; + struct LevelInfo { + double delta[3]; // find differences in delta + int childstride[3]; // stride through children + void setDelta(double *dx){ + for(int i=0;i<3;i++){ + // childstride[i]=1; // why? + delta[i]=dx[i]; // CRASH !!! + } + printf("setDelta=%lf\n",delta[0]); + } + void setStride(double *childdx){ + for(int i=0;i<3;i++) + childstride[i] = (int)(delta[i]/childdx[i] + 0.5); + + printf("Stride=%u from dx=%lf\n",childstride[0],childdx[0]); + } + }; +public: + typedef OrderedList GridList; + FlexArray grids; + + FlexArray levelinfo; +// public: + ~AmrUcdGridHierarchy(); + void addGrid(AmrGrid &grid); // copy from + //*** Now do parenting of the nodes (can be combined with the addGrid +#if 0 // disabled + struct CellInfo { + struct Face { + Vec3f normal; + // int neighbor[3]; return as -1,0,1 values + Vec3f minext[3]; + Vec3f maxext[3]; + }; + Face faces[6]; + float Vec3f[3],Vec3f[3]; + }; + static inline AmrUcdGrid *Grid2Cell(int coord[3],AmrUcdGrid *gridinfo ,CellInfo *cellinfo){ + // automatically hoists grid reference if intersection with denser region + // automatically deprecates grid reference if intersection with boundary + // returns null if encounter with outer boundary + // Ordering of faces are {+x -x +y -y +z -z} + + // actually totally wrong... need to compute cell min max!!!!!! + Vec3f min(gridinfo->bounds.min),max(gridinfo->bounds.max); + + cellinfo->face[0].minext.set(min[0],min[1],min[2]); // m000 + cellinfo->face[0].maxext.set(min[0],max[1],max[2]); // M011 + cellinfo->face[1].minext.set(max[0],min[1],min[2]); // m100 + cellinfo->face[1].maxext.set(max[0],max[1],max[2]); // M111 + cellinfo->face[2].minext.set(min[0],min[1],min[2]); // m000 + cellinfo->face[2].maxext.set(max[0],min[1],max[2]); // M101 + cellinfo->face[3].minext.set(min[0],max[1],min[2]); // m010 + cellinfo->face[3].maxext.set(max[0],max[1],max[2]); // M111 + cellinfo->face[4].minext.set(min[0],min[1],min[2]); // m000 + cellinfo->face[4].maxext.set(max[0],max[1],min[2]); // M110 + cellinfo->face[5].minext.set(min[0],min[1],max[2]); // m001 + cellinfo->face[5].maxext.set(max[0],max[1],max[2]); // M111 + + Vec3f p1(min[0],min[1],min[2]),// (0,0,0), + p2(max[0],min[1],min[2]),// (1,0,0), + p3(max[0],max[1],min[2]),// (1,1,0), + p4(min[0],max[1],min[2]),// (0,1,0), + p5(min[0],min[1],max[2]),// (0,0,1), + p6(max[0],min[1],max[2]),// (1,0,1), + p7(max[0],max[1],max[2]),// (1,1,1), + p8(min[0],max[1],max[2]); // (0,1,1) + cellinfo->face[0].normal.norm(p1,p4,p8); + cellinfo->face[1].normal.norm(p3,p2,p6); + cellinfo->face[2].normal.norm(p2,p1,p5); + cellinfo->face[3].normal.norm(p4,p3,p7); + cellinfo->face[4].normal.norm(p1,p4,p3); + cellinfo->face[5].normal.norm(p8,p7,p6); + } +#endif // disabled + void purge(); + void buildNodeHierarchy(); + void print(); + void buildUCD(FlexArray &nodes,FlexArray &cells); +}; + + +#endif + diff --git a/src/AppendTest.c b/src/AppendTest.c new file mode 100644 index 0000000..d1e1349 --- /dev/null +++ b/src/AppendTest.c @@ -0,0 +1,69 @@ +#include +#include "IEEEIO.h" + +int main(int argc, char **argv) { + IOFile noapp, app, appch; + Int i,j,k; + double x[20][20][20]; + double y[10][20][20]; + int dims[3],chdim[3],chori[3]; + + dims[0] = 20; dims[1] = 20; dims[2] = 20; + + for (i=0;i<20;i++) + for (j=0;j<20;j++) + for (k=0;k<20;k++) { + x[i][j][k] = 20*i + j + k*0.05; + if (i < 10) y[i][j][k] = x[i][j][k]; + } + + /* OK so first write the one three times without appending */ + noapp = IEEEopen("noapp.ieee","w"); + for (i=0;i<3;i++) { + IOwrite(noapp, FLOAT64, 3, dims, x); + } + IOclose(noapp); + + /* Now do the appended one */ + for (i=0;i<3;i++) { + if (i == 0) + app = IEEEopen("app.ieee","w"); + else + app = IEEEopen("app.ieee","a"); + IOwrite(app, FLOAT64, 3, dims, x); + IOclose(app); + } + + /* Now do a chunked one */ + for (i=0;i<3;i++) { + if (i == 0) + appch = IEEEopen("appch.ieee","w"); + else + appch = IEEEopen("appch.ieee","a"); + + IOreserveChunk(appch,FLOAT64,3,dims); + chdim[0] = 20; + chdim[1] = 20; + chdim[2] = 20; + chori[0] = 0; + chori[1] = 0; + chori[2] = 0; + IOwriteChunk(appch,chdim,chori,x); + IOclose(appch); + } + + /* Now do a chunked one without appending */ + appch = IEEEopen("noappch.ieee","w"); + for (i=0;i<3;i++) { + IOreserveChunk(appch,FLOAT64,3,dims); + chdim[0] = 20; + chdim[1] = 20; + chdim[2] = 20; + chori[0] = 0; + chori[1] = 0; + chori[2] = 0; + IOwriteChunk(appch,chdim,chori,x); + } + IOclose(appch); + +} diff --git a/src/Arch.h b/src/Arch.h new file mode 100644 index 0000000..5d0eeb0 --- /dev/null +++ b/src/Arch.h @@ -0,0 +1,74 @@ +#ifndef _MACHDEFS_H_ +#define _MACHDEFS_H_ + +#ifdef ANSI +#define PROTO(x) x +#else +#define PROTO(x) () +#endif + +#if defined(SGI) || defined(CM5) || defined (DEC) +#define F77NAME(a,b,c) a +#else +#ifdef HP +#define F77NAME(a,b,c) b +#else +#ifdef CRAY +#define F77NAME(a,b,c) c +#endif +#endif +#endif + +#ifndef F77NAME +#define F77NAME(a,b,c) a +#endif + + +#ifndef SGI +#ifdef WIN32 +typedef __int64 Long8; +#else +typedef long Long8; +#endif +#else /* default SGI behavior. long longs=8 bytes long=4 bytes*/ +typedef long long Long8; +#endif + +#ifdef T3E +#ifndef FFIO +#define FFIO /* forces it to use FFIO if on a T3E */ +#endif +typedef short Int; /* T3E uses 8-byte integers as default */ +typedef short Long; /* this is wierd, but its a T3E... */ +#else +typedef int Int; /* every other sane design uses 4-byte ints */ +typedef int Long; /* for now Long *MUST* be 32bit integer for PC compatability */ +/* if we run into problems later we'll just need have a separate rev of the file format for PC's */ +#endif + +#ifdef WIN32 /* this aint a happenin thang yet... */ +/* #include ... bahh!!! Win32 doesn't have this! */ +typedef unsigned int IOFile; /* cast to integer for pointers :( */ +union Integer8 { + long l; + int i[2]; + char c[8]; +}; /* what can be said about the byte order though? */ +#else /* its a Mac or Unix box probably */ +#include +typedef caddr_t IOFile; /* use caddr_t to store pointers */ +#endif + +#ifdef HP +#define NO_RECURSIVE_INLINE +#endif + +#ifndef CONST_BROKEN +#define CONST const +#else +#ifdef CONST +#undef CONST +#endif +#endif + +#endif diff --git a/src/Bounds.cc b/src/Bounds.cc new file mode 100644 index 0000000..f291050 --- /dev/null +++ b/src/Bounds.cc @@ -0,0 +1,29 @@ +#include "Bounds.hh" + +void Bounds::setFromExtents(double *p1,double *p2){ + for(int i=0;i<3;i++){ + if(p1[i]1) + max[i]=origin[i]+dx[i]*(double)(dims[i]-1); + else max[i]=origin[i]; // failsafe for cheating on dims + } +} +int Bounds::contains(double point[3]) { + for(int i=0;i<3;i++){ + if(min[i]>point[i]) return 0; + if(max[i] +#endif + +#include "Arch.h" +// #define DOUBLEWORD 8 // sgi doubleword == -align64 at a minimum +#define DOUBLEWORD 1 // kludge for space efficiency (should allow setting of blocksize +// #define FLEXARRAYDEBUG +/*------------- + Template: FlexArray + Purpose: Simplifies dynamically allocated array management since it contains + array size information and manages array resizing. However, since speed-critical + operations like indexing (the [] operator) are inlined, it adds no speed + penalty for the most common speed-critical operations. + Method Summary: + constructor: The initial "size" is 0 (the size of the array that is accessible + using the indexing operator []. However, the internally allocated size is + a minimum of 8 elements. + [] : Indexing operator. Acts just like [] would for a generic array. Since + it is inlined, there is actually no penalty in performance compared to + using a generic array. + append : Add an element to the end of the array, resizing the array if necessary. + The arrays are allocated in blocks so it doesn't need to realloc on every append. + For arrays < 1024 elements long, it doubles the array size on each realloc. When + larger than 1024 elements, it adds 1024 elements to the array on every realloc. + setSize(): Sets the internal and externally availible array sizes to the + specified size; shrinking a larger internal array if necessary. + getSize(): Return the current externally availible array size. The internal + size may be larger. +---------------*/ +template +class FlexArray { + int size,maxsize; + T *data; + // Internal reallocation procedure. + void grow(int targetSize=1); +public: + // constructor + FlexArray(int sz=0); + // copy constructor + FlexArray(FlexArray &src); + FlexArray &operator=(FlexArray &src); + // destructor + ~FlexArray(); + inline int getSize(){return size;} + int setSize(int s); + int append(T value); + int append(T *values,int nvals); +#ifdef FLEXARRAYDEBUG + T &operator[](int index){ + if(index>=size || index<0) { // range check + printf("FlexArray:: Bad index. Arraysize=%u Index=%u\n", + size,index); + index=0; + } + return (data[index]); + } +#else + inline T &operator[](int index){ return (data[index]); } +#endif + // purge? which forces array delete + inline void purge(){ + if(data) + delete[] data; +#ifdef FLEXARRAYDEBUG + else + printf("-----FlexArray.purge(): Data was already 0\n"); + printf("****Flexarray.purge() maxsize=%u size=%u data was = %lX\n", + maxsize,size,data); +#endif + data=0; + maxsize=size=0; + } + //inline operator T*() { return data; } // typecasting operator + inline T *getData() { return data; } // sometimes you need direct access to the contained array. +}; + +template +FlexArray::FlexArray(int sz):size(sz){ + /* + if(sz>DOUBLEWORD) maxsize=sz; + else maxsize=DOUBLEWORD; always allocate in doubleword chunks + data = new T[maxsize]; + */ + + maxsize=sz; // problem here is that virtually guarauntees reallocation + if(maxsize>0) data = new T[maxsize]; + else data = 0; +#ifdef FLEXARRAYDEBUG + printf("****FlexArray constructor: Init with maxsize=%u size=%u data was = %lX\n", + maxsize,size,data); +#endif +} + +template +FlexArray::~FlexArray(){ + if(maxsize>0 && data) + delete[] data; + size=maxsize=0; + data=0; +} + + +template +void FlexArray::grow(int targetSize){ +#ifdef FLEXARRAYDEBUG + printf("****FlexArray.grow(targ=%u): Init with maxsize=%u size=%u data was = %lX\n", + targetSize,maxsize,size,data); +#endif + do{ + if(!maxsize) maxsize=1; + //if(maxsize<1024) + maxsize<<=1; // double in size + //else + // maxsize+=1024; // increase by 1k element block + }while(maxsize%u\n",targetSize,maxsize); + T *newdata=new T[maxsize]; + // has to do its own copy because realloc is not always compatible with + // new/delete on all machines + if(data){ + for(int i=0;i +FlexArray::FlexArray(FlexArray &src):data(0),size(0),maxsize(0){ + setSize(src.getSize()); + //puts("\tFlexArraycopy constructor***********"); + for(int i=0;idata[i]=src->data[i]; + + // (*this)[i]=src[i]; // a full stupid copy!! +#ifdef FLEXARRAYDEBUG + printf("****FlexArray copy constructor: Init with maxsize=%u size=%u data was = %lX\n", + maxsize,size,data); +#endif +} + +template +FlexArray &FlexArray::operator=(FlexArray &src){ + if(this == &src) return *this; + setSize(src.getSize()); + //puts("\t\tFlexArraycopy operator"); + for(int i=0;i +int FlexArray::setSize(int s){ +#ifdef FLEXARRAYDEBUG + printf("****FlexArray.setSize(%u): Init with maxsize=%u size=%u data was = %lX\n", + s,maxsize,size,data); +#endif + if(s<0) s=0; // make sure size isn't negative + if(s<=maxsize){ + size=s; +#ifdef FLEXARRAYDEBUG + printf("****FlexArray.setSize(%u): Changed to maxsize=%u size=%u data was = %lX\n", + s,maxsize,size,data); +#endif + return size; // can't allow shrinkage below current size + } + // otherwise if >, then set array size to exactly requested size + maxsize=s; + T *newdata=new T[maxsize]; + if(data){ + for(int i=0;i +int FlexArray::append(T value){ + if(size>=maxsize) // failsafe check + grow(size+1); // this array only increases in size + data[size++]=value; + return size; +} + +template +int FlexArray::append(T *values,int nvals){ + if(size+nvals >= maxsize) + grow(size+nvals);//this array only increases in size + for(int i=0;i +#include +#include + +#ifdef WITH_HDF5 +#include +#endif + +#ifdef WITH_HDF4 +#include +#endif + +/* + This check should be more advanced, of course. + It currently just checks if the extension is anywhere in the + filename. This might be ok in most situation, but will fail + if the filename is e.g. /tmp/dir.h5/data.ieee ... + Should check for true file extension (I'm too lazy here). + Possibly it might be even better to read the first four bytes of + the file - if it already exists - and determine the file type based + on that. + */ + +/* +In preparation for the automatic detection and opening of the proper file +type, IEEEIO was designed so that you can sense the file type using the 1st 4 +bytes of the file (the magic number), so that you don't have to rely on the +file extensions. HDF4 and HDF5 also use this same methodology. IEEEIO's +magic number is 0x01020304. HDF4 uses the ascii representation for ctrl-n +ctrl-c ctrl-s ctrl-a (^N^C^S^A). These are stored as individual characters +and so must be read consecutively from the file so as to counteract the +effects of byte-swapping. In IEEEIO, I actually store the magic number as a +sequence of characters followed by the same magic number written as an +integer. This is how IEEEIO auto-detects the byte-order of the file (or at +least whether the file's byte order is opposite that of the machine +architecture which is reading it). + +-john +*/ +IObase* FlexIOopen(const char*filename, IObase::AccessMode mode) +{ + +#ifdef WITH_HDF5 + if (strstr(filename, ".h5") ) + return new H5IO(filename, mode); +#endif + +#ifdef WITH_HDF4 + if (strstr(filename, ".hdf") ) + return new HDFIO(filename, mode); +#endif + + return new IEEEIO(filename, mode); +} + diff --git a/src/FlexIO.hh b/src/FlexIO.hh new file mode 100644 index 0000000..233188a --- /dev/null +++ b/src/FlexIO.hh @@ -0,0 +1,27 @@ +///////////////////////////////////////////////////////////////// +// +// $Id$ +// +// $Log$ +// Revision 1.1 2000/04/28 08:51:16 werner +// Wrapper function for runtime detection of IEEEIO,HDF5,HDF4 format. +// Takes a filename and returns an IObase* object. +// For compilation, the flags -DWITH_HDF5 and -DWITH_HDF4 have to be set +// to enable HDF{4|5} functionality, otherwise just IEEEIO is available. +// These flags have to be set in the makefile, depending on wether the HDF{4|5} +// libraries are available at compilation time. +// +// Created 2000/04/28 10:28:21 werner +// Initial version +// +// +///////////////////////////////////////////////////////////////// +#ifndef __FLEXIO_HPP +#define __FLEXIO_HPP "Created 28.04.2000 10:28:21 by werner" + +#include + +IObase* FlexIOopen(const char*filename, IObase::AccessMode = IObase::Read); + + +#endif /* __FLEXIO_HPP */ diff --git a/src/GNUmakefile b/src/GNUmakefile new file mode 100644 index 0000000..b9fcc49 --- /dev/null +++ b/src/GNUmakefile @@ -0,0 +1,62 @@ +# +# FlexIO Interface to the Makefile Configuration System, as +# described and available at +# +# http://amira.zib.de/make/ +# +# $Revision: 1.1.1.1 $ +# $Date: 2000-09-13 13:49:09 $ +# $Log: not supported by cvs2svn $ +# Revision 1.4 2000/05/29 14:06:11 werner +# Using VPATH instead of PWD is much saver. +# +# Revision 1.3 2000/05/25 16:20:38 werner +# HDF4 interface enabled +# +# Revision 1.2 2000/05/17 10:45:38 werner +# GNUmakefile falls back to include the Makefile in the same directory, if +# no ../GNUmakefile.rules exists. +# +# Revision 1.1 2000/05/10 11:36:52 werner +# A GNUmakefile to enable compilation of FlexIO directly in the context of +# Amira. Please cry if this leads to problems; if so, we have to find some +# more complicated mechanism... +# +# +# + +OBJECTS = IO.$O IEEEIO.$O FlexIO.$O + +HDF4OBJECTS = HDFIO.$O +HDF5OBJECTS = H5IO.$O + +AMROBJECTS = AmrGridReader.$O AmrUcdFileReader.$O \ + AmrFileReader.$O Bounds.$O \ + AmrUcdGridHierarchy.$O AMRwriter.$O \ + Writer.$O + +SOCKOBJECTS = SockIOreader.$O SockIOwriter.$O +MPOBJECTS = MPIO.$O MPIutils.$O + +OBJS = $(OBJECTS) $(AMROBJECTS) $(HDF5OBJECTS_${HDF5}) $(HDF4OBJECTS_${HDF4}) + +HDF4OBJECTS_true=$(HDF4OBJECTS) +HDF5OBJECTS_true=$(HDF5OBJECTS) + +TARGET = FlexIO +PACKAGE = $(TARGET) + +all.dtor=remove-config visible + +RULEFILE = $(shell if [ -r $(VPATH)../GNUmakefile.rules ] ; then echo $(VPATH)../GNUmakefile.rules ; else echo Makefile ; fi) + +include $(RULEFILE) + +CXXFLAGS += $(hdf5_FLAGS) $(hdf4_FLAGS) -I$(VPATH)./ +LIBS += $(hdf5_LIB) $(hdf4_LIB) -lm + +# +# Add a variable to the makefile configuration +# +TARGET_FLAGS=-I$$(MAKE_LOCAL)/external/FlexIO -I$$(MAKE_ROOT)/external/FlexIO $(hdf5_FLAGS) $(hdf4_FLAGS) + diff --git a/src/H5IO.cc b/src/H5IO.cc new file mode 100644 index 0000000..f41471b --- /dev/null +++ b/src/H5IO.cc @@ -0,0 +1,689 @@ +#include +#include +#include +//#include +#include "H5IO.hh" +#include + +hid_t H5IO::DataType2H5(IObase::DataType nt){ + switch(nt){ + case Int8: + return H5T_NATIVE_CHAR; // means data + case Char8: // distinct from INT8.. + return H5T_NATIVE_CHAR; // means string + case Float32: + return H5T_NATIVE_FLOAT; + case Float64: + return H5T_NATIVE_DOUBLE; + case Int32: + return H5T_NATIVE_INT; + case Int64: + return H5T_NATIVE_LLONG; + case Int16: + return H5T_NATIVE_SHORT; + case uInt8: + return H5T_NATIVE_UCHAR; + case uInt16: + return H5T_NATIVE_USHORT; + case uInt32: + return H5T_NATIVE_UINT; + case uInt64: + return H5T_NATIVE_ULLONG; + case Char16: // unicode character type + return H5T_NATIVE_USHORT; + } + printf("H5IO::H52DataType(): Don't recognize type %d\n",(int)nt); + return -1; +} + +IObase::DataType H5IO::H5DataType2DataType(hid_t nt){ + H5T_class_t typeclass; + size_t typesize; + + typeclass = H5Tget_class(nt); + typesize = H5Tget_size(nt); + + switch(typeclass){ + case H5T_INTEGER: + printf("Int %d bytes\n",typesize); + switch(typesize){ + case 1: + return Int8; + case 2: + return Int16; + case 4: + return Int32; + case 8: + return Int64; + default: + printf("Cannot convert type for integer with %d bytes\n", + typesize); + break; + } + break; + case H5T_FLOAT: + // printf("Float %d bytes\n",typesize); + switch(typesize){ + case 4: + return Float32; + case 8: + return Float64; + default: + printf("Cannot convert type for floating point with %d bytes\n", + typesize); + } + break; + case H5T_TIME: + puts("Cannot convert type Time"); + break; + case H5T_STRING: + //puts("String"); + switch(typesize){ + case 1: + return Char8; + case 2: + return Char16; + default: + printf("Cannot convert type for string element with %d bytes\n", + typesize); + break; + } + break; + case H5T_BITFIELD: + puts("Cannot convert type Bitfield"); + break; + case H5T_OPAQUE: + puts("Cannot convert type Opaque"); + break; + case H5T_COMPOUND: + default: + puts("Cannot convert type Unknown"); + break; + } + puts("Type conversion failed"); + return Error; +} +#if 0 +IObase::DataType H5IO::H52DataType(hid_t &nt){ + switch(nt){ + case H5T_NATIVE_CHAR: + return Int8; + case H5T_NATIVE_CHAR: + return Char8; + case H5T_NATIVE_FLOAT: + return Float32; + case H5T_NATIVE_DOUBLE: + return Float64; + case H5T_NATIVE_INT: + return Int32; + case H5T_NATIVE_LONGLONG: + return Int64; + case H5T_NATIVE_SHORT: + return Int16; + case H5T_NATIVE_UCHAR: + return uInt8; + case H5T_NATIVE_USHORT: + return uInt16; + case H5T_NATIVE_UINT: + return uInt32; + case H5T_NATIVE_ULONGLONG: + return uInt64; + // no translation to Char16 from HDF5 right now (unclear what to do) + } + fprintf(stderr,"H5IO::H52DataType(): Don't recognize type %d\n",(int)nt); + return Error; +} +#endif +int H5IO::createdataspace(int rank,CONST int *dims){ + if(dataspacevalid && rankf==rank){ + // lets compare dims + int val=1; + for(int i=0;i=nitems) index=nitems-1; + if(index<0) index=0; + // must iterate to select or for now just + char dataname[128]; + //char dataname2[128]; + sprintf(dataname,"H5IO-Dataset%u",index); // was a KLUDGE! + //getdatasetname(index,dataname2); + //printf("Datasetname for dataset[%u]=[%s] [%s]\n",index,dataname,dataname2); + enddataset(); // close current dataset + dataset = H5Dopen(file,dataname); // open a dataset + if(!dataset) puts("error no dataset"); + datasetvalid=1; // we have a new dataset + // if(!datasetvalid) return -1; + enddataspace(); + dataspace = H5Dget_space(dataset); + if(!dataspace) puts("error no dataspace"); + enddatatype(); + datatype = H5Dget_type(dataset); + enddataspace(); + rankf = H5Sget_simple_extent_ndims(dataspace); + H5Sget_simple_extent_dims(dataspace,dimsf,NULL); + //printf("\tdimsf is now %lu:%lu:%lu\n",dimsf[0],dimsf[1],dimsf[2]); + datasetvalid=dataspacevalid=datatypevalid=1; // all valid now + return index; +} + +herr_t H5IOcounter(hid_t group_id, + const char *member_name, + void *operator_data){ + int *count = (int*)operator_data; + (*count)++; + return 0; +} + +struct H5IO_getname_t { + int index,count; + char *name; +}; +herr_t H5IOgetname(hid_t group_id, + const char *member_name, + void *operator_data){ + H5IO_getname_t *getn = (H5IO_getname_t*)operator_data; + if(getn->index==getn->count){ + strcpy(getn->name,member_name); + return 1; // success + } + getn->count++; + return 0; +} + +int H5IO::getndatasets(){ + int count=0; + int idx=0; + while(H5Giterate(file, /* hid_t loc_id, */ + "/", /*const char *name, */ + &idx, /* int *idx, */ + H5IOcounter, + &count)<0){} + //if(nitems!=count){ + //printf("getndatasets: nitems{%d}!=count{%d}\n", + // nitems,count); + //} + nitems = count; // just for internal bookkeeping + return count; +} + +void H5IO::getdatasetname(int _index, // in + char *name){ // out + H5IO_getname_t getn; + int idx=_index; + getn.index=_index; getn.name=name; getn.count=_index; + while(H5Giterate(file, /* hid_t loc_id, */ + "/", /*const char *name, */ + &idx, /* int *idx, */ + H5IOgetname, + &getn)<0){} +} + +void H5IO::enddataspace(){ + if(!dataspacevalid) return; + dataspacevalid=0; + for(int i=0;i=0) H5Fclose(file); + filevalid=0; +} + +int H5IO::isValid() { return filevalid; } + +int H5IO::write(IObase::DataType typeID,int rank,CONST int *dims,void *data){ + hasread=0; + //printf("++Write index=%u\n",index); + createdataset(typeID,rank,dims); + status = H5Dwrite(dataset, DataType2H5(typeID), H5S_ALL, H5S_ALL, + H5P_DEFAULT, data); + enddataset(); // commit it now + return status; +} + +//int H5IO::write(char *name, IObase::DataType typeID,int rank,CONST int *dims,void *data){ +// hasread=0; +// createdataset(name,typeID,rank,dims); +// return status = H5Dwrite(dataset, DataType2H5(typeID), H5S_ALL, H5S_ALL, +// H5P_DEFAULT, data); +//} + +int H5IO::readInfo(char *name,IObase::DataType &typeID,int &rank,int *dims,int maxdims){ + + // name shouls be attribute "long_name"); + if(hasread){ + //printf("hasread=1, so get next dataset index %u\n",index+1); + hasread=0; + selectdataset(index+1); + } + else { + //printf("hasread=0, so select current index for dataset %u\n",index); + selectdataset((int)index); + } + getdatasetinfo(rank,dims,typeID); + //sprintf(name,"H5IO-Dataset%u",index); + getdatasetname(index,name); + hasread=1; + return 1; +} + +int H5IO::readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims){ + // name is an attribute "long_name"); + if(hasread){ + hasread=0; + selectdataset(index+1); + } + else { + selectdataset((int)index); + } + getdatasetinfo(rank,dims,typeID); + hasread=1; + return 1; +} + +int H5IO::read(void *data){ + selectdataset(index); // make certain its selected + // we will be getting all of the dataset + //SDgetinfo(sid,name,&rank,dims,&nt,&natt); + // set up memspace + hid_t memspace = H5Screate_simple(rankf,dimsf,NULL); + //printf("rankf=%u dimsf=%u:%u:%u\n",(int)rankf, + // (int)dimsf[0],(int)dimsf[1],(int)dimsf[2]); + // printf("Data = %u\n",data); + // if(!memspace) puts("no memspace"); + //if(!dataset) puts("no dataset"); + status = H5Dread(dataset,DataType2H5(H5DataType2DataType(datatype)), + memspace,dataspace,H5P_DEFAULT,data); + // printf("H5Dread status = %d\n",status); + hasread=1; + return status; +} + +int H5IO::seek(int i) { selectdataset((int)i); hasread=0; return index; } + +int H5IO::nDatasets(){ // not completely correct due to coordvar's + // must scan for coordvar's and eliminate them from the count. + // int32 ndatasets,nattribs; + //SDfileinfo(fid,&ndatasets,&nattribs); + // return (int)ndatasets; //? + return getndatasets(); +} + +int H5IO::writeAnnotation(CONST char *annotation){ +#if 0 + select((int)index); // select if not already selected + int32 ref=SDidtoref(sid); + return (int)DFANputlabel(filename,DFTAG_NDG,ref,(char*)annotation); +#endif +} + +int H5IO::readAnnotationInfo(int number,int &length){ +#if 0 + select(index); + int32 ref=SDidtoref(sid); + length=(int)DFANgetlablen(filename,DFTAG_NDG,ref); + return length; +#endif + return 1; +} + +int H5IO::readAnnotation(int number,char *annotation,int maxlen){ +#if 0 + // number=0; // How do I get the number of annotations availible? + // use get lablist to get list of tags + number=0; // number is ALWAYS 0 for hdf files + select(index); + int32 ref=SDidtoref(sid); + return (int)DFANgetlabel(filename,DFTAG_NDG,ref,annotation,maxlen); +#endif + return 1; +} + + +int H5IO::nAnnotations(){ +#if 0 + select(index); + int32 ref=SDidtoref(sid); + if(DFANgetlablen(filename,DFTAG_NDG,ref)<=0) return 0; // no labels found + return 1; // always 1 annotation per object limit for H5 is appears +#endif + return 1; +} + +int H5IO::writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data){ + //printf("writeAttrib index=%u\n",index); + selectdataset(index); // make sure it is selected + //printf("\tindex=%u\n",index); + // create a datashape + hsize_t dimsa[2]={0,0}; + dimsa[0]=length; + hid_t shape = H5Screate_simple(1, dimsa, NULL); + hid_t attrib = H5Acreate(dataset,name,DataType2H5(typeID),shape,H5P_DEFAULT); + H5Awrite(attrib, DataType2H5(typeID), data); + H5Aclose(attrib); + H5Sclose(shape); + return 1; +} + +int H5IO::readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen){ + selectdataset(index); // make sure current dataset is selected + hid_t attrib = H5Aopen_idx(dataset,number); + hid_t atype = H5Aget_type(attrib); + hid_t ashape = H5Aget_space(attrib); + H5Aget_name(attrib,maxnamelen,name); + hsize_t ranka = H5Sget_simple_extent_ndims(ashape); + // rank should always be 1; + hsize_t dimsa[5]; + H5Sget_simple_extent_dims(ashape,dimsa,NULL); + typeID = H5DataType2DataType(atype); + nelem = dimsa[0]; // single-dimensional array for attributes + + H5Tclose(atype); + H5Sclose(ashape); + H5Aclose(attrib); + return 1; +} + +struct H5IOatt_name2index_t { + char *name; + int count; +}; +herr_t H5IOattr_name2index(hid_t group_id, + const char *member_name, + void *operator_data){ + H5IOatt_name2index_t *s=(H5IOatt_name2index_t*)operator_data; + s->count++; + if(!strcmp(member_name,s->name)) + return s->count; + else{ + return 0; + } +} + +herr_t H5IOattr_count(hid_t group_id, + const char *member_name, + void *operator_data){ + // cycle through all attribs as a dummy counter + int *count = (int *)operator_data; + (*count)++; + return 0; +} + +int H5IO::readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem){ + selectdataset(index); // make sure current dataset is selected + H5IOatt_name2index_t stype; + stype.name=(char*)name; + stype.count=0; + unsigned idx=0; + int aindex = H5Aiterate(dataset,&idx,H5IOattr_name2index,&stype); + if(aindex<=0) return -1; + aindex--; // index is one more than the actual index of the item + hid_t attrib = H5Aopen_name(dataset,name); + hid_t atype = H5Aget_type(attrib); + hid_t ashape = H5Aget_space(attrib); + hsize_t ranka = H5Sget_simple_extent_ndims(ashape); + // rank should always be 1; + hsize_t dimsa[5]; + H5Sget_simple_extent_dims(ashape,dimsa,NULL); + typeID = H5DataType2DataType(atype); + nelem = dimsa[0]; // single-dimensional array for attributes + + H5Tclose(atype); + H5Sclose(ashape); + H5Aclose(attrib); + return aindex; +} + +int H5IO::readAttribute(int number,void *data){ + // now must openIDX again + selectdataset(index); // just to be sure we've got data + hid_t attrib = H5Aopen_idx(dataset,number); + hid_t atype = H5Aget_type(attrib); + H5Aread(attrib,DataType2H5(H5DataType2DataType(atype)),data); + H5Tclose(atype); + H5Aclose(attrib); + return 1; +} + +int H5IO::nAttributes(){ + selectdataset(index); + unsigned idx=0; + int count=0; + int aindex = H5Aiterate(dataset,&idx,H5IOattr_count,&count); + return count; +} +//================Chunking Interface----------------------- +int H5IO::reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){ +#if 0 + hasread=0; + for(int i=0;iisValid()) + return (Long8)fid; + else + delete fid; // file open failed + return 0; +} + +Long8 f_h5_openr (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new H5IO(file,IObase::Read)); +} + +Long8 f_h5_openw (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new H5IO(file,IObase::Create)); +} + +Long8 f_h5_opena (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new H5IO(file,IObase::Append)); +} + +IOFile H5IOopen (char *file,char *accessname){ + // Parse all of the ansi stdio access option strings + IObase::AccessMode mode; + if(!strcmp(accessname,"read") || + !strcmp(accessname,"r") || + !strcmp(accessname,"rb")) + mode=IObase::Read; + else if(*accessname=='a') + mode=IObase::Append; + else if(!strcmp(accessname,"write") || + !strcmp(accessname,"create") || + !strcmp(accessname,"wb")) + mode = IObase::Write; + else if(!strcmp(accessname,"w+") || + !strcmp(accessname,"w+b") || + !strcmp(accessname,"wb+")) + mode=IObase::Append; + else{ + fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n", + accessname,file); + return 0; + } + IObase *fid=new H5IO(file,mode); + if(fid->isValid()) + return (IOFile)fid; + else + delete fid; // file open failed + return 0; // unknown option +} + +IOFile H5IOopenRead (char *file){ + return (IOFile)(new H5IO(file,IObase::Read)); +} + +IOFile H5IOopenWrite (char *file){ + return (IOFile)(new H5IO(file,IObase::Write)); +} + +IOFile H5IOopenAppend (char *file){ + return (IOFile)(new H5IO(file,IObase::Append)); +} diff --git a/src/H5IO.h b/src/H5IO.h new file mode 100644 index 0000000..28637c9 --- /dev/null +++ b/src/H5IO.h @@ -0,0 +1,12 @@ +#ifndef __H5IO_H_ +#define __H5IO_H_ + +#include "IOProtos.h" +#include "Arch.h" + +IOFile H5IOopen PROTO((char *filename,char *accessname)); +IOFile H5IOopenRead PROTO((char *filename)); +IOFile H5IOopenWrite PROTO((char *filename)); +IOFile H5IOopenAppend PROTO((char *filename)); + +#endif diff --git a/src/H5IO.hh b/src/H5IO.hh new file mode 100644 index 0000000..97ded33 --- /dev/null +++ b/src/H5IO.hh @@ -0,0 +1,130 @@ +#ifndef __H5IO_HH_ +#define __H5IO_HH_ +#include "Arch.h" +#include "IO.hh" + +/* +H5stream for networking & message passing! +This is not the same as HDF5 because you cannot ask for a subset of the +data that arrives. You can only ask what is in the pipe and recieve it or +dump it. This is only for marshalling and unmarshalling datastructures +into a network pipe for transport in a platform independent manner (ie. +use the HDF5 data translation mechanisms) + +Should have pluggable transport layer! +Just provide a VFT with read/write/connect/terminate + perhaps block/nonblock/and poll for connections too? + If we can make do with blocking that should be sufficient + Also need an exception handling mechanism in the embeded/pluggable + transport. + +Transport policies should also be pluggable. They would be +* periodic (timer-based) +* synchronous/rendezvous (MPI or Occam-like) +* transport on write (active message push) +* transport on read (on-demand-based active message request w/ round-trip) +* virtual shared memory background async transport (implicit sync on read or sync on write, or explicit sync or no-sync) + +Query Policy +* Blocking +* nonblocking + +Buffer Policy +* WriteBufferSize +* ReadBufferSize + + */ +#include + +class H5IO : public IObase { + // *** Flags for usage of each type + char filevalid,datasetvalid,datatypevalid,dataspacevalid; + IObase::DataType currentdatatype; + hid_t file, dataset; /* file and dataset handles */ + hid_t datatype, dataspace; /* handles */ + hsize_t dimsf[5],rankf; /* current dataset dimensions */ + herr_t status; + + hid_t DataType2H5(IObase::DataType nt); // in-memory type is *always* native + // IObase::DataType H52DataType(hid_t &nt); + IObase::DataType H5DataType2DataType(hid_t nt); + int createdataspace(int rank,CONST int *dims); + int createdatatype(IObase::DataType dt); + int selectdataset(int i); + // void selectdataset(char *name); + int createdataset(char *name,IObase::DataType nt, + int rank,CONST int *dims); + int createdataset(IObase::DataType nt,int rank,CONST int *dims); + int getdatasetinfo(int &rank, int *dims, + IObase::DataType &nt); + void enddataspace(); + void enddatatype(); + void enddataset(); + int getndatasets(); + void getdatasetname(int _index, // in + char *name); + + + int chunkdims[5]; + int hasread; +public: + H5IO(CONST char *fname,AccessMode access); + virtual ~H5IO(); + virtual int isValid(); + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data); + // virtual int write(char *name,IObase::DataType typeID,int rank,CONST int *dims,void *data); + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int readInfo(char *name,IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int read(void *data); + virtual int seek(int i); + virtual int nDatasets(); + virtual int writeAnnotation(CONST char *annotation); + virtual int readAnnotationInfo(int number,int &length); // NEW + virtual int readAnnotation(int index,char *annotation,int maxlen); // changed + virtual int nAnnotations(); // New + + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data); // New + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128); // New + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem); // New + virtual int readAttribute(int number,void *data); // New + // virtual Long readAttribute(CONST char *name,void *data); + virtual int nAttributes(); // New + + //-----------------Chunking Utilities.................. + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + //-----------------Streaming interface (for PANDA, Sockets & MPIO)......... + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims) {return -1; } + virtual int writeStream(void *data,int length){ return -1; } // not implemented yet + virtual int readStream(void *data,int length) { return -1; } // not implemented yet + //----------------Special HDF5-specific methods......... + // will put some hyperslab definition stuff here +}; + +#define f_h5_open F77NAME(h5_open_,h5_open,H5_OPEN) +#define f_h5_openr F77NAME(h5_openr_,h5_openr,H5_OPENR) +#define f_h5_openw F77NAME(h5_openw_,h5_openw,H5_OPENW) +#define f_h5_opena F77NAME(h5_opena_,h5_opena,H5_OPENA) + +extern "C" { +#ifdef CRAY // Note: This isn't really implemented yet... +#include + Long8 f_h5_open(_fcd fcfilename,_fcd accessname); + Long8 f_h5_openr(_fcd fcfilename); + Long8 f_h5_openw(_fcd fcfilename); + Long8 f_h5_opena(_fcd fcfilename); +#else + Long8 f_h5_open(char *file,char *access,int flen,int alen); + Long8 f_h5_openr(char *file,int flen); + Long8 f_h5_openw(char *file,int flen); + Long8 f_h5_opena(char *file,int flen); +#endif +#include "H5IO.h" +} +/* + long io_open_ieee_(constCONST char *file,constCONST char *access,int flen,int alen); +*/ + +#endif + diff --git a/src/H5IOwriter.cc b/src/H5IOwriter.cc new file mode 100644 index 0000000..2b133fe --- /dev/null +++ b/src/H5IOwriter.cc @@ -0,0 +1,84 @@ +/* + * This example writes data to the HDF5 file. + * Data conversion is performed during write operation. + */ +#include +#include + +#define FILE "SDS.h5" +#define DATASETNAME "IntArray" +#define NX 5 /* dataset dimensions */ +#define NY 6 +#define RANK 2 +/* +Perhaps support a filtration/pattern matching architecture which +recognizes particular patterns of values in the file and offers those +patterns as a new typename in the architecture or even a particular +callback. So for instance you could have a group of "dataset" with +"edgecoords" is a rectilinear dataset. Otherwise we'll need to +match groupnames? Could have a "type" attribute which disambiguates +this because each object must have a unique text name. + */ + +main (void) +{ + // int data[NX][NY]; /* data to write */ + int *data = new int[NX*NY]; + int i, j; + int idx,rval; + int dims[3]; + int rank=RANK; + + /* + * Data and output buffer initialization. + */ + for (j = 0; j < NX; j++) { + for (i = 0; i < NY; i++) + data[j*NY + i] = i + j; + } + /* + * 0 1 2 3 4 5 + * 1 2 3 4 5 6 + * 2 3 4 5 6 7 + * 3 4 5 6 7 8 + * 4 5 6 7 8 9 + */ + + /* + * Create a new file using H5F_ACC_TRUNC access, + * default file creation properties, and default file + * access properties. + */ + H5IO *file = new H5IO(FILE,IObase::Write); + /* + * Describe the size of the array and create the data space for fixed + * size dataset. + */ + dims[0] = NX; + dims[1] = NY; + float attr[3]={1.0,2.0,3.0}; + file->write(IObase::Int32,2,dims,data); + file->writeAttribute("floatattr",IObase::Float32,3,attr); + file->write(IObase::Int32,2,dims,data); + delete file; + + puts("**********************Now read the file*******************"); + /* typedef herr_t *(H5G_operator_t)(hid_t group_id, + const char *member_name, + void *operator_data // in,out); */ + file = new H5IO(FILE,IObase::Read); + int nds = file->nDatasets(); + printf("number of datasets = %u\n",nds); + for(int i=0;ireadInfo(name,datatype,rank,dims); + printf("name = [%s] rank=%u dims=%u,%u\n",name,rank,dims[0],dims[1]); + if(datatype==IObase::Int32) puts("\tcorrect type Int32\n"); + else puts("\ttype failed"); + printf("\tnattribs=%u\n",file->nAttributes()); + } + delete file; + return 0; +} diff --git a/src/H5writer.c b/src/H5writer.c new file mode 100644 index 0000000..2f133f7 --- /dev/null +++ b/src/H5writer.c @@ -0,0 +1,175 @@ +/* + * This example writes data to the HDF5 file. + * Data conversion is performed during write operation. + */ +// #include +#include +#define WRITE_H5 +#define FILE "SDS.h5" +#define DATASETNAME "IntArray" +#define NX 5 /* dataset dimensions */ +#define NY 6 +#define RANK 2 +/* +Perhaps support a filtration/pattern matching architecture which +recognizes particular patterns of values in the file and offers those +patterns as a new typename in the architecture or even a particular +callback. So for instance you could have a group of "dataset" with +"edgecoords" is a rectilinear dataset. Otherwise we'll need to +match groupnames? Could have a "type" attribute which disambiguates +this because each object must have a unique text name. + */ + +herr_t GroupOp(hid_t group_id, + const char *member_name, + void *operator_data){ + hid_t dataset,space,datatype; + hsize_t rank, dims[5]; + H5T_class_t typeclass; + size_t typesize; + int i; + + printf("GroupOp: member_name = %s id %u\n",member_name,group_id); + /* get info on a particular member */ + dataset = H5Dopen(group_id,member_name); + space = H5Dget_space(dataset); + datatype = H5Dget_type(dataset); + rank = H5Sget_simple_extent_ndims(space); + H5Sget_simple_extent_dims(space,dims,NULL); + printf("\tndims=%d Dims ",rank); + for(i=0;i +#include +#include +//#include +#include "HDFIO.hh" +#include + +int32 HDFIO::DataType2HDF(IObase::DataType nt){ + switch(nt){ + case Int8: + return DFNT_INT8; // means data + case Char8: // distinct from INT8.. + return DFNT_CHAR8; // means string + case Float32: + return DFNT_FLOAT32; + case Float64: + return DFNT_FLOAT64; + case Int32: + return DFNT_INT32; + case Int64: + return DFNT_INT64; + case Int16: + return DFNT_INT16; + case uInt8: + return DFNT_UINT8; + case uInt16: + return DFNT_UINT16; + case uInt32: + return DFNT_UINT32; + case uInt64: + return DFNT_UINT64; + case Char16: // unicode character type + return DFNT_CHAR16; + } + printf("HDFIO::HDF2DataType(): Don't recognize type %d\n",(int)nt); + return -1; +} + +IObase::DataType HDFIO::HDF2DataType(int32 nt){ + switch(nt){ + case DFNT_INT8: + return Int8; + case DFNT_CHAR8: + return Char8; + case DFNT_FLOAT32: + return Float32; + case DFNT_FLOAT64: + return Float64; + case DFNT_INT32: + return Int32; + case DFNT_INT64: + return Int64; + case DFNT_INT16: + return Int16; + case DFNT_UINT8: + case DFNT_UCHAR8: + return uInt8; + case DFNT_UINT16: + return uInt16; + case DFNT_UINT32: + return uInt32; + case DFNT_UINT64: + return uInt64; + case DFNT_CHAR16: + return Char16; + } + printf("HDFIO::HDF2DataType(): Don't recognize type %d\n",(int)nt); + return Error; +} + +void HDFIO::create(int rank,CONST int *dims,IObase::DataType nt){ + int32 hdims[5]; + if(sid>=0) SDendaccess(sid); + nitems++; + index=nitems-1; + for(int i=0;i=0) + return; + if(index>=nitems) index=nitems-1; + if(index<0) index=0; + if(sid>=0) SDendaccess(sid); + sid=SDselect(fid,i); + index=i; +} +void HDFIO::endaccess(){ + if(sid<0) return; + SDendaccess(sid); + sid=-1; +} + +HDFIO::HDFIO(CONST char *fname,AccessMode access):IObase(fname,access),sid(-1),fid(-1),hasread(0){ + switch(accessmode){ + case Read: + fid=SDstart(filename,DFACC_RDONLY); + break; + case Write: + fid=SDstart(filename,DFACC_CREATE); + break; + case Append: + fid=SDstart(filename,DFACC_RDWR); + break; + default: + puts("HDFIO: constructor... invalid accessmode"); + break; + } +} + +HDFIO::~HDFIO(){ + // printf("Destroying HDF file fid=%u, sid=%u\n",fid,sid); + endaccess(); + if(fid>=0) SDend(fid); + // SDend(fid); +} + +int HDFIO::isValid() { if(fid>=0) return 1; else return 0; } + +int HDFIO::write(IObase::DataType typeID,int rank,CONST int *dims,void *data){ + int32 origin[5]={0,0,0,0,0}; + int32 stride[5]={1,1,1,1,1}; // kludge... we'll fix later + int32 hdims[5]={0,0,0,0,0}; + hasread=0; + for(int i=0;i0) + return readAttributeInfo(number,fakename,typeID,nelem); + else return -1; +} + +int HDFIO::readAttribute(int number,void *data){ + select(index); + return (int)SDreadattr(sid,number,data); +} + +int HDFIO::nAttributes(){ + int32 nt,nattr,rank,dims[5]; + char name[128]; + select(index); + SDgetinfo(sid,name,&rank,dims,&nt,&nattr); + return (int)nattr; +} +//================Chunking Interface----------------------- +int HDFIO::reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){ + //int32 origin[5]={0,0,0,0,0}; + //int32 stride[5]={1,1,1,1,1}; // kludge... we'll fix later + //int32 hdims[5]={0,0,0,0,0}; + hasread=0; + for(int i=0;iisValid()) + return (Long8)fid; + else + delete fid; // file open failed + return 0; +} + +Long8 f_hdf_openr (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new HDFIO(file,IObase::Read)); +} + +Long8 f_hdf_openw (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new HDFIO(file,IObase::Create)); +} + +Long8 f_hdf_opena (char *file,int flen){ + file[flen]='\0'; // null terminate + return (Long8)(new HDFIO(file,IObase::Append)); +} + +IOFile HDFIOopen (char *file,char *accessname){ + // Parse all of the ansi stdio access option strings + IObase::AccessMode mode; + if(!strcmp(accessname,"read") || + !strcmp(accessname,"r") || + !strcmp(accessname,"rb")) + mode=IObase::Read; + else if(*accessname=='a') + mode=IObase::Append; + else if(!strcmp(accessname,"write") || + !strcmp(accessname,"create") || + !strcmp(accessname,"wb")) + mode = IObase::Write; + else if(!strcmp(accessname,"w+") || + !strcmp(accessname,"w+b") || + !strcmp(accessname,"wb+")) + mode=IObase::Append; + else{ + fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n", + accessname,file); + return 0; + } + IObase *fid=new HDFIO(file,mode); + if(fid->isValid()) + return (IOFile)fid; + else + delete fid; // file open failed + return 0; // unknown option +} + +IOFile HDFIOopenRead (char *file){ + return (IOFile)(new HDFIO(file,IObase::Read)); +} + +IOFile HDFIOopenWrite (char *file){ + return (IOFile)(new HDFIO(file,IObase::Write)); +} + +IOFile HDFIOopenAppend (char *file){ + return (IOFile)(new HDFIO(file,IObase::Append)); +} + diff --git a/src/HDFIO.h b/src/HDFIO.h new file mode 100644 index 0000000..a3f8f89 --- /dev/null +++ b/src/HDFIO.h @@ -0,0 +1,12 @@ +#ifndef __HDFIO_H_ +#define __HDFIO_H_ + +#include "IOProtos.h" +#include "Arch.h" + +IOFile HDFIOopen PROTO((char *filename,char *accessname)); +IOFile HDFIOopenRead PROTO((char *filename)); +IOFile HDFIOopenWrite PROTO((char *filename)); +IOFile HDFIOopenAppend PROTO((char *filename)); + +#endif diff --git a/src/HDFIO.hh b/src/HDFIO.hh new file mode 100644 index 0000000..5041030 --- /dev/null +++ b/src/HDFIO.hh @@ -0,0 +1,79 @@ +#ifndef __HDFIO_HH_ +#define __HDFIO_HH_ +#include "Arch.h" +#include "IO.hh" +#include + +class HDFIO : public IObase { + int32 fid,sid,current_rank; + int32 DataType2HDF(IObase::DataType nt); + IObase::DataType HDF2DataType(int32 nt); + int chunkdims[5]; + int hasread; + void create(int rank,CONST int *dims,DataType nt); + void select(int i); + void endaccess(); +public: + HDFIO(CONST char *fname,AccessMode access); + virtual ~HDFIO(); + virtual int isValid(); + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data); + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int readInfo(char *name,IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int read(void *data); + virtual int seek(int i); + virtual int nDatasets(); + virtual int writeAnnotation(CONST char *annotation); + virtual int readAnnotationInfo(int number,int &length); // NEW + virtual int readAnnotation(int index,char *annotation,int maxlen); // changed + virtual int nAnnotations(); // New + + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data); // New + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128); // New + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem); // New + virtual int readAttribute(int number,void *data); // New + // virtual Long readAttribute(CONST char *name,void *data); + virtual int nAttributes(); // New + + //-----------------Chunking Utilities.................. + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + //-----------------Streaming interface (for PANDA, Sockets & MPIO)......... + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims) {return -1; } + virtual int writeStream(void *data,int length){ return -1; } // not implemented yet + virtual int readStream(void *data,int length) { return -1; } // not implemented yet + //----------------Special HDF-specific methods......... + int isCoord(); // Tells whether the dataset is a coordinate or a dataset + int readDimInfo(int dimnumber,char *name, IObase::DataType &datatype, int &length); + int readDim(int dimnumber, void *dim); + int writeDim(int dimnumber,IObase::DataType datatype,int length,void *dim); + int writeDimName(int dimnumber,CONST char *name); +}; + +#define f_hdf_open F77NAME(hdf_open_,hdf_open,HDF_OPEN) +#define f_hdf_openr F77NAME(hdf_openr_,hdf_openr,HDF_OPENR) +#define f_hdf_openw F77NAME(hdf_openw_,hdf_openw,HDF_OPENW) +#define f_hdf_opena F77NAME(hdf_opena_,hdf_opena,HDF_OPENA) + +extern "C" { +#ifdef CRAY // Note: This isn't really implemented yet... +#include + Long8 f_hdf_open(_fcd fcfilename,_fcd accessname); + Long8 f_hdf_openr(_fcd fcfilename); + Long8 f_hdf_openw(_fcd fcfilename); + Long8 f_hdf_opena(_fcd fcfilename); +#else + Long8 f_hdf_open(char *file,char *access,int flen,int alen); + Long8 f_hdf_openr(char *file,int flen); + Long8 f_hdf_openw(char *file,int flen); + Long8 f_hdf_opena(char *file,int flen); +#endif +#include "HDFIO.h" +} +/* + long io_open_ieee_(constCONST char *file,constCONST char *access,int flen,int alen); +*/ + +#endif + diff --git a/src/IEEEIO.cc b/src/IEEEIO.cc new file mode 100644 index 0000000..c2f653b --- /dev/null +++ b/src/IEEEIO.cc @@ -0,0 +1,1443 @@ +#include +#include +#include +#include "IEEEIO.hh" + +#ifdef WIN32 +// Are we Microsoft VC++ 5.0 or 6.0? +#if defined(_MSC_VER) && ( (_MSC_VER == 1100) || (_MSC_VER == 1200) ) // yes we are +#include +#ifdef O_RDONLY +#undef O_RDONLY +#endif +#define O_RDONLY _O_RDONLY|_O_BINARY +#ifdef O_RDWR +#undef O_RDWR +#endif +#define O_RDWR _O_RDWR|_O_BINARY +#ifdef O_WRONLY +#undef O_WRONLY +#endif +#define O_WRONLY _O_WRONLY|_O_BINARY +#ifdef O_CREAT +#undef O_CREAT +#endif +#define O_CREAT _O_CREAT|_O_BINARY +#ifdef O_TRUNC +#undef O_TRUNC +#endif +#define O_TRUNC _O_TRUNC|_O_BINARY +#ifdef O_APPEND +#undef O_APPEND +#endif +#define O_APPEND _O_APPEND|_O_BINARY +#else // not an MSC compiler (use the old defines) +#define O_RDONLY _O_RDONLY +#define O_RDWR _O_RDWR +#define O_WRONLY _O_WRONLY +#define O_CREAT _O_CREAT +#define O_TRUNC _O_TRUNC +#define O_APPEND _O_APPEND +#endif // not an MSC compiler +#endif // WIN32 + +#ifdef FFIO +#include +static struct ffsw ffopens_status; +//#define open(x,y,z) ffopens(x,y,z, 0, 0, &ffopens_status, "bufa.bufsize=256.num_buffers=4") +#define LAYERS "" +#ifdef T3E +#define open(x,y,z) ffopens(x,y,S_IWRITE|S_IREAD,0,100,&ffopens_status,LAYERS); +#else // its probably an SGI +#define open(x,y,z) ffopens(x,y,S_IWRITE|S_IREAD,0,0,&ffopens_status,LAYERS); +#endif +#define close(x) ffclose(x) +#endif + +#ifdef T3E +int IEEEIO::ffioIsTrue(){ +#ifdef FFIO + return 1; +#else + return 0; +#endif +} +#endif + + +// int IEEEIO::nextRecord() (stores state in current_record) +// also garauntees integrity of datasetnumber and +// the current_rec and current_dat + +IEEEIO::AttribRef::AttribRef(IEEEIO::AttribRef &src){ + //puts("AttribRef::copy constructor"); + rec=src.rec; + offset=src.offset; + strcpy(name,src.name); +} + +IEEEIO::AttribRef::AttribRef(){ + //puts("empty attribref constructor"); +} +/* +IEEEIO::AttribRef::~AttribRef(){ + //puts("delete an attrib ref"); +} +IEEEIO::RecRef::~RecRef(){ + //puts("delete a recref"); +} +*/ + +IEEEIO::AttribRef &IEEEIO::AttribRef::operator=(IEEEIO::AttribRef &src){ + if(this != &src) { + //puts("\tAttribRef::copy operator"); + rec=src.rec; + offset=src.offset; + //name=src.name; // uses the flexarray copy constructor + strcpy(name,src.name); + } + return *this; +} + +IEEEIO::DataRef::DataRef():end_offset(0){ + //puts("Empty DataRef Constructor!!"); +} + + +IEEEIO::DataRef::DataRef(IEEEIO::DataRef &src){ + //puts("DataRef:: copy constructor"); + rec=src.rec; + offset=src.offset; + end_offset=src.end_offset; + annotations = src.annotations; + attributes = src.attributes; + //puts("DataRef:: copy constructor DONE"); +} +/* +IEEEIO::DataRef::~DataRef(){ + // puts("dataref destructor"); +}*/ + +IEEEIO::DataRef &IEEEIO::DataRef::operator=(IEEEIO::DataRef &src){ + if(this != &src){ + rec=src.rec; + offset=src.offset; + end_offset=src.end_offset; + annotations = src.annotations; + attributes = src.attributes; + } + return *this; +} + +void IEEEIO::initPosition(){ + // init +#ifdef FFIO + actual_position = ::ffseek(fid,0,L_INCR); +#else + actual_position = ::lseek(fid,0,L_INCR); +#endif + virtual_position = actual_position + writebuffercount; + // get actual filesize + +#ifdef FFIO + file_length = ::ffseek(fid,0,L_XTND); + ::ffseek(fid,actual_position,L_SET); // seek back to original pos +#else +#ifdef SGI + file_length = ::lseek64(fid,0,L_XTND); + ::lseek64(fid,actual_position,L_SET); // seek back to original pos +#else + file_length = ::lseek(fid,0,L_XTND); + ::lseek(fid,actual_position,L_SET); // seek back to original pos +#endif +#endif + if(virtual_position > file_length) + file_length = virtual_position; + // printf("Init position: a=%ld v=%ld f=%ld\n", + // actual_position,virtual_position,file_length); +} + + +//long IEEEIO::getPosition(int immediate) { +//#ifdef FFIO +// if(!writebuffer || immediate) +// return ::ffseek(fid,0,L_INCR); +// else +// return ::ffseek(fid,0,L_INCR)+writebuffercount; +//#else +// if(!writebuffer || immediate) +// return ::lseek(fid,0,L_INCR); +// else +// return ::lseek(fid,0,L_INCR)+writebuffercount; +//#endif +//} + +void IEEEIO::restart(){ + // this->initPosition(); + //puts("restart seek"); + IEEEIO::lseek(FileHdrSize,L_SET); // T3E Kludge + //puts("restart"); + current_rec_offset=current_dat_offset=FileHdrSize; // T3E Kludge + current_rec.recordsize=0; + current_dat.datasize=0; + current_dat.rank=0; + datasetnumber=0; // initial + hasread=0; // and it hasn't been read yet... +} + +int IEEEIO::nextRecord(){ + RecordHdr rec; + // should have it check the datasetnumber before seeking + // this will require consistancy checks for the datasetnumber + // elsewhere in the code + Long8 src=current_rec_offset; + Long8 dst=src+current_rec.recordsize; + current_rec_offset=IEEEIO::lseek(dst,L_SET); // seek from start + // or use rec.read(rec,fid) + // or IEEEIO::RecordHdr::read(rec,fid) + if(RecordHdr::read(this,rec) <= 0) + return 0; + current_rec_offset=dst+RecordHdrSize; + current_rec=rec; + return 1; +} + +int IEEEIO::nextDataRecord(){ + hasread=0; // reset the hasread field + if(current_rec.recordtype==DataRecord && + datasetnumber!=current_rec.sequenceID){ + IEEEIO::lseek(current_rec_offset,L_SET); // seek to record start + } + else { + do { // scan through records for the next DataRecord + if(!nextRecord()) + return 0; // reached end of file + } while(current_rec.recordtype!=DataRecord); + } + // dat_offset is same as current_rec_offset for the data record + // so nextRecord() can be used for scanning for annotations + current_dat_offset=current_rec_offset; + DataRecordHdr::read(this,current_dat); + datasetnumber=current_rec.sequenceID; + return 1; +} + +//long IEEEIO::getLength(int immediate){ +//#ifdef FFIO +// long currentpos=::ffseek(fid,0,L_INCR); // find currentposition +// long auspos = ::ffseek(fid,0,L_XTND); // seek to end to find length +//#else +// long currentpos=::lseek(fid,0,L_INCR); // find currentposition +// long auspos = ::lseek(fid,0,L_XTND); // seek to end to find length +//#endif +// if(writebuffer && writebuffercount && !immediate){ +// // must compute real end of file +// register long pos1=currentpos+writebuffercount; +// if(pos1>auspos) auspos=pos1; +// } +//#ifdef FFIO +// ::ffseek(fid,currentpos,L_SET); // seek back to original position +//#else +// ::lseek(fid,currentpos,L_SET); // seek back to original position +//#endif +// return auspos; // return end position +//} + +void IEEEIO::byteswapBuffer(void *buf,Long8 nelements,int elementsize){ + char *buffer=(char *)buf; // treat as a character buffer + if(elementsize<=1) return; + for(Long8 i=0;iflush(); + //puts("WriteHeader"); + for(char c=0;c<4;c++) // make sure magic is correct + file_header.magic.c[c]=c+1; + if(swapbytes) + file_header.byteorder.i=IEEE_REVERSE_MAGIC; + else + file_header.byteorder.i=IEEE_NATIVE_MAGIC; + file_header.majorversion = IEEE_MAJORVERSION; + file_header.minorversion = IEEE_MINORVERSION; + IEEEIO::lseek(0,L_SET); // will force a flush (if needed) + //puts("done writeheader seek"); + if(swapbytes) file_header.byteswap(); + // T3E Kludge + int sz=FileHdr::write(this,file_header); + if(swapbytes) file_header.byteswap(); + // if(pos>=FileHdrSize) // T3E Kludge + // IEEEIO::lseek(pos,L_SET); + return sz; +} + +// reads the start of the file (including the magic number) +// and determines if this is +// 1) A valid IEEEIO file +// 2) what the byte order is +// 3) How many datasets are contained +int IEEEIO::readFileHeader(){ + Long8 pos=getPosition(); // use virtual_position + IEEEIO::lseek(0,L_SET); + // T3E Kludge + // int sz=FileHdr::read(this,file_header); + FileHdr::read(this,file_header); + IEEEIO::lseek(pos,L_SET); // return to original position + for(char c=0;c<4;c++){ + if((c+1)!=file_header.magic.c[c]){ + file_header.ndatasets=0; + // fprintf(stderr,"IEEEIO: File %s has the wrong magic number\n",filename); + return -1; // bad magic + } + } + // now compare byte order + if(file_header.byteorder.i==IEEE_NATIVE_MAGIC) + swapbytes=0; + else{ + swapbytes=1; + //puts("byteswapping is On !!!!!!!!!!!!!!!"); + } + if(swapbytes) file_header.byteswap(); + ndatasets=file_header.ndatasets; + return 1; +} + +void IEEEIO::rebuildFileHeader(){ + int lndatasets; + Long8 pos=getPosition(); // save file position (use virtual position + restart(); + // steal seek loop from the nextDataRecord() + for(lndatasets=0; + nextDataRecord()>0; + lndatasets++){ + // now check the length of the record + // for each record. + } + file_header.ndatasets=lndatasets; + writeFileHeader(); + IEEEIO::lseek(pos,L_SET); +} + +void IEEEIO::appendRecordTable(){ + //printf("appending records==================\n"); + while(nextRecord()>0){ + //printf("appending record\n"); + switch(current_rec.recordtype){ + case DataRecord: + //fprintf(stderr,"DataRecord"); + (rec_table[current_rec.sequenceID]).rec=current_rec; + // use virtual_position + (rec_table[current_rec.sequenceID]).offset=getPosition()-RecordHdrSize; + break; + case AnnotationRecord:{ + //fprintf(stderr,"\tAnnotationRecord\n"); + RecRef ref; + ref.rec=current_rec; + ref.offset=getPosition()- RecordHdrSize; // T3E Kludge + (rec_table[current_rec.sequenceID]).annotations.append(ref); + } + break; + case AttributeRecord:{ + //fprintf(stderr,"\tAttributeRecord\n"); + AttribRef ref,*refp; + AttributeRecordHdr attribhdr; + ref.rec=current_rec; + ref.offset=getPosition()- RecordHdrSize; // T3E Kludge + (rec_table[current_rec.sequenceID]).attributes.append(ref); + int idx=(rec_table[current_rec.sequenceID]).attributes.getSize()-1; + refp = &((rec_table[current_rec.sequenceID]).attributes[idx]); + AttributeRecordHdr::read(this,attribhdr); + IEEEIO::read(refp->name,attribhdr.namesize); + } + break; + default: + fprintf(stderr,"\tIEEEIO::Error UNKNOWN RECORD TYPE [%d]... recovering.", + (int)(current_rec.recordtype)); + return; + } + (rec_table[current_rec.sequenceID]).end_offset = + current_rec_offset + current_rec.recordsize; + } +} + +void IEEEIO::buildRecordTable(){ + if(file_header.ndatasets<0) + return; // failure + restart(); + rec_table.setSize(file_header.ndatasets); + appendRecordTable(); +} + +void IEEEIO::openFile(CONST char *fname,IObase::AccessMode access,int swbytes){ + switch(access){ + case IObase::Read: + fid=open(fname,O_RDONLY,0644); + if(fid<0){ + fprintf(stderr,"IEEEIO: Failed to open %s for reading\n",fname); + return; + } + initPosition(); + if(readFileHeader()<=0){ + close(fid); + // fprintf(stderr,"IEEEIO: File %s is empty (opened for reading)\n",fname); + fid=-1; // invalid file + return; + } + if(file_header.ndatasets<0){ + // must recover from crash + close(fid); + fid=open(fname,O_RDWR,0644); + rebuildFileHeader(); + close(fid); + fid=open(fname,O_RDONLY,0644); + readFileHeader(); // reread.. + } + buildRecordTable(); + restart(); // go to start of file + ndatasets = file_header.ndatasets; + nextRecord(); // prime the recordnumber + break; + case IObase::Write: // truncates + fid=open(fname,O_WRONLY|O_CREAT|O_TRUNC,0644); + if(fid<0){ + fprintf(stderr,"IEEEIO: Failed to create %s for writing\n",fname); + return; + } + initPosition(); + file_header.ndatasets=-1; + ndatasets=0; + writeFileHeader(); + restart(); + break; + case IObase::Append: + default: + fid=open(fname,O_RDWR,0644); // PW: We *don't* want O_APPEND here. + // O_Append moves the file ptr to end + // of file before a write; this means + // when we do the writeHeader() below + // this is stuck at the end of this file + // which makes it puke. + if(fid<0){ + fprintf(stderr,"IEEEIO: Failed to open %s for append\n",fname); + return; + } + initPosition(); + if(readFileHeader()<=0){ + close(fid); + fprintf(stderr,"IEEEIO: File %s is empty (opened for append)\n",fname); + fid=-1; // invalid file + return; + } + if(file_header.ndatasets<0){ + // must recover from crash + close(fid); + fid=open(fname,O_RDWR,0644); + initPosition(); + rebuildFileHeader(); + close(fid); + fid=open(fname,O_RDWR,0644); // PW: We want to open RDWR again + initPosition(); + readFileHeader(); // reread.. + } + buildRecordTable(); + restart(); // go to start of file + ndatasets = file_header.ndatasets; + // now we sync up in the way we would for a write + file_header.ndatasets=-1; + writeFileHeader(); // write header with -1 to indicate we are writing + // could refcount by increasing the - of numbers in header + // (needs extra flag for synced) + restart(); + nextRecord(); // prime the recordnumber + //seek(ndatasets); + break; + } +} + +IEEEIO::IEEEIO(IEEEIO *file): // read only dup + IObase(file->filename,IObase::Read),fid(dup(file->fid)), + datasetnumber(0),ndatasets(file->ndatasets), + swapbytes(file->swapbytes),hasread(0), + writebuffersize(0),writebuffercount(0),writebuffer(0), + savedposition(-1),virtual_position(-1),actual_position(-1), + file_length(-1) +{ + if(file->masterfile) masterfile=file->masterfile; + else masterfile=file; + initPosition(); // initial positional pointers + ndatasets = file_header.ndatasets = file->ndatasets; + buildRecordTable(); + restart(); // go to start of file + nextRecord(); // prime the recordnumber +} + + +IEEEIO::IEEEIO(CONST char *fname, ExtendedAccessMode access,int swbytes): + IObase(fname,mode(access)),fid(-1),datasetnumber(0), + ndatasets(0),swapbytes(swbytes),hasread(0),masterfile(0), + writebuffersize(0),writebuffercount(0),writebuffer(0), + savedposition(-1),virtual_position(-1),actual_position(-1), + file_length(-1) +{ + if(access==IEEEIO::SharedRead){ + masterfile=this; // we are multi-reading + fid=open(fname,O_RDONLY,0644); + if(fid<0){ + fprintf(stderr,"IEEEIO: Failed to open %s for reading\n",fname); + return; + } + this->initPosition(); + if(readFileHeader()<=0){ + close(fid); + fprintf(stderr,"IEEEIO: File %s is empty (opened for reading)\n",fname); + fid=-1; // invalid file + return; + } + buildRecordTable(); + restart(); // go to start of file + ndatasets = file_header.ndatasets; + nextRecord(); // prime the recordnumber + } + else + openFile(fname,mode(access),swbytes); +} + +IEEEIO::IEEEIO(CONST char *fname,IObase::AccessMode access,int swbytes): + IObase(fname,access),fid(-1),datasetnumber(0), + ndatasets(0),swapbytes(swbytes),hasread(0),masterfile(0), + writebuffersize(0),writebuffercount(0),writebuffer(0), + savedposition(-1) +{ + // Long8 fpos; + openFile(fname,access,swbytes); +} + +IEEEIO::~IEEEIO(){ + if(fid<0 && savedposition>=0) resume(); + // resume IO only if it is paused so that + // we can do the final writes to the file before + // closing + //puts("do bufferoff"); + if(writebuffer) bufferOff(); // automatically flushes buffer + //puts("now rewrite header"); + if(fid>=0){ + if(accessmode!=IObase::Read){ + file_header.ndatasets=ndatasets; + writeFileHeader(); + } + close(fid); + } + fid=-1; +} + +int IEEEIO::isValid(){ + if(fid>=0) return 1; + else return 0; +} + +int IEEEIO::write(IObase::DataType typeID,int rank,CONST int *dims,void *data){ + int i; + RecordHdr rec; + DataRecordHdr hdr; + // make sure its the EOF + if(accessmode==IObase::Read) return 0; + hasread=0; // reset hasread; (JMS: changed from local Thu Mar 12 13:53:13 CST 1998) + if(rec_table.getSize()>0){ + Long8 endpos = rec_table[rec_table.getSize()-1].end_offset; + IEEEIO::lseek(endpos,L_SET); // don't know if this is costly + } + else + IEEEIO::lseek(0,L_XTND); // seek to end of file + // if 0-length seeks are costly, then alternative + // logic can be constructed to ensure writes to end of file + for(i=0,hdr.datasize=1;i=rec_table.getSize()) return 0; // end of file + // read the record + header + hasread=1; // we've read this, so next time we hit it, we'll increment again + IEEEIO::lseek(rec_table[datasetnumber].offset,L_SET); + // T3E Kludge + RecordHdr::read(this,current_rec); + DataRecordHdr::read(this,current_dat); + rank=current_dat.rank; + if(chunkdims.getSize()maxdims)?maxdims:rank,sizeof(Int)); + + for(int i=0;i=rec_table.getSize()) return 0; // seek past end. + Long8 datapos=rec_table[datasetnumber].offset+RecordHdrSize+DataRecordHdrSize+ + sizeof(Int)*current_dat.rank; + // should make certain current file position is correct + // if(getPosition() != datapos) (redundant call to lseek()) + IEEEIO::lseek(datapos,L_SET); // seek to position + int sz=IEEEIO::read(data,current_dat.datasize); // read nbytes + int typelen = sizeOf(Int2DataType(current_dat.numbertype));// compute elem sz + if(swapbytes) byteswapBuffer(data,current_dat.datasize/typelen,typelen); + return sz; +} + +int IEEEIO::seek(int idx){ + if(accessmode!=IObase::Read && + accessmode!=IObase::Append) // can't seek unless readable + return -1; // failed to seek + if (idx >= ndatasets || idx < 0) { + return -1; // do a bounds check (probably should just clip) + } + // bound the index + if((1+idx)>rec_table.getSize()) idx=rec_table.getSize(); + if(idx<0) idx=0; + index = idx; + IEEEIO::lseek(rec_table[index].offset,L_SET); + // T3E Kludge + RecordHdr::read(this,current_rec); + current_rec_offset=getPosition(); + datasetnumber=current_rec.sequenceID; // Changed: had -1 + hasread=0; // new file position + return current_rec.sequenceID; +} + +int IEEEIO::nDatasets() { + // can work across threads or across processes since + // it gathers information directly from the file. + // it does not need to share info with masterfile + // in fact you can delete the masterfile + if(masterfile){ // we are passive read-only. update nDatasets + // seek-scan to find datasets? + int oldlength = (rec_table.getSize())?(rec_table[rec_table.getSize()-1].end_offset):0; + //printf("oldlength=%u newlength=%u\n",oldlength,(unsigned int)(getLength())); + if(getLength()>oldlength){ + // lets scan to find the end + int lndatasets; + puts("We should clearly not be here!!!"); + restart(); // go to beginning + // steal seek loop from the nextDataRecord() + for(lndatasets=0; + nextDataRecord()>0; + lndatasets++){ + //printf("scan dataset[%u]\n",lndatasets); + } + file_header.ndatasets = lndatasets; + rec_table.setSize(lndatasets); + // printf("counted %u datasets. old was %u datasets\n",lndatasets,ndatasets); + seek(ndatasets); // seek to current last + ndatasets = lndatasets; // then reset the last + appendRecordTable(); // append new stuff to record table + } + } + return ndatasets; +} + +int IEEEIO::writeAnnotation(CONST char *annotation){ + int stringlen; + RecRef aref; + RecordHdr rec; + if(accessmode==IObase::Read || !annotation) return 0; + stringlen=strlen(annotation)+1; + + if(rec_table.getSize()>0){ + Long8 endpos = rec_table[rec_table.getSize()-1].end_offset; + IEEEIO::lseek(endpos,L_SET); // don't know if this is costly + } + else + IEEEIO::lseek(0,L_XTND); // seek to end of file + + rec.recordtype=AnnotationRecord; + rec.recordsize=stringlen; + if(datasetnumber>=0) rec.sequenceID=datasetnumber; + else rec.sequenceID=current_rec.sequenceID; // a kludge for error immunity + current_rec = rec; + // T3E Kludge + current_rec_offset = getPosition() + RecordHdrSize; + // T3E Kludge + RecordHdr::write(this,rec); + // if(swapbytes) byteswap(rec); + int sz=IEEEIO::write(annotation,stringlen); + + aref.rec=current_rec; + // T3E Kludge + aref.offset=current_rec_offset-RecordHdrSize; + if(accessmode!=IObase::Write){ // don't write to index cache if in write-only mode + rec_table[datasetnumber].annotations.append(aref); + rec_table[datasetnumber].end_offset=getPosition(); + } + return sz; +} +/* + If objects could have all attributes implicitly availible for querying + when passed to subroutines. Basic object methods for data movement like + linearize() or object.linearized[index] object.linearized.size. + Then for objects that a receiver can't deal with either + 1: have compiletime "gatekeepers" that restrict allowable types + that it can receive + 2: Do a treesearch through object space to find a convertor sequence + that can convert the current type into the one that the object + accepts. If no such object can be found, indicate runtime + object adaptor failure. +*/ +int IEEEIO::readAnnotationInfo(int number,int &length){ + if(datasetnumber<0 || + number>=rec_table[datasetnumber].annotations.getSize()){ + length=0; + return -1; + } + length=rec_table[datasetnumber].annotations[number].rec.recordsize; + return length; +} + +int IEEEIO::readAnnotation(int number,char *annotation,int maxsize){ + // returns actual size of annotation or -1 if error + if(datasetnumber<0 || accessmode==IObase::Write || + number>=rec_table[datasetnumber].annotations.getSize()){ + return -1; + } + IEEEIO::lseek(rec_table[datasetnumber].annotations[number].offset,L_SET); + // T3E Kludge + RecordHdr::read(this,current_rec); + IEEEIO::read(annotation,(maxsize0){ + Long8 endpos = rec_table[rec_table.getSize()-1].end_offset; + IEEEIO::lseek(endpos,L_SET); // don't know if this is costly + } + else + IEEEIO::lseek(0,L_XTND); // seek to end of file + attrib.datasize=length*sizeOf(typeID); + attrib.namesize=stringlen; + attrib.numbertype=typeID; + rec.recordtype=AttributeRecord; + rec.recordsize=attrib.datasize+attrib.namesize+AttributeRecordHdrSize; + if(datasetnumber>=0) rec.sequenceID=datasetnumber; + else rec.sequenceID=current_rec.sequenceID; // a kludge for error immunity + current_rec=rec; + current_rec_offset=getPosition() + RecordHdrSize; + aref.rec=current_rec; + aref.offset=current_rec_offset-RecordHdrSize; + // no copy constructor for aref, so must do manually + if(accessmode != IObase::Write){ + int lastindex; + rec_table[datasetnumber].attributes.append(aref); + lastindex=rec_table[datasetnumber].attributes.getSize()-1; + strcpy(rec_table[datasetnumber].attributes[lastindex].name,name); + } + // T3E Kludge + RecordHdr::write(this,rec); + AttributeRecordHdr::write(this,attrib); + //printf("\tnow write the string\n"); + IEEEIO::write(name,stringlen); + //printf("\tdone IEEEIO::stringlen=%u typeid=%u\n",attrib.namesize,attrib.numbertype); + // data is not byte-reversed... + int sz=0; + if(swapbytes) byteswapBuffer(data,length,sizeOf(typeID)); + IEEEIO::write(data,length*sizeOf(typeID)); + if(swapbytes) byteswapBuffer(data,length,sizeOf(typeID)); // swap back + if(accessmode != IObase::Write) + rec_table[datasetnumber].end_offset=getPosition(); + // doesn't appear to store attributes properly + return sz; +} + +int IEEEIO::readAttributeInfo(int number,char *name,IObase::DataType &typeID, + Long &nelem,int maxnamelen){ + if(accessmode==IObase::Write) return -1; + FlexArray *attribs= &(rec_table[datasetnumber].attributes); + if(number>=(*attribs).getSize()) return -1; // > number of attributes + AttribRef *attrib=&((*attribs)[number]); + if(strlen(attrib->name)>(size_t)maxnamelen){ + strncpy(name,attrib->name,maxnamelen); // don't we want to copy the other way? + name[maxnamelen-1]='\0'; + } + else strcpy(name,attrib->name); + name[maxnamelen-1]='\0'; // make certain it is null capped + AttributeRecordHdr attribhdr; + IEEEIO::lseek((*attribs)[number].offset,L_SET); + RecordHdr::read(this,current_rec); + AttributeRecordHdr::read(this,attribhdr); +//printf("IEEEIO:attribrechdr = ds,nt,ns %d,%d,%d\n", +// attribhdr.datasize, +// attribhdr.numbertype, +// attribhdr.namesize); + typeID = Int2DataType(attribhdr.numbertype); + nelem = attribhdr.datasize/sizeOf(typeID); + return -1; +} + +int IEEEIO::readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem){ + // by name + if(accessmode==IObase::Write) return -1; + FlexArray *attribs= &(rec_table[datasetnumber].attributes); + for(int i=0;igetSize();i++){ + if(!strcmp(name,(*attribs)[i].name)){ + // must read the record to get this info + AttributeRecordHdr attribhdr; + IEEEIO::lseek((*attribs)[i].offset,L_SET); + RecordHdr::read(this,current_rec); + AttributeRecordHdr::read(this,attribhdr); + typeID = Int2DataType(attribhdr.numbertype); + nelem = attribhdr.datasize/sizeOf(typeID); + return i; + } + } + return -1; // Attribute not found +} + +int IEEEIO::readAttribute(int number,void *data){ + if(accessmode==IObase::Write) return -1; + FlexArray *attribs= &(rec_table[datasetnumber].attributes); + if(number>=(*attribs).getSize()) return -1; // > number of attributes + AttributeRecordHdr attribhdr; + IEEEIO::lseek((*attribs)[number].offset,L_SET); + RecordHdr::read(this,current_rec); + AttributeRecordHdr::read(this,attribhdr); + IObase::DataType typeID = Int2DataType(attribhdr.numbertype); + if(typeID==IObase::Error) return -1; // read failed due to bad datatype + // Long8 nelem = attribhdr.datasize/sizeOf(typeID); + IEEEIO::lseek(attribhdr.namesize,L_INCR); + int sz=IEEEIO::read(data,attribhdr.datasize)/sizeOf(typeID); + if(swapbytes) byteswapBuffer(data,sz,sizeOf(typeID)); + if(typeID==IObase::String){ + char *cdata=(char *)data; + cdata[sz]='\0'; /* Null Terminate String data */ + } + return sz; // returns number of elements read +} + +int IEEEIO::nAttributes(){ + if(datasetnumber<0 || accessmode == IObase::Write) return -1; + return rec_table[datasetnumber].attributes.getSize(); +} + +//================Chunking Interface----------------------- +void IEEEIO::clearChunk(int nbytes){ +#ifdef T3E +#define DISKBLOCKSIZE 128*1024 +#else +#define DISKBLOCKSIZE 8192 +#endif +// This is a wasteful feature that will be eliminated in later releases +// This is currently done because I needed the disk space to be zero'ed +// prior to writing for debugging purposes... Could have a writeStream +// class. + int nwritten; + char dummy[DISKBLOCKSIZE]; + for(int i=0;iDISKBLOCKSIZE){ + nwritten=IEEEIO::write(dummy,DISKBLOCKSIZE); + if(nwritten<=0) return; // this aint working + nbytes-=nwritten; + } + if(nbytes>0) IEEEIO::write(dummy,nbytes); // write the remaining bytes +#undef DISKBLOCKSIZE +} + +int IEEEIO::reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){ + reserveStream(typeID,rank,dims); // sets up the chunking state machine + // clearing does not appear to be needed... just need header + //clearChunk(IObase::nBytes(typeID,rank,dims)); // this pre-clears the reserved area to 0. (inefficient) + return 1; +} + +// Chunking should probably include striding.... +// But thats a pain since you'll need to read + write to +// Accomplish that (yuck!). Lots of seeking. +// Lets leave striding out for now. + +// should also check for contiguous data (eg. slicing) and optimize for that layout +// for now, the streaming interface best serves contiguous data. +int IEEEIO::writeChunk(CONST int *dims,CONST int *origin,void *data){ + int i,sz=-1; + // make sure its the EOF + if(accessmode==IObase::Read) { + fprintf(stderr,"IEEEIO::writeChunk(): Error! Access is ReadOnly\n"); + return 0; + } + // should have a "chunk reserved" flag set. + if(current_reserved_chunk!=datasetnumber){ + fprintf(stderr,"IEEEIO::writeChunk(): Error! You forgot to reserve space for the chunk using IO::reserveChunk()\n"); + return 0; + } + + // now we need to seek to the position of the data + int rank = current_dat.rank; + IObase::DataType typeID = IObase::Int2DataType(current_dat.numbertype); + int typesize=sizeOf(typeID); + // Long8 basefileoffset = rec_table[datasetnumber].offset+ + Long8 basefileoffset = stream_offset + + RecordHdrSize+DataRecordHdrSize+sizeof(Int)*current_dat.rank; // T3E Kludge + Long8 chunkcolumnsize=dims[0]*typesize; // stride between columns in chunk + Long8 filecolumnsize=chunkdims[0]*typesize; // stride between columns on disk (full array size) + Long8 originoffset; + Long8 accumdims; + for(originoffset=0,accumdims=typesize,i=0;ichunkdims[i]){ + fprintf(stderr,"IEEEIO::writeChunk(): ERROR!! specified dims and origin exceed reserved block size\n"); + fprintf(stderr,"\tfor dimension %u origin=%u and dims=%u\n",i,origin[i], + dims[i]); + fprintf(stderr,"\torigin+dims=%u whereas the maximum must be less than %u\n",origin[i]+dims[i],chunkdims[i]); + } + } + originoffset+=basefileoffset; // for absolute seeking + Long8 maxindex,minindex; + minindex=basefileoffset; + maxindex=basefileoffset+current_dat.datasize; + int ncolumns; // computed in loop below + for(ncolumns=1,i=1;imaxindex){ + fprintf(stderr,"WriteChunk() inconsistency. Writing greater than maximum index\n"); + fprintf(stderr,"\tCol[%u]: Requested %u, but maxindex= %u\n", + i,(unsigned int)originoffset,(unsigned int)maxindex); + } + if((originoffset+chunkcolumnsize)>maxindex){ + fprintf(stderr,"WriteChunk() inconsistency. This write will overrun the reserved data\n"); + fprintf(stderr,"\tCol[%u]: Requested %u, maxindex %u, and the write of %u will run to %u\n", + i,(unsigned int)originoffset,(unsigned int)maxindex,(unsigned int)chunkcolumnsize,(unsigned int)(originoffset+chunkcolumnsize)); + } + IEEEIO::lseek(originoffset,L_SET); + sz=IEEEIO::write(((char*)data)+i*chunkcolumnsize,(int)chunkcolumnsize); + originoffset+=filecolumnsize; + for(Long8 j=1,idx=dims[1],planesize=filecolumnsize; + j<(rank-1) && !((i+1)%idx); + idx*=dims[++j]){ + Long8 extraoffset=planesize*(chunkdims.getData()[j]-dims[j]); + originoffset+=extraoffset; + planesize*=dims[j]; + } + } + // now swap the data back to native order... + if(swapbytes) + byteswapBuffer(data,IObase::nElements(rank,dims),typesize); + + return sz; +} +int IEEEIO::readChunk(CONST int *dims,CONST int *origin,void *data){ + int sz=-1,i; + if(accessmode!=IObase::Read && accessmode!=IObase::Append) + return 0; + // gonna have to stride through this sucker... (yuck) + // use the same chunkdims for this. Must set during readinfo... + // now we need to seek to the position of the data + int rank = current_dat.rank; + IObase::DataType typeID = IObase::Int2DataType(current_dat.numbertype); + int typesize=sizeOf(typeID); + Long8 basefileoffset = rec_table[datasetnumber].offset+ + // sizeof(RecordHdr)+sizeof(DataRecordHdr)+sizeof(Int)*current_dat.rank; + RecordHdrSize+DataRecordHdrSize+sizeof(Int)*current_dat.rank; // T3E Kludge + Long8 chunkcolumnsize=dims[0]*typesize; // stride between columns in chunk + Long8 filecolumnsize=chunkdims[0]*typesize; // stride between columns on disk (full array size) + Long8 originoffset; + Long8 accumdims; + // compute the offset into the data on disk required by the chunk origin (initial offset) + for(originoffset=0,accumdims=typesize,i=0;i0){ + Long8 endpos = rec_table[rec_table.getSize()-1].end_offset; + IEEEIO::lseek(endpos,L_SET); // don't know if this is costly + } + else { + IEEEIO::lseek(0,L_XTND); // seek to end of file + } + // if 0-length seeks are costly, then alternative + // logic can be constructed to ensure writes to end of file + if(chunkdims.getSize() != rank) + chunkdims.setSize(rank); // KLUDGE! + for(i=0,hdr.datasize=1;i0){ + fprintf(stderr,"IEEEIO::bufferOff() ERROR!!!!"); + fprintf(stderr,"\tFile %s is either paused or invalid, so I can't deallocate the write buffer safely\n",filename); + return; + } + //printf("bufferoff on a=%ld v=%ld f=%ld b=%d\n", + // actual_position,virtual_position,file_length,writebuffercount); + this->flush(); +#ifdef SGI // block-aligned write buffer + free(writebuffer); +#else + delete writebuffer; +#endif + writebuffer=0; +} + +int IEEEIO::pause(){ + if(fid<0) return 0; // fail + this->flush(); // flush the buffer to pause + savedposition=getPosition(); + close(fid); + fid=-1; + return 1; // success +} + +int IEEEIO::resume(){ + if(fid>=0 || savedposition<0) return 0; // fail + switch(IObase::accessmode){ + case IObase::Read: + fid=open(filename,O_RDONLY,0644); + break; + case IObase::Write: + fid=open(filename,O_WRONLY,0644); + break; + case IObase::Append: + fid=open(filename,O_RDWR,0644); + break; + } + if(fid<0){ + printf("IEEEIO::resume failed for file %s\n",filename); + return -1; + } + ::lseek(fid,savedposition,L_SET); // this is OK.. + savedposition=-1; + return 1; // success +} + +//=================== Experimental MPIO methods ================= +void IEEEIO::getFilename(char *fn,int maxlen){ + strncpy(fn,filename,maxlen-1); +} + +int IEEEIO::reserveStream(IObase::DataType typeID,int rank,CONST int *dims,Long8 &soffset){ + int rv=this->reserveStream(typeID,rank,dims); + soffset = stream_offset + RecordHdrSize+DataRecordHdrSize+sizeof(Int)* + current_dat.rank; + return rv; +} + +// writes to explicit offset in file! +// always overrides the current filepointer position! +// only useful for the master process *if* it +// must write to a non-zero location +// *** So the usage scenario is that the master +// has the IEEEIO file handle and getFilename() is +// used to pass the name of the file to the slave procs +// which open it O_WRITE. The master gets the offset +// for a particular stream from the special version +// of the method reserverStream and uses that to position +// their respective file pointers. All slaves and +// the master then write to the file simultaneously to +// different file offsets. It remains to be seen how +// well this works without O_DIRECT. We can use timing +// loops to stagger the writes somewhat though. +int IEEEIO::writeStream(void *data,int length,Long8 soffset){ + IEEEIO::lseek(soffset,L_SET); + streaming=1; + return writeStream(data,length); +} + +/*********************Fortran Interface**********************/ +Long8 f_ieee_open (char *file,char *accessname,int flen,int alen){ + // would have used tolower(), but it doesn't exist everywhere.... :( + IObase::AccessMode mode; + if(*accessname=='R' || *accessname=='r') + mode=IObase::Read; + else if(*accessname=='W' || *accessname=='w' || + *accessname=='C' || *accessname=='c') + mode=IObase::Write; + else if(*accessname=='A' || *accessname=='a') + mode=IObase::Append; + else { + fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n", + accessname,file); + return 0; + } + IObase *fid=new IEEEIO(file,mode); + if(fid->isValid()) + return (Long8)fid; + else + delete fid; // file open failed + return 0; +} + +Long8 f_ieee_openr(char *filename,int namelen){ + filename[namelen]='\0'; + return (Long8)(new IEEEIO(filename,IObase::Read)); +} + +Long8 f_ieee_openw(char *filename,int namelen){ + filename[namelen]='\0'; + return (Long8)(new IEEEIO(filename,IObase::Write)); +} + +Long8 f_ieee_opena(char *filename,int namelen){ + filename[namelen]='\0'; + return (Long8)(new IEEEIO(filename,IObase::Append)); +} + +void ieee_bufon(Long8 *fileID,int bufsize){ + IEEEIO *f=(IEEEIO*)(*fileID); + if(bufsize<0) f->bufferOn(); // use default size + else f->bufferOn(bufsize); // or specify +} + +void ieee_bufoff(Long8 *fileID){ + IEEEIO *f=(IEEEIO*)(*fileID); + f->bufferOff(); +} + +IOFile IEEEopen(char *filename,char *accessname){ + // Parse all of the ansi stdio access option strings + IObase::AccessMode mode; + if(!strcmp(accessname,"read") || + !strcmp(accessname,"r") || + !strcmp(accessname,"rb")) + mode=IObase::Read; + else if(*accessname=='a') + mode=IObase::Append; + else if(!strcmp(accessname,"write") || + !strcmp(accessname,"create") || + !strcmp(accessname,"w") || + !strcmp(accessname,"wb") || + !strcmp(accessname,"w+") || + !strcmp(accessname,"w+b") || + !strcmp(accessname,"wb+")) + mode=IObase::Write; + else{ + fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n", + accessname,filename); + return 0; + } + IObase *fid=new IEEEIO(filename,mode); + if(fid->isValid()) + return (IOFile)fid; + else + delete fid; // file open failed + return 0; // unknown option +} + +IOFile IEEEopenRead(char *filename){ + return (IOFile)(new IEEEIO(filename,IObase::Read)); +} + +IOFile IEEEopenWrite(char *filename){ + return (IOFile)(new IEEEIO(filename,IObase::Create)); +} + +IOFile IEEEopenAppend(char *filename){ + return (IOFile)(new IEEEIO(filename,IObase::Append)); +} + +void IEEEbufferOn(IOFile fileID,int bufsize){ + IEEEIO *f=(IEEEIO*)fileID; + if(bufsize<0) f->bufferOn(); // use default size + else f->bufferOn(bufsize); // or specify +} + +void IEEEbufferOff(IOFile fileID){ + IEEEIO *f=(IEEEIO*)fileID; + f->bufferOff(); +} + diff --git a/src/IEEEIO.h b/src/IEEEIO.h new file mode 100644 index 0000000..8b57ac2 --- /dev/null +++ b/src/IEEEIO.h @@ -0,0 +1,13 @@ +#ifndef __IEEEIO_H_ +#define __IEEEIO_H_ + +#include "IOProtos.h" +#include "Arch.h" + +IOFile IEEEopen PROTO((char *filename,char *accessname)); +IOFile IEEEopenRead PROTO((char *filename)); +IOFile IEEEopenWrite PROTO((char *filename)); +IOFile IEEEopenAppend PROTO((char *filename)); +void IEEEbufferOn PROTO((IOFile fileID,int bufsize)); +void IEEEbufferOff PROTO((IOFile fileID)); +#endif diff --git a/src/IEEEIO.hh b/src/IEEEIO.hh new file mode 100644 index 0000000..1b81dbb --- /dev/null +++ b/src/IEEEIO.hh @@ -0,0 +1,709 @@ +#ifndef __IEEEIO_HH_ +#define __IEEEIO_HH_ +#ifndef WIN32 +#include +#include +#include +#else +#include +#endif + +#include "IEEEIOWinDllApi.h" + +#include "IO.hh" +#include "FlexArrayTmpl.H" +#include "Arch.h" +#include +#include +#include +#include +#if defined(WIN32) || defined(SOLARIS) +// I'm a WIN32 box and I ignore standards +// or I'm a Sun box and I hate BSD. +#define bcopy(src,dest,len) memcpy(dest,src,len) +#else +#include // available non-ANSI/Posix compliant +#endif + +#ifdef FFIO +#include +#endif + +// Win32/Solaris lseek crap... +#if defined(WIN32) || defined(SOLARIS) || defined (HITACHI) || defined(sun) +#define L_INCR SEEK_CUR +#ifndef L_SET // for that wanky Solaris compiler +#define L_SET SEEK_SET +#endif +#define L_XTND SEEK_END +#endif +// T3E lseek crap... +#ifdef T3E // I'm a T3E and I ignore ANSI/Posix standards +#define L_INCR SEEK_CUR +#define L_SET SEEK_SET +#define L_XTND SEEK_END +#endif + +#define IEEE_NATIVE_MAGIC 0x01020304 +#define IEEE_REVERSE_MAGIC 0x04030201 +#define IEEE_ALTERNATING_MAGIC 0x02010403 + +#define IEEE_BIG_ENDIAN IEEE_NATIVE_MAGIC +#define IEEE_LITTLE_ENDIAN IEEE_REVERSE_MAGIC +#define IEEE_VAX_ENDIAN IEEE_ALTERNATING_MAGIC + +#define IEEE_MAJORVERSION 1 +#define IEEE_MINORVERSION 1 + +class IEEEIO_API IEEEIO : public IObase { +public: + enum RecordType {DataRecord=1,AnnotationRecord,AttributeRecord}; + union btorder { + char c[4]; // write as Int, read as Int + Int i; + }; +#define FileHdrSize (4+4+4+2+2) // T3E Kludge + struct FileHdr { + // do magic twice so we can figure out which byte-order + // the current machine is in addition (without hardcoding) in + // addition to which byte order the file is in + btorder magic; + btorder byteorder; + Long ndatasets; + // T3E will be stupid for this, but thats OK + short majorversion; + short minorversion; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,FileHdr &rec){ + int r=0; +#ifdef T3E // data structures are not packed contiguously in memory + r+=ieeeio->write((rec.magic.c),4); + r+=ieeeio->write((rec.byteorder.c),4); + r+=ieeeio->write(&(rec.ndatasets),4); + // this may be incorrect, but it will work for now + // It assumes the low order bytes will be first to + // be written. + r+=ieeeio->write(&(rec.majorversion),2); + r+=ieeeio->write(&(rec.minorversion),2); +#else + // problem if this includes pointers to static methods + // will require an extra degree of inheritance. (inherit + // from a base structure. + r=ieeeio->write(&rec,FileHdrSize); +#endif + return r; + } + static int read(IEEEIO *ieeeio,FileHdr &rec){ + int r=0; +#ifdef T3E // data structures are not packed contiguously in memory + char buffer[FileHdrSize]; + r=ieeeio->read(buffer,FileHdrSize); // read full buffer in and then copy to struct + ::bcopy(buffer,(rec.magic.c),4); + ::bcopy(buffer+4,(rec.byteorder.c),4); + ::bcopy(buffer+8,&(rec.ndatasets),4); + // May be invalid if low order bytes are not the + // proper ones to load. (eg. may fail on big-endian systems) + ::bcopy(buffer+12,&(rec.majorversion),2); + ::bcopy(buffer+14,&(rec.minorversion),2); +#else + r=ieeeio->read(&rec,FileHdrSize); +#endif + return r; + } + static void byteswap(FileHdr &hdr){ + IEEEIO::byteswapBuffer(&(hdr.ndatasets),1,sizeof(hdr.ndatasets)); + // because the t3e doesn't have a 2-byte datatype, must do this manually + IEEEIO::byteswapBuffer(&(hdr.majorversion),1,2); + IEEEIO::byteswapBuffer(&(hdr.minorversion),1,2); + } + // May be a problem to have a nonstatic class member here because + // this will create a vtable entry. + void byteswap(){ + IEEEIO::byteswapBuffer(&ndatasets,1,sizeof(ndatasets)); + // because the t3e doesn't have a 2-byte datatype, must do this manually + IEEEIO::byteswapBuffer(&majorversion,1,2); + IEEEIO::byteswapBuffer(&minorversion,1,2); + } + }; +#define RecordHdrSize (4+4+4) // T3E Kludge + struct RecordHdr { + Int recordtype; + Long recordsize; + Int sequenceID; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,RecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[RecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.recordtype),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.recordsize),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.sequenceID),buffer+8,1,4); + r=ieeeio->write(buffer,RecordHdrSize); + } + else { +#ifdef T3E // data structures are not packed contiguously in memory + r+=ieeeio->write(&(rec.recordtype),4); + r+=ieeeio->write(&(rec.recordsize),4); + r+=ieeeio->write(&(rec.sequenceID),4); +#else + r=ieeeio->write(&rec,RecordHdrSize); + //printf("Wrote rechdr %u,%u,%u\n",rec.recordtype,rec.recordsize,rec.sequenceID); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,RecordHdr &rec){ + char buffer[RecordHdrSize]; + int r=ieeeio->read(buffer,RecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4);//3 elements of 4 bytes +#ifdef T3E // data structures are not packed contiguously in memory + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.recordtype),4); + ::bcopy(buffer+4,&(rec.recordsize),4); + ::bcopy(buffer+8,&(rec.sequenceID),4); +#else + ::bcopy(buffer,(char*)&rec,RecordHdrSize); +#endif + return r; + } + }; + +#define DataRecordHdrSize (4+4+4) // T3E Kludge + struct DataRecordHdr { + Long datasize; + Int numbertype; + Int rank; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,DataRecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[DataRecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.rank),buffer+8,1,4); + r=ieeeio->write(buffer,DataRecordHdrSize); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.rank),4); +#else + r=ieeeio->write(&rec,DataRecordHdrSize); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,DataRecordHdr &rec){ + char buffer[DataRecordHdrSize]; + int r=ieeeio->read(buffer,DataRecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4);//3 elements of 4 bytes +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.rank),4); +#else + ::bcopy(buffer,(char*)&rec,DataRecordHdrSize); +#endif + return r; + } + }; +#define DataRecordHdr64Size (8+4+4) // T3E Kludge + struct DataRecordHdr64 { + Long8 datasize; + Int numbertype; + Int rank; + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,DataRecordHdr64 &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ + char buffer[DataRecordHdr64Size]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,8); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+8,1,4); + IEEEIO::byteswapBuffer(&(rec.rank),buffer+12,1,4); + r=ieeeio->write(buffer,DataRecordHdr64Size); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),8); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.rank),4); +#else + r=ieeeio->write(&rec,DataRecordHdr64Size); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,DataRecordHdr64 &rec){ + char buffer[DataRecordHdr64Size]; + int r=ieeeio->read(buffer,DataRecordHdr64Size); + if(ieeeio->swapbytes){ + IEEEIO::byteswapBuffer(buffer,1,8); + IEEEIO::byteswapBuffer(buffer+8,2,4);//2 elements of 4 bytes + } +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + ::bcopy(buffer,&(rec.datasize),8); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.rank),4); +#else + ::bcopy(buffer,(char*)&rec,DataRecordHdr64Size); +#endif + return r; + } + }; +#define AttributeRecordHdrSize (4+4+4) // T3E Kludge + struct AttributeRecordHdr { + Long datasize; + Int numbertype; + Int namesize; // attributes are named + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,AttributeRecordHdr &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ // pack a buffer + char buffer[AttributeRecordHdrSize]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.namesize),buffer+8,1,4); + r=ieeeio->write(buffer,RecordHdrSize); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.namesize),4); +#else + //printf("AttribRec::writing ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + r = ieeeio->write(&rec,AttributeRecordHdrSize); + //printf("Wrote attribhdr %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + //printf("\tr=%u\n",r); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,AttributeRecordHdr &rec){ + int r=0; + char buffer[AttributeRecordHdrSize]; + r=ieeeio->read(buffer,AttributeRecordHdrSize); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4); +#ifdef T3E + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.namesize),4); +#else + ::bcopy(buffer,(char*)&rec,AttributeRecordHdrSize); + //printf("AttribRec::reading ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); +#endif + return r; + } + }; +#define AttributeRecordHdr64Size (8+4+4) // T3E Kludge + struct AttributeRecordHdr64 { + Long8 datasize; + Int numbertype; + Int namesize; // attributes are named + // ** Inline these because they are + // ** actually kludges for the T3E + static int write(IEEEIO *ieeeio,AttributeRecordHdr64 &rec){ + int r=0; + // copy into buffer + if(ieeeio->swapbytes){ // pack a buffer + char buffer[AttributeRecordHdr64Size]; + IEEEIO::byteswapBuffer(&(rec.datasize),buffer,1,4); + IEEEIO::byteswapBuffer(&(rec.numbertype),buffer+4,1,4); + IEEEIO::byteswapBuffer(&(rec.namesize),buffer+8,1,4); + r=ieeeio->write(buffer,AttributeRecordHdr64Size); + } + else { +#ifdef T3E + r+=ieeeio->write(&(rec.datasize),4); + r+=ieeeio->write(&(rec.numbertype),4); + r+=ieeeio->write(&(rec.namesize),4); +#else + //printf("AttribRec::writing ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + r = ieeeio->write(&rec,AttributeRecordHdr64Size); + //printf("Wrote attribhdr %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); + //printf("\tr=%u\n",r); +#endif + } + return r; + } + static int read(IEEEIO *ieeeio,AttributeRecordHdr64 &rec){ + int r=0; + char buffer[AttributeRecordHdr64Size]; + r=ieeeio->read(buffer,AttributeRecordHdr64Size); + if(ieeeio->swapbytes) + IEEEIO::byteswapBuffer(buffer,3,4); +#ifdef T3E + ::bcopy(buffer,&(rec.datasize),4); + ::bcopy(buffer+4,&(rec.numbertype),4); + ::bcopy(buffer+8,&(rec.namesize),4); +#else + ::bcopy(buffer,(char*)&rec,AttributeRecordHdr64Size); + //printf("AttribRec::reading ds,nt,ns %d,%d,%d\n",rec.datasize,rec.numbertype,rec.namesize); +#endif + return r; + } + }; + + struct RecRef { + RecordHdr rec; + Long8 offset; + // should have a cached flag to indicate if Attribs should be scanned for + //virtual ~RecRef(); + // ** Inline these because they are + // ** actually kludges for the T3E + }; + + struct AttribRef : public RecRef { + //FlexArray name; + char name[64]; + AttribRef(); + AttribRef(AttribRef &src); + //virtual ~AttribRef(); + AttribRef &operator=(AttribRef &src); + // ** Inline these because they are + // ** actually kludges for the T3E + }; + + struct DataRef : public RecRef { + // should have a cached flag to indicate if Attribs should be scanned for + FlexArray annotations; + FlexArray attributes; + Long8 end_offset; + DataRef(); + //virtual ~DataRef(); + DataRef(DataRef &src); + DataRef &operator=(DataRef &src); + }; +private: + friend class AttribRef; + friend class DataRef; + friend class FileHdr; + friend class RecordHdr; + friend class DataRecordHdr; + friend class AttributeRecordHdr; + friend class DataRecordHdr64; + friend class AttributeRecordHdr64; + // convenience utilities +#ifdef T3E + int ffioIsTrue(); +#endif + void initPosition(); + inline Long8 getPosition(){return this->lseek(0,L_INCR);} + void restart(); + int nextRecord(); + int nextDataRecord(); + inline Long8 getLength(){ return file_length; } + static void byteswapBuffer(void *buf,Long8 nelements,int elementsize); + static void byteswapBuffer(void *source,void *dest,Long8 nelements,int elementsize); + int writeFileHeader(); + int readFileHeader(); + void rebuildFileHeader(); + void appendRecordTable(); + void buildRecordTable(); + void clearChunk(int nbytes); + void openFile(CONST char *fname,IObase::AccessMode access,int swbytes); + // annotations don't need a header + // for c, size includes null terminator. + // must decrement size for f77 + //inline int write(int fid,void *data,int size); +protected: + FlexArray rec_table; + FlexArray chunkdims; + FileHdr file_header; + RecordHdr current_rec,current_data_rec; + DataRecordHdr current_dat; + Long8 current_rec_offset; // offset past the record header + Long8 stream_offset; // kludge to allow index cache to be turned off + Long8 current_dat_offset; // to datarec + int fid,datasetnumber,ndatasets,swapbytes,current_reserved_chunk; + int hasread,streaming,cur_type_size; + IEEEIO *masterfile; + int writebuffersize,writebuffercount; + char *writebuffer; + Long8 savedposition; + Long8 virtual_position,actual_position; + Long8 file_length; +protected: + inline int write(const void *data,size_t size); + inline void flush(); + inline Long8 lseek(Long8 len, int direction); + inline int read(void *data,size_t size); +public: + //------------------------core stuff..................... + enum ExtendedAccessMode {Read=0,Write=1,Create=1,Append=2,SharedRead=4}; + + IObase::AccessMode mode(ExtendedAccessMode amode) + { + switch(amode){ + case Read: + return IObase::Read; + case Write: + return IObase::Write; + case Append: + return IObase::Append; + default: + return IObase::Read; + } + } + // the IEEEIO:: commented out to satisfy Microsoft Compiler + IEEEIO(CONST char *fname, ExtendedAccessMode access,int swbytes=0); + IEEEIO(CONST char *fname, AccessMode access,int swbytes=0); + IEEEIO(IEEEIO *file); // read-only dup an existing open file + virtual ~IEEEIO(); + virtual int isValid(); + // could use overloading to differentiate type here... (but I'm going simple) + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data); + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int read(void *data); + //virtual int readChunk(int dims,int origin,int stride,void *data)=0; + virtual int seek(int dataset_index); + virtual int nDatasets(); + + virtual int writeAnnotation(CONST char *annotation); + virtual int readAnnotationInfo(int number,int &length); // returns length (-1 if none left) + virtual int readAnnotation(int number,char *annotation,int maxsize=128); + virtual int nAnnotations(); + + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data); + // returns number + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128); + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem); // returns number + virtual int readAttribute(int number,void *data); + // virtual Long readAttribute(CONST char *name,void *data); + virtual int nAttributes(); + + //-----------------Chunking Utilities.................. + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + // Streaming interface is for support of PANDA, Sockets etc.. + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims); + virtual int writeStream(void *data,int length); + virtual int readStream(void *data,int length); + virtual int pause(); + virtual int resume(); + void bufferOn(long size=-1); + void bufferOff(); + //---------------------MPIO Experimental Methods------------ + void getFilename(char *fn,int maxlen=256); + int reserveStream(IObase::DataType typeID,int rank,CONST int *dims,Long8 &offset); + int writeStream(void *data,int length,Long8 offset); +}; +/* +int bcopy(char *src,char *dst,int len){ + // copying bytes on the DEC Alpha processor can be costly due + // to the penalty of non-aligned memory accesses. This tries + // to align the copys. + + You can use the program copyperf to see how bcopy() improves performance + You must build copyperf separately using + gmake copyperf + + The following will test copy a 64meg buffer 1 time. + copyperf 64m + The following will test copy a 32k buffer 1000 times + copyperf 32k 1000 + The performance differences are 4-to-1 or greater in favor of bcopy(). +} +*/ +int IEEEIO::write(const void *data,size_t size){ + //puts("***********write()"); +#ifdef T3E + static int ffio_inline_true=0; + if(ffio_inline_true >= 0){ + // do this test only once on first write + // this just gives someone a clue that they've done the + // wrong thing when they compiled +#ifdef FFIO + if(!ffioIsTrue()){ + fprintf(stderr,"Error!!! Inconsistent FFIO flags on a T3E!\n"); + fprintf(stderr,"Your libraries have been compiled without -DFFIO, but your executable has been compled and linked with them with -DFFIO.\n"); + fprintf(stderr,"\t*****Please either rebuild the IEEEIO library with -DFFIO or *remove* -DFFIO from your own build.******\n"); + } +#else + if(ffioIsTrue()){ + fprintf(stderr,"Error!!! Inconsistent FFIO flags on a T3E!\n"); + fprintf(stderr,"Your libraries have been compiled with -DFFIO, but your executable has been compled and linked with them without -DFFIO\n"); + fprintf(stderr,"\t*****Please recompile with -DFFIO******\n"); + } +#endif + ffio_inline_true = -1; + } +#endif + if(!writebuffer){ + register Long8 r=0; +#ifdef FFIO + r = ::ffwrite(fid,data,size); +#else + r = ::write(fid,data,size); +#endif + if(r>0) actual_position += r; + virtual_position = actual_position; + // if(r>0) virtual_position = actual_position = (actual_position+r); + if(virtual_position>file_length) file_length = virtual_position; + return r; + } + // otherwise, do a buffered write + int retval=0; + char *datap = (char *)data; + if(writebuffercount>0){ + // copy as much as you can to the writebuffer + // should use bcopy... its a whole lot faster!!! + Long8 copysize = (size>(size_t)(writebuffersize-writebuffercount))?(writebuffersize-writebuffercount):size; + bcopy(datap,writebuffer+writebuffercount,copysize); + writebuffercount += copysize; + virtual_position += copysize; + retval += copysize; + if(writebuffercount>=writebuffersize) + this->flush(); // dump immediately (updates both virtual and actual pos) + size-=copysize; datap+=copysize; + if(size<=0) { + // virtual_position = actual_position + writebuffercount; + if(virtual_position>file_length) file_length=virtual_position; + return retval; + } + } + // at this point size>0 and writebuffercount=0 + if(size<=0 || writebuffercount!=0){ + printf("***Write Failed: size=%u writebuffercount=%u\n", + (unsigned int)size,writebuffercount); + } + if(size<(size_t)writebuffersize){// store to buffer (size>0 is implicit in loop) + bcopy(datap,writebuffer+writebuffercount,size); + writebuffercount += size; + virtual_position += size; + retval += size; + } + else { + register Long8 r=0; + // its larger than buffer, so bypass it and + // write it directly to the disk. +#ifdef FFIO + r = ::ffwrite(fid,datap,size); +#else + r = ::write(fid,datap,size); +#endif + actual_position += r; + virtual_position = actual_position; // essentially equiv to flush + if(r>0) retval+=r; + } + // double-check virtual position + // virtual_position = actual_position + writebuffercount; + if(virtual_position>file_length) file_length = virtual_position; + return retval; +} +void IEEEIO::flush(){ + register Long8 r=0; + if(writebuffercount){ +#ifdef FFIO + r = ::ffwrite(fid,writebuffer,writebuffercount); +#else + r = ::write(fid,writebuffer,writebuffercount); +#endif + } + writebuffercount=0; + if((r+actual_position)!=virtual_position){ + fprintf(stderr,"IEEEIO::flush() : inconsistent file positions! r=%ld v=%ld a=%ld\n", + r,virtual_position,actual_position); + } + actual_position = virtual_position; + if(virtual_position>file_length) file_length=virtual_position; +} +Long8 IEEEIO::lseek(Long8 len, int direction){ + // compute new pos + register Long8 npos=0; + // can seek beyond end of file + switch(direction){ + case L_XTND: /* should do special case for 0 len */ + npos = file_length + len; + break; + case L_SET: + npos = len; + break; + case L_INCR:; + npos = virtual_position + len; + break; + } + if(npos>file_length) + file_length = npos; + if(virtual_position != npos) { + if(writebuffer) + this->flush(); // must flush current buffer contents + // printf("Actually seeking from %ld to %ld\n",virtual_position,npos); + virtual_position = actual_position = npos; +#ifdef FFIO + // if(!writebuffer) + return ::ffseek(fid,npos,L_SET); +#else + // if(!writebuffer) +#ifdef SGI + return ::lseek64(fid,npos,L_SET); +#else + return ::lseek(fid,npos,L_SET); +#endif +#endif + } + return npos; // otherwise no change required +} +/* Will eventually want to buffer the reads as well... */ +int IEEEIO::read(void *data,size_t size){ + register int r=0; + if(writebuffercount>0) + flush(); +#ifdef FFIO + r = ::ffread(fid,data,size); +#else + r = ::read(fid,data,size); +#endif + if(r>0) virtual_position += r; + actual_position=virtual_position; + // can't read past end of file of course so no need to update file_length; + return r; +} + + +//==========F77 Interface============= +#define f_ieee_open F77NAME(ieee_open_,ieee_open,IEEE_OPEN) +#define f_ieee_openr F77NAME(ieee_openr_,ieee_openr,IEEE_OPENR) +#define f_ieee_openw F77NAME(ieee_openw_,ieee_openw,IEEE_OPENW) +#define f_ieee_opena F77NAME(ieee_opena_,ieee_opena,IEEE_OPENA) +#define f_ieee_bufon F77NAME(ieee_bufon_,ieee_bufon,IEEE_BUFON) +#define f_ieee_bufoff F77NAME(ieee_bufoff_,ieee_bufoff,IEEE_BUFOFF) +extern "C"{ +#ifdef CRAY // Note: This isn't really implemented yet... +#include + Long8 f_ieee_open (_fcd fcfilename,_fcd fcaccessmode); + Long8 f_ieee_openr (_fcd fcfilename); + Long8 f_ieee_openw (_fcd fcfilename); + Long8 f_ieee_opena (_fcd fcfilename); +#else + Long8 f_ieee_open (char *filename,char *accessmode,int namelen,int accesslength); + Long8 f_ieee_openr (char *filename,int namelen); + Long8 f_ieee_openw (char *filename,int namelen); // actually IObase::Create + Long8 f_ieee_opena (char *filename,int namelen); +#endif + void f_ieee_bufon (Long8 *fileID,int *bufsize); + void f_ieee_bufoff (Long8 *fileID); + //=====================ANSI C interface +#include "IEEEIO.h" // ANSI C interface + } + +#endif diff --git a/src/IEEEIOWinDllApi.h b/src/IEEEIOWinDllApi.h new file mode 100644 index 0000000..8d1296c --- /dev/null +++ b/src/IEEEIOWinDllApi.h @@ -0,0 +1,42 @@ +///////////////////////////////////////////////////////////////// +// +// $Id$ +// +// $Log$ +// Revision 1.3 2000/09/11 14:58:45 tradke +// Undo my last commit. #ifdef _WIN32 should be fine. +// +// Revision 1.2 2000/09/11 14:07:22 tradke +// #ifdef _WIN32 -> #ifdef WIN32 +// +// Revision 1.1 2000/02/24 05:47:45 jshalf +// +// More minor bugfixes to eliminate compiler warnings. +// Added Windows support file which was formerly forgotten in +// the repos. +// +// Revision 1.1 2000/01/11 15:56:01 werner +// Windows Compliance, added WinDLL API. +// +// Revision 1.1 2000/01/07 17:52:48 bzfbenge +// Template file for Win DLL API generation +// +// +///////////////////////////////////////////////////////////////// + +#ifndef __IEEEIO_WIN_DLL_API_H +#define __IEEEIO_WIN_DLL_API_H + + +#ifdef _WIN32 +# ifdef IEEEIO_EXPORTS +# define IEEEIO_API __declspec(dllexport) +# else +# define IEEEIO_API __declspec(dllimport) +# endif +#else +# define IEEEIO_API +#endif + +#endif /* __IEEEIO_WIN_DLL_API_H */ + diff --git a/src/IEEEIOslave.hh b/src/IEEEIOslave.hh new file mode 100644 index 0000000..79e7b3e --- /dev/null +++ b/src/IEEEIOslave.hh @@ -0,0 +1,63 @@ +#ifndef __IEEEIOSLAVE_HH_ +#define __IEEEIOSLAVE_HH_ + +class IEEEIOslave { + // open two fid's (one for O_DIRECT and the other for buffered) + // determine which sections of the buffer are remainders and + // write them buffered which requires nasty locking + // since this is SGI_specific, we can use aio for the remainders + int fid; + struct ffsw ffopens_status; +public: + IEEEIOslave(char *filename):fid(-1){ + // opens read/write + fid = open(fname,O_RDWR,0644); + } + ~IEEEIOslave(){ + if(fid>=0){ + close(fid); + } + } +}; + +#ifdef T3E +// T3E-specific ffio slaves +// #define open(x,y,z) ffopens(x,y,z, 0, 0, &ffopens_status, "bufa.bufsize=256.num_buffers=4") + +class ffIEEEIOslave { + int fid; +public: + IEEEIOslave(char *filename):fid(-1){ + // opens read/write + fid = ffopens(fname,O_RDWR,0644); + } + ~IEEEIOslave(){ + if(fid>=0){ + ffclose(fid); + } + } +}; + + + +#ifdef SGI +// SGI-specific slaves + +class asyncIEEEIOslave { + int fid; +public: + IEEEIOslave(char *filename):fid(-1){ + // opens read/write + } + ~IEEEIOslave(){ + if(fid>=0){ + close(fid); + } + } +}; + + + +#endif + +#endif diff --git a/src/IO.cc b/src/IO.cc new file mode 100644 index 0000000..a6c8eab --- /dev/null +++ b/src/IO.cc @@ -0,0 +1,371 @@ + +#include +#include +#include +#include "IO.hh" + +IObase::IObase(CONST char *fname,AccessMode access):index(0),nitems(0),accessmode(access){ + strcpy(filename,fname); +} + +IObase::DataType IObase::Int2DataType(int dt){ + if(dt==Byte) + return Byte; + else if(dt==Int16) + return Int16; + else if(dt==Int32) + return Int32; + else if(dt==Int64) + return Int64; + else if(dt==Float32) + return Float32; + else if(dt==Float64) + return Float64; + else if(dt==uInt8) + return uInt8; + else if(dt==uInt16) + return uInt16; + else if(dt==uInt32) + return uInt32; + else if(dt==uInt64) + return uInt64; + else if(dt==Char8) + return Char8; + else if(dt==Char16) + return Char16; + else return Error; +} + +int IObase::sizeOf(IObase::DataType dt){ + switch(dt){ + case Int8: + case uInt8: + case Char8: + return 1; + case Int16: + case uInt16: + case Char16: + return 2; + case Int32: + case uInt32: + case Float32: + return 4; + case Int64: + case uInt64: + case Float64: + return 8; + default: + return 0; + } +} + +int IObase::nElements(int rank,CONST int *dims){ + int nelem,i; + for(i=0,nelem=1;iisValid(); +} + +int f_io_sizeof(int *type){ + return IObase::sizeOf(IObase::Int2DataType(*type)); +} + +int f_io_nelements(int *rank,int *dims){ + return IObase::nElements(*rank,dims); +} + +int f_io_nbytes(int *type,int *rank,int *dims){ + return IObase::nBytes(IObase::Int2DataType(*type),*rank,dims); +} + +int f_io_write(Long8 *deviceID,int *typeID,int *rank,int *dims,void *data){ + IObase *dev=(IObase*)(*deviceID); + dev->write(dev->Int2DataType(*typeID),*rank,dims,data); + return 1; +} + +int f_io_readinfo(Long8 *deviceID,int *typeID,int *rank,int *dims,int *maxdims){ + IObase *dev=(IObase*)(*deviceID); + IObase::DataType tid; + if(*maxdims<0) *maxdims=0; + int r=dev->readInfo(tid,*rank,dims,*maxdims); + //int r=dev->readInfo(tid,*rank,dims); + *typeID=tid; + return r; +} + +int f_io_numdata(Long8 *deviceID){ + IObase *dev=(IObase*)(*deviceID); + return dev->nDatasets(); +} +int f_io_read(Long8 *deviceID,void *data){ + IObase *dev=(IObase*)(*deviceID); + return dev->read(data); +} + +int f_io_seek(Long8 *deviceID,int *dataset_index){ + IObase *dev=(IObase*)(*deviceID); + return dev->seek(*dataset_index); +} +//--------------Annotations +int f_io_writenote(Long8 *deviceID,char *annotation,int size){ + IObase *dev=(IObase*)(*deviceID); + annotation[size]='\0'; // Yeah! its unsafe I know..!! (but it works!) + return dev->writeAnnotation(annotation); +} + +int f_io_readnote(Long8 *deviceID,int *index,char *annotation,int maxsize){ + IObase *dev=(IObase*)(*deviceID); + return dev->readAnnotation(*index,annotation,maxsize); +} + +int f_io_noteinfo(Long8 *deviceID,int *index,int *length){ + IObase *dev=(IObase*)(*deviceID); + return dev->readAnnotationInfo(*index,*length); +} + +int f_io_numnote(Long8 *deviceID){ + IObase *dev=(IObase*)(*deviceID); + return dev->nAnnotations(); +} + +//---------------Attributes +int f_io_writeatt(Long8 *deviceID,char *name, + int *datatype,Long *nelements,void *data,int namesize){ + IObase *dev=(IObase*)(*deviceID); + name[namesize]='\0'; // cap name (to be certain).. unsafe but it works + // should copy into a flexarray which will be destroyed on return + IObase::DataType typeID = IObase::Int2DataType(*datatype); + return dev->writeAttribute(name,typeID,*nelements,data); +} + +int f_io_attinfo(Long8 *deviceID,char *name, + int *datatype,Long *nelements,int namesize){ + IObase *dev=(IObase*)(*deviceID); + IObase::DataType typeID; + if(namesize>0) + name[namesize]='\0'; + int i=dev->readAttributeInfo(name,typeID,*nelements); + *datatype=typeID; + return i; +} + +int f_io_iattinfo(Long8 *deviceID,int *index,char *name, + int *datatype,Long *nelements,int namesize){ + int i; + IObase *dev=(IObase*)(*deviceID); + IObase::DataType typeID; + for(i=0;ireadAttributeInfo(*index,name,typeID,*nelements,namesize); + // need to zero the array + //printf("io_iattinfo(): Newname=[%s]\n",name); + *datatype=typeID; + //printf("io_iattinfo(): attribs are index=%u type=%u nelements=%u namesize=%u\n", + // *index,*datatype,*nelements,namesize); + return i; +} + +int f_io_readatt(Long8 *deviceID,int *number,void *data){ + IObase *dev=(IObase*)(*deviceID); + return dev->readAttribute(*number,data); +} + +int f_io_numatt(Long8 *deviceID){ + IObase *dev=(IObase*)(*deviceID); + return dev->nAttributes(); +} + +//==========F77 Chunking interface-------------------- +int f_io_reserveck(Long8 *deviceID,int *typeID,int *rank,int *dims){ + IObase *dev=(IObase*)(*deviceID); + return dev->reserveChunk(dev->Int2DataType(*typeID),*rank,dims); +} + +int f_io_writeck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data){ + IObase *dev=(IObase*)(*deviceID); + return dev->writeChunk(chunkdims,chunkorigin,data); +} + +int f_io_readck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data){ + IObase *dev=(IObase*)(*deviceID); + return dev->readChunk(chunkdims,chunkorigin,data); +} +int f_io_writestrm(Long8 *deviceID,void *data,int *length){ + IObase *dev=(IObase*)(deviceID); + return dev->writeStream(data,*length); +} + +int f_io_readstrm(Long8 *deviceID,void *data,int *length){ + IObase *dev=(IObase*)(deviceID); + return dev->readStream(data,*length); +} + +int f_io_pause(Long8 *deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->pause(); +} + +int f_io_resume(Long8 *deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->resume(); +} + +//====================C Interface======================== +int IOclose(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + delete dev; + deviceID=0; + return 1; +} + +int IOisValid(IOFile deviceID){ + if(!deviceID) return 0; + IObase *dev=(IObase*)(deviceID); + return dev->isValid(); +} + +int IOsizeOf(int type){ + return IObase::sizeOf(IObase::Int2DataType(type)); +} + +int IOnElements(int rank,int *dims){ + return IObase::nElements(rank,dims); +} + +int IOnBytes(int type,int rank,int *dims){ + return IObase::nBytes(IObase::Int2DataType(type),rank,dims); +} + +int IOwrite(IOFile deviceID,int typeID,int rank,int *dims,void *data){ + IObase *dev=(IObase*)(deviceID); + return dev->write(dev->Int2DataType(typeID),rank,dims,data); +} + +int IOreadInfo(IOFile deviceID,int *typeID,int *rank,int *dims,int maxdims){ + IObase *dev=(IObase*)(deviceID); + IObase::DataType tid; + int r=dev->readInfo(tid,*rank,dims,maxdims); + *typeID=tid; + return r; +} + +int IOread(IOFile deviceID,void *data){ + IObase *dev=(IObase*)(deviceID); + return dev->read(data); +} + +int IOseek(IOFile deviceID,int dataset_index){ + IObase *dev=(IObase*)(deviceID); + return dev->seek(dataset_index); +} + +int IOnDatasets(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->nDatasets(); +} + +int IOwriteAnnotation(IOFile deviceID,char *annotation){ + IObase *dev=(IObase*)(deviceID); + //annotation[size]='\0'; // Yeah! its unsafe I know..!! (but it works!) + return dev->writeAnnotation(annotation); +} + +int IOreadAnnotation(IOFile deviceID,int index,char *annotation,int maxsize){ + IObase *dev=(IObase*)(deviceID); + return dev->readAnnotation(index,annotation,maxsize); +} + +int IOreadAnnotationInfo(IOFile deviceID,int index,int *size){ + IObase *dev=(IObase*)(deviceID); + return dev->readAnnotationInfo(index,*size); +} + +int IOnAnnotations(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->nAnnotations(); +} + +int IOwriteAttribute(IOFile deviceID,char *name,int type,Long length,void *data){ + IObase *dev=(IObase*)(deviceID); + IObase::DataType typeID = IObase::Int2DataType(type); + return dev->writeAttribute(name,typeID,length,data); +} + +int IOreadIndexedAttributeInfo(IOFile deviceID,int number,char *name, + int *type,Long *nelem,int maxnamelen){ + IObase *dev=(IObase*)(deviceID); + IObase::DataType typeID; + int i=dev->readAttributeInfo(number,name,typeID,*nelem,maxnamelen); + *type=typeID; // convert from enum + return i; +} + +int IOreadAttributeInfo(IOFile deviceID,char *name,int *type,Long *nelem){ + IObase *dev=(IObase*)(deviceID); + IObase::DataType typeID; + int i=dev->readAttributeInfo(name,typeID,*nelem); + *type=typeID; // convert from enum + return i; +} + +int IOreadAttribute(IOFile deviceID,int number,void *data){ + IObase *dev=(IObase*)(deviceID); + return dev->readAttribute(number,data); +} + +int IOnAttributes(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->nAttributes(); +} + +//=============C Chunking interface--------------- +int IOreserveChunk(IOFile deviceID,int typeID,int rank,int *dims){ + IObase *dev=(IObase*)(deviceID); + return dev->reserveChunk(dev->Int2DataType(typeID),rank,dims); +} + +int IOwriteChunk(IOFile deviceID,int *chunkdims,int *chunkorigin,void *data){ + IObase *dev=(IObase*)(deviceID); + return dev->writeChunk(chunkdims,chunkorigin,data); +} + +int IOreadChunk(IOFile deviceID,int *chunkdims,int *chunkorigin,void *data){ + IObase *dev=(IObase*)(deviceID); + return dev->readChunk(chunkdims,chunkorigin,data); +} + +int IOwriteStream(IOFile deviceID,void *data,int length){ + IObase *dev=(IObase*)(deviceID); + return dev->writeStream(data,length); +} + +int IOreadStream(IOFile deviceID,void *data,int length){ + IObase *dev=(IObase*)(deviceID); + return dev->readStream(data,length); +} +int IOpause(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->pause(); +} + +int IOresume(IOFile deviceID){ + IObase *dev=(IObase*)(deviceID); + return dev->resume(); +} diff --git a/src/IO.hh b/src/IO.hh new file mode 100644 index 0000000..330a8d1 --- /dev/null +++ b/src/IO.hh @@ -0,0 +1,188 @@ +#ifndef __IO_HH_ +#define __IO_HH_ +#include "Arch.h" + +class IObase { +public: + //-----------------------Public Enums.................... + enum AccessMode {Read=0,Write=1,Create=1,Append=2}; + enum DataType {Byte=0,Int8=0,Int16=1,Int32=2,Int64=3, + Float32=4,Float64=5, + uInt8=6,uChar=6,uInt16=7,uInt32=8,uInt64=9, + Char=10,Char8=10,String=10,Unicode=11,Char16=11, // special string types + Error=-1}; +protected: + //-----------------------State variables................. + int index,nitems; + AccessMode accessmode; + char filename[256]; +public: + //------------------------core stuff..................... + IObase(CONST char *fname,AccessMode access); + virtual ~IObase() {} + virtual int isValid() { return 0; } + // could use overloading to differentiate type here... (but I'm going simple) + virtual int write(DataType typeID,int rank,CONST int *dims,void *data)=0; + virtual int readInfo(DataType &typeID,int &rank,int *dims,int maxdims=3)=0; + virtual int read(void *data)=0; + virtual int seek(int dataset_index)=0; + virtual int nDatasets()=0; + virtual int writeAnnotation(CONST char *annotation)=0; + virtual int readAnnotationInfo(int number,int &length)=0; // returns length (-1 if none left) + virtual int readAnnotation(int number,char *annotation,int maxsize=128)=0; + virtual int nAnnotations()=0; + + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data)=0; + // returns number + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128)=0; + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem)=0; // returns number + +#ifdef T3E + /********** Kludge for T3E support*/ + inline int readAttributeInfo(int number,char *name,IObase::DataType &typeID,int &nelem,int maxnamelen=128){ + register Long n=nelem; + register int r=this->readAttributeInfo(number,name,typeID,n,maxnamelen); + nelem=n; + return r; +} + inline int readAttributeInfo(CONST char *name,IObase::DataType &typeID,int &nelem){ + register Long n=nelem; + register int r=this->readAttributeInfo(name,typeID,n); + nelem=n; + return r; +} + // returns number +#endif + + virtual int readAttribute(int number,void *data)=0; + // virtual Long readAttribute(char *name,void *data); + virtual int nAttributes()=0; + + //-----------------Chunking Features (for MPI/HPF)................ + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims)=0; + + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data)=0; + // virtual int writeStridedChunk()=0; + // virtual int writeHPF(int processorID,int *proclayout,IObase::HPFlayout *arraylayout,void *data)=0; + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data)=0; + // virtual int readStrided()=0; + // virtual int readHPF(int processorID,int *proclayout,IObase::HPFlayout *arraylayout,void *data)=0; + //-----------------Streaming interface (for PANDA, Sockets & MPIO)......... + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims)=0; + virtual int writeStream(void *data,int length)=0; + virtual int readStream(void *data,int length)=0; + //-----------------------Utilities........................ + // unfortunately you can cast enums to int but not the reverse + static DataType Int2DataType(int dt); + static int sizeOf(DataType dt); + static int nElements(int rank,CONST int *dims); // returns number of elements in dataset + static int nBytes(DataType dt,int rank,CONST int *dims); // returns number of bytes (good for malloc) + CONST char *name() { return filename; } + virtual int pause() { return 0; } + virtual int resume() { return 0; } +}; + +//===================Fortran77 Interface +#define f_io_close F77NAME(io_close_,io_close,IO_CLOSE) +#define f_io_isvalid F77NAME(io_isvalid_,io_isvalid,IO_ISVALID) +#define f_io_sizeof F77NAME(io_sizeof_,io_sizeof,IO_SIZEOF) +#define f_io_nbytes F77NAME(io_nbytes_,io_nbytes,IO_NBYTES) +#define f_io_nelements F77NAME(io_nelements_,io_nelements,IO_NELEMENTS) +#define f_io_write F77NAME(io_write_,io_write,IO_WRITE) +#define f_io_readinfo F77NAME(io_readinfo_,io_readinfo,IO_READINFO) +#define f_io_read F77NAME(io_read_,io_read,IO_READ) +#define f_io_seek F77NAME(io_seek_,io_seek,IO_SEEK) +#define f_io_numdata F77NAME(io_numdata_,io_numdata,IO_NUMDATA) +#define f_io_writenote F77NAME(io_writenote_,io_writenote,IO_WRITENOTE) +#define f_io_readnote F77NAME(io_readnote_,io_readnote,IO_READNOTE) +#define f_io_numnote F77NAME(io_numnote_,io_numnote,IO_NUMNOTE) +#define f_io_writeatt F77NAME(io_writeatt_,io_writeatt,IO_WRITEATT) +#define f_io_attinfo F77NAME(io_attinfo_,io_attinfo,IO_ATTINFO) +#define f_io_iattinfo F77NAME(io_iattinfo_,io_iattinfo,IO_IATTINFO) +#define f_io_readatt F77NAME(io_readatt_,io_readatt,IO_READATT) +#define f_io_numatt F77NAME(io_numatt_,io_numatt,IO_NUMATT) +#define f_io_reserveck F77NAME(io_reserveck_,io_reserveck,IO_RESERVECK) +#define f_io_writeck F77NAME(io_writeck_,io_writeck,IO_WRITECK) +#define f_io_readck F77NAME(io_readck_,io_readck,IO_READCK) +#define f_io_writestrm F77NAME(io_writestrm_,io_writestrm,IO_WRITESTRM) +#define f_io_readstrm F77NAME(io_readstrm_,io_readstrm,IO_READSTRM) +#define f_io_pause F77NAME(io_pause_,io_pause,IO_PAUSE) +#define f_io_resume F77NAME(io_resume_,io_resume,IO_RESUME) +extern "C"{ +//================Ansi C interface +#include "IOProtos.h" +//==== f77 interface +#ifdef CRAY + // Cray fortran uses an _fcd data structure to pass strings. This is in preparation + // for using this on Crays, but since nobody is using them yet, I've left the code for + // these versions of the routines blank. It'll be filled in later if the need arises +#include + int f_io_close (Long8 *deviceID); + int f_io_isvalid (Long8 *deviceID); + int f_io_sizeof (int *datatype); + int f_io_nelements (int *rank,int *dims); + int f_io_nbytes (int *datatype,int *rank,int *dims); + int f_io_write (Long8 *deviceID,int *typeID,int *rank,int *dims,void *data); + int f_io_readinfo (Long8 *deviceID,int *typeID,int *rank,int *dims,int *maxdims); + int f_io_read (Long8 *deviceID,void *data); + int f_io_seek (Long8 *deviceID,int *dataset_index); + int f_io_numdata (Long8 *deviceID); + int f_io_writenote (Long8 *deviceID,_fcd fcannotation); + int f_io_noteinfo (Long8 *deviceID,int *number,int *length); + int f_io_readnote (Long8 *deviceID,int *number,_fcd fcannotation); + int f_io_numnote (Long8 *deviceID); + + int f_io_writeatt (Long8 *deviceID,_fcd fcname, + int *datatype,Long *nelements,void *data); + int f_io_attinfo (Long8 *deviceID,_fcd fcname, + int *datatype,Long *nelements); + int f_io_iattinfo (Long8 *deviceID,int *index,_fcd fcname, + int *datatype,Long *nelements); + int f_io_readatt (Long8 *deviceID,int *number,void *data); + int f_io_numatt (Long8 *deviceID); + int f_io_reserveck(Long8 *deviceID,int *typeID,int *rank,int *dims); + int f_io_writeck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data); + int f_io_readck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data); + int f_io_writestrm(Long8 *deviceID,void *data,int *length); + int f_io_readstrm(Long8 *deviceID,void *data,int *length); + int f_io_pause(Long8 *deviceID); + int f_io_resume(Long8 *deviceID); +#else + int f_io_close (Long8 *deviceID); + int f_io_isvalid (Long8 *deviceID); + int f_io_sizeof (int *datatype); + int f_io_nelements (int *rank,int *dims); + int f_io_nbytes (int *datatype,int *rank,int *dims); + int f_io_write (Long8 *deviceID,int *typeID,int *rank,int *dims,void *data); + int f_io_readinfo (Long8 *deviceID,int *typeID,int *rank,int *dims,int *maxdims); + int f_io_read (Long8 *deviceID,void *data); + int f_io_seek (Long8 *deviceID,int *dataset_index); + int f_io_numdata (Long8 *deviceID); + + int f_io_writenote (Long8 *deviceID,char *annotation,int size); + int f_io_noteinfo (Long8 *deviceID,int *number,int length); + int f_io_readnote (Long8 *deviceID,int *number,char *annotation,int maxsize); + int f_io_numnote (Long8 *deviceID); + + int f_io_writeatt (Long8 *deviceID,char *name, + int *datatype,Long *nelements,void *data,int namesize); + int f_io_attinfo (Long8 *deviceID,char *name, + int *datatype,Long *nelements,int namesize); + int f_io_iattinfo (Long8 *deviceID,int *index,char *name, + int *datatype,Long *nelements,int namesize); + int f_io_readatt (Long8 *deviceID,int *number,void *data); + int f_io_numatt (Long8 *deviceID); + int f_io_reserveck(Long8 *deviceID,int *typeID,int *rank,int *dims); + int f_io_writeck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data); + int f_io_readck(Long8 *deviceID,int *chunkdims,int *chunkorigin,void *data); + int f_io_writestrm(Long8 *deviceID,void *data,int *length); + int f_io_readstrm(Long8 *deviceID,void *data,int *length); + int f_io_pause(Long8 *deviceID); + int f_io_resume(Long8 *deviceID); +#endif +} + +#endif + + + diff --git a/src/IOProtos.h b/src/IOProtos.h new file mode 100644 index 0000000..e2d475c --- /dev/null +++ b/src/IOProtos.h @@ -0,0 +1,63 @@ +/* IOProtos.h C header */ +#ifndef __IO_H_ +#define __IO_H_ +#ifndef UNITYPE +#define UNITYPE +#define BYTE 0 +#define INT8 0 +#define INT16 1 +#define INT32 2 +#define INT64 3 +#define FLOAT32 4 +#define FLOAT64 5 +#define UCHAR 6 +#define UINT8 6 +#define UINT16 7 +#define UINT32 8 +#define UINT64 9 +/* special string types */ +#define CHAR 10 +#define CHAR8 10 +#define STRING 10 +#define UNICODE 11 +#define CHAR16 11 +#endif +/* error */ +#define TYPEERROR -1 + +#define IOREAD 0 +#define IOWRITE 1 +#define IOAPPEND 2 +#define IOCREATE 1 /* Same as IOWRITE */ + +#include "Arch.h" + +int IOclose PROTO((IOFile deviceID)); +int IOisValid PROTO((IOFile deviceID)); +int IOsizeOf PROTO((int datatype)); +int IOnElements PROTO((int rank,int *dims)); +int IOnBytes PROTO((int datatype,int rank,int *dims)); +int IOwrite PROTO((IOFile deviceID,int typeID,int rank,int *dims,void *data)); +int IOreadInfo PROTO((IOFile deviceID,int *typeID,int *rank,int *dims,int maxdims)); +int IOread PROTO((IOFile deviceID,void *data)); +int IOseek PROTO((IOFile deviceID,int dataset_index)); +int IOnDatasets PROTO((IOFile deviceID)); +int IOwriteAnnotation PROTO((IOFile deviceID,char *annotation)); +int IOreadAnnotation PROTO((IOFile deviceID,int index,char *annotation,int maxsize)); +int IOreadAnnotationInfo PROTO((IOFile deviceID,int index,int *size)); +int IOnAnnotations PROTO((IOFile deviceID)); + +int IOwriteAttribute PROTO((IOFile deviceID,char *name,int type,Long length,void *data)); +int IOreadIndexedAttributeInfo PROTO((IOFile deviceID,int number, + char *name,int *type,Long *nelem,int maxnamelen)); +int IOreadAttributeInfo PROTO((IOFile deviceID,char *name,int *type,Long *nelem)); +int IOreadAttribute PROTO((IOFile deviceID,int number,void *data)); +int IOnAttributes PROTO((IOFile deviceID)); +int IOreserveChunk PROTO((IOFile deviceID,int typeID,int rank,int *dims)); +int IOwriteChunk PROTO((IOFile deviceID,int *chunkdims,int *chunkorigin,void *data)); +int IOreadChunk PROTO((IOFile deviceID,int *chunkdims,int *chunkorigin,void *data)); +int IOwriteStream PROTO((IOFile deviceID,void *data,int length)); +int IOreadStream PROTO((IOFile deviceID,void *data,int length)); +int IOpause PROTO((IOFile deviceID)); +int IOresume PROTO((IOFile deviceID)); +#endif diff --git a/src/IOspeed.cc b/src/IOspeed.cc new file mode 100644 index 0000000..a0003e4 --- /dev/null +++ b/src/IOspeed.cc @@ -0,0 +1,183 @@ +#include +#include +#include +#include +#include +#include +#include "Arch.h" +#include "IO.hh" +#include "IEEEIO.hh" +#include "HDFIO.hh" +#include "FlexArrayTmpl.H" + +#define f_openf77 F77NAME(openf77_,openf77,OPENF77) +#define f_writef77 F77NAME(writef77_,writef77,WRITEF77) +#define f_closef77 F77NAME(closef77_,closef77,CLOSEF77) +extern "C" { +void f_openf77(); +void f_writef77(double *data); +void f_closef77(); +} + +//typedef FlexArray FloatVector; +// +//class fVectorStatistics : public FloatVector { +// fVectorStatistics(int sz=0):FloatVector(sz){} +//}; + +struct ResultRecord { + float usertime,systemtime,realtime,combined,nbytes,megs_per_second; + // ResultRecord():usertime(0),systemtime(0),realtime(0), + // combined(0),nbytes(0),megs_per_second(0){} +}; + +#define ClearLine fprintf(stderr,"\r \r") + +struct ResultRecordList { + FlexArray results; + ResultRecord average_results; + ResultRecordList(){} + void append(ResultRecord &rec); + ResultRecord &operator[](int index){ + return results[index]; + } + +}; + +void ResultRecordList::append(ResultRecord &rec){ + int idx=results.getSize(); + float nrecs=(float)idx; + results.append(rec); + average_results.usertime=(average_results.usertime*nrecs+rec.usertime)/(nrecs+1); + average_results.systemtime=(average_results.systemtime*nrecs+rec.systemtime)/(nrecs+1); + average_results.realtime=(average_results.realtime*nrecs+rec.realtime)/(nrecs+1); + average_results.combined=(average_results.combined*nrecs+rec.combined)/(nrecs+1); + average_results.nbytes=(average_results.nbytes*nrecs+rec.nbytes)/(nrecs+1); + rec.megs_per_second = (double)(rec.nbytes)/(1024.0L*1024.0L*(double)rec.realtime); + average_results.megs_per_second = (average_results.megs_per_second*nrecs+rec.megs_per_second)/(nrecs+1); +} + +void main(int argc,char *argv[]){ + double data[64*64*64]; + int dims[3]={64,64,64}; + int i,nds; + int ntests; + struct tms stms,etms; + struct timeval stmv,etmv; + double srt,ert; + ResultRecordList ieeeio_results,f77_results,hdf_results; + + if(argc>1){ + ntests=atoi(argv[1]); + printf("Ntests=%u\n",ntests); + } + else { + ntests=1; + } + + for(int tst=0;tst "); + times(&stms); + gettimeofday(&stmv); + IObase *file = new IEEEIO("speed.raw",IObase::Write); + fprintf(stderr,"Write %2u datasets:",nds); + for(int n=0;nwrite(IObase::Float64,3,dims,data); + } + delete file; + gettimeofday(&etmv); + times(&etms); // times after close to account for buffer flushing + puts(""); + ert=(double)etmv.tv_sec + (double)etmv.tv_usec/1000000.0L; + srt=(double)stmv.tv_sec + (double)stmv.tv_usec/1000000.0L; + results.realtime = ert-srt; + results.usertime = (float)(etms.tms_utime-stms.tms_utime)/CLK_TCK; + results.systemtime = (float)(etms.tms_stime-stms.tms_stime)/CLK_TCK; + results.combined = (float)(etms.tms_utime-stms.tms_utime+ + etms.tms_stime-stms.tms_stime)/CLK_TCK; + results.nbytes = (float)(nds*IObase::nBytes(IObase::Float64,3,dims)); + ieeeio_results.append(results); + } + puts("--------------HDF---------------"); + for(i=0,nds=5;i<8;i++,nds+=5){ + fprintf(stderr,"HDF "); + times(&stms); + gettimeofday(&stmv); + IObase *file = new HDFIO("speed.hdf",IObase::Write); + fprintf(stderr,"Write %2u datasets:",nds); + for(int n=0;nwrite(IObase::Float64,3,dims,data); + } + delete file; + gettimeofday(&etmv); + times(&etms); // times after close to account for buffer flushing + puts(""); + ert=(double)etmv.tv_sec + (double)etmv.tv_usec/1000000.0L; + srt=(double)stmv.tv_sec + (double)stmv.tv_usec/1000000.0L; + results.realtime = ert-srt; + results.usertime = (float)(etms.tms_utime-stms.tms_utime)/CLK_TCK; + results.systemtime = (float)(etms.tms_stime-stms.tms_stime)/CLK_TCK; + results.combined = (float)(etms.tms_utime-stms.tms_utime+ + etms.tms_stime-stms.tms_stime)/CLK_TCK; + results.nbytes = (float)(nds*IObase::nBytes(IObase::Float64,3,dims)); + hdf_results.append(results); + } + puts("-------------F77 Unformatted---------------"); + for(i=0,nds=5;i<8;i++,nds+=5){ + fprintf(stderr,"F77 Unf "); + times(&stms); + gettimeofday(&stmv); + f_openf77(); + fprintf(stderr,"Write %2u datasets:",nds); + for(int n=0;n +#include "MPIO.hh" + +MPIO::MPIO(IEEEIO *io, MPIcomm &c):file(io),comm(c),sendreq(0){ + + for(int i=0;i<3;i++) globaldims[i]=localdims[i]=localorigin[i]=0; + myid=comm.rank(); + + int *rootarray=0; + if(!myid) rootarray=new int[comm.numProcs()]; + int hasfile= file?1:0; + comm.gather(0,1,&hasfile,rootarray); + if(!myid){ + int count,p; + for(count=0,p=0;p1){ + fprintf(stderr,"MPIO only accepts a single IO node right now.\n"); + fprintf(stderr,"You chose %u io nodes\n",count); + fprintf(stderr,"I will select only the first one\n"); + } + } + for(int i=0;i<3;i++) slicebuffer[i]=0; + for(int i=0;i<2;i++) recvreq[i]=0; + comm.bcast(0,root); // tell everyone which proc is root + if(rootarray) {delete rootarray; rootarray=0;} +} + +MPIO::~MPIO(){} + +void MPIO::setLocalDims(int rank,int *origin, int *dims){ + if(rank!=3) perror("MPIO is only for 3D IO for now (sorry)!"); + if(sendreq) { puts("Bad move!!! Die!!!"); exit(0); } + // now check to see if anything has changed + // actually we still need to do this collection because we + // don't know if something might have changed on some other processor + // URK... + allorigins = new int[3*comm.numProcs()]; + alldims = new int[3*comm.numProcs()]; + for(int i=0;i<3;i++) { + //printf("localdims-n-origin[%u] = %u:%u\n",i,dims[i],origin[i]); + localdims[i]=dims[i]; + localorigin[i]=origin[i]; + } + for(int i=0;ireserveStream(IObase::Float32,3,globaldims); + } + for(int i=1;iwriteStream(slicebuffer[2],globaldims[0]*globaldims[1]); + } + } + if(isRoot()){ + int n = globaldims[2]-1; + waitForSlice(n,slicebuffer[(n)%2],slicebuffer[2],recvreq[(n)%2]); + file->writeStream(slicebuffer[2],globaldims[0]*globaldims[1]); + // do requestfree (double-buffered request free-s) + //for(int i=0;i<3;i++) delete slicebuffer[i]; // free everything up + //for(int i=0;i<2;i++) delete recvreq[i]; + } + //**** At end (matching deletes) **** + // fprintf(stderr,"Cleanup proc %u\n",myid); + // comm.print("Cleanup"); + for(int n=0;n=localdims[2]) return; + // fprintf(stderr,"\tSendSlice: Proc %u Slice %u sndindex=%u\n", + // myid,z,lz); + comm.iSend(root,z, + localdims[0]*localdims[1], // size of the data + data+localdims[0]*localdims[1]*lz,req[lz]); +} + +int MPIO::requestSlice(int z,float *slicebuf, MPI_Request *req){ + if(!isRoot()) return 0; // only root performs this operation + // for every processor that intersects this slice boundary, + // make a request for the contents of that slice! + int reqindex =0; + for(int offset=0,p=0;p=origin[2] && z=origin[2] && z +#include "MPIutils.hh" +#include "MPIO.hh" + +void MPIO::requestSlice(int z,float *slicebuffer,MPI_Request *req){ + // skip to z + //loop (foreach p of pe's) + if(!isRoot()) return; + //printf("requestSlice %u",z); + for(int reqindex=0,offset=0,idx=slicemap[z],lastchunk=slicemap[z]+chunkindexcount[z]; + idx=38) debug=1; + int p = procmap[chunkidx]; + //if(debug) printf("\tp=%u\n",p); + int *idims = gdims + chunkindex[chunkidx]; + //if(debug) printf("\tdims(%u)=%u:%u:%u\n",chunkidx,idims[0],idims[1],idims[2]); + int *iorigin = gorigins + chunkindex[chunkidx]; + //if(debug) printf("\torigin=%u:%u:%u\n",iorigin[0],iorigin[1],iorigin[2]); + MPI_Status stat; + //printf("waitfor(%u):MPI_Request[%u]=%u\n",z,reqindex,req[reqindex]); + // slicewait.start(); + comm.wait(req[reqindex],stat); // frees request object too + //slicewait.stop(); + // get information out of the status object!!!! + //slicecollect.start(); + int offset = iorigin[1]*globaldims[0] + iorigin[0]; + for(int idx=0,pos=offset,j=0;j1){ + fprintf(stderr,"MPIO only accepts a single IO node right now.\n"); + fprintf(stderr,"You chose %u io nodes\n",count); + fprintf(stderr,"I will select only the first one\n"); + } + for(root=-1,p=0;p=idims[2]) continue; + thickness = gdims[2]; // assumes uniform domain decomp in Z + chunkcount++; + } + } + // procmap = new int[chunkcount]; + //chunkindex = new int[chunkcount]; // points into iorigin/idims + // chunkindexcount = chunkcount; + } + procmap = new int[comm.numProcs()]; + chunkindex = new int [comm.numProcs()]; + // printf("(2): chunkindexcount = %u\n",chunkindexcount); + for(int thickness=0,mapcount=0,chunkcount=0,z=0;z=idims[2]) continue; + thickness = gdims[2]; + procmap[chunkcount] = p; + chunkindex[chunkcount] = dindex; // point into iorogin/idims + //printf("chunkcount=%u chunkindex=%u\n",chunkcount,chunkindex[chunkcount]); + chunkcount++; + } + } + //puts("(3)"); + for(chunkcount=0,z=0;z=idims[2]) continue; + thickness = gdims[2]; + levelcount++; chunkcount++; + } + for(int pz=0;pzreserveChunk operation + if(isRoot()) file->reserveStream(IObase::Float32,3,globaldims); + int writecount=0; + for(int i=1;iwriteStream(slicebuffer[2],globaldims[0]*globaldims[1]); + slicewrite.stop(); + } + } + if(isRoot()){ + waitForSlice(i-1,slicebuffer[(i-1)%2],slicebuffer[2],recvreq[(i-1)%2]); + file->writeStream(slicebuffer[2],globaldims[0]*globaldims[1]); + writecount+=globaldims[0]*globaldims[1]; + // do requestfree (double-buffered request free-s) + for(i=0;i<3;i++) delete slicebuffer[i]; // free everything up + for(i=0;i<2;i++) delete recvreq[i]; + } + MPI_Status stat; + for(i=0;i=localdims[2]) return; + //printf("sendslice %u\n",z); + comm.isSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); +} + +#endif // __MPIO_HH_ diff --git a/src/MPIO.h b/src/MPIO.h new file mode 100644 index 0000000..cf969f8 --- /dev/null +++ b/src/MPIO.h @@ -0,0 +1,16 @@ +#ifndef __MPIO_H_ +#define __MPIO_H_ + +#include "Arch.h" + +/*********************C Interface**********************/ + +IOFile MPIOopen (IOFile fid); + +int MPIOclose (IOFile deviceID); + +void MPIOsetLocalDims (IOFile deviceID, int rank, int *origin, int *dims); + +int MPIOwrite (IOFile deviceID, int typeID, void *data); + +#endif diff --git a/src/MPIO.hh b/src/MPIO.hh new file mode 100644 index 0000000..67bfebd --- /dev/null +++ b/src/MPIO.hh @@ -0,0 +1,39 @@ +#ifndef __MPIO_HH_ +#define __MPIO_HH_ + +#include "IEEEIO.hh" +#include "MPIutils.hh" +#include "Timer.hh" + +class MPIO { +typedef float *floatP; +typedef MPI_Request *MPI_RequestP; + + MPIcomm &comm; + int *alldims,*allorigins; + int globaldims[3]; // for all procs + int localorigin[3],localdims[3]; // local dims are full extent + bound & ghost + int root, myid; + IEEEIO *file; // only on master + MPI_Request *sendreq; // is it proper to have a pointer here? + MPI_RequestP recvreq[2]; // double-buffered + floatP slicebuffer[3]; // double-buffered + a scratch space + + +protected: + void sendSlice(int z, float *data, MPI_Request *req); + int requestSlice(int z, float *slicebuffer, MPI_Request *req); + void waitForSlice(int z, float *slicebuffer, float *destbuffer, MPI_Request *req); + void asyncWrite(float *data); +public: + MPIO(IEEEIO *io,MPIcomm &c); + ~MPIO(); + inline int isRoot() { return ((myid==root)?1:0);} + void setLocalDims(int rank,int *origin,int *dims); + virtual int write(float *data){ + asyncWrite(data); + return 1; + } +}; + +#endif diff --git a/src/MPIO.old.cc b/src/MPIO.old.cc new file mode 100644 index 0000000..ef609f1 --- /dev/null +++ b/src/MPIO.old.cc @@ -0,0 +1,344 @@ +#include +#include "MPIutils.hh" +#include "MPIO.hh" + +#define CollectTime 0 /* not collecting timing data right now */ + +void MPIO::sendSlice(int z,float *data,MPI_Request *req){ + int iz = z - localorigin[2]; + if(iz<0 || iz>=localdims[2]) return; + if(syncsend) + comm.isSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); + else + comm.iSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); +} + +void MPIO::requestSlice(int z,float *slicebuffer,MPI_Request *req){ + // skip to z + //loop (foreach p of pe's) + if(!isRoot()) return; + //printf("PE(%u) request slice %u\n",myid,z); + for(int offset=0,p=0,reqindex=0;p=idims[2]) continue; + comm.iRecv(p,z,idims[0]*idims[1],slicebuffer+offset,req[reqindex++]); + //printf("reqslice(%u):MPI_Request=%u\n",iz,req[reqindex-1]); + offset+=idims[0]*idims[1]; + } + // break if outside of z-range (dangerous if non-canonical proc layout) +} + +void MPIO::waitForSlice(int z,float *slicebuffer,float *destbuffer,MPI_Request *req){ + if(!isRoot()) return; + // could do this 8k at a time + // loop for each p of pe's + // if within z-range, compute nelem based on dims at p + // wait for current request. + // re-copy based on offset & origin + if(CollectTime) sliceallwait.start(); + for(int p=0,reqindex=0;p=idims[2]) continue; + MPI_Status stat; + //printf("waitfor(%u):MPI_Request=%u\n",iz,req[reqindex]); + if(CollectTime) slicewait.start();// this is a timer (start the timer) + comm.wait(req[reqindex++],stat); // frees request object too + if(CollectTime) slicewait.stop(); + // get information out of the status object!!!! + if(CollectTime) slicecollect.start(); + int offset = iorigin[1]*globaldims[0] + iorigin[0]; + for(int idx=0,pos=offset,j=0;j=localdims[2]) return; + if(syncsend) + comm.isSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); + else + comm.iSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); +} + +void MPIO::requestSlice(int z,double *slicebuffer,MPI_Request *req){ + // skip to z + //loop (foreach p of pe's) + if(!isRoot()) return; + //printf("PE(%u) request slice %u\n",myid,z); + for(int offset=0,p=0,reqindex=0;p=idims[2]) continue; + comm.iRecv(p,z,idims[0]*idims[1],slicebuffer+offset,req[reqindex++]); + //printf("reqslice(%u):MPI_Request=%u\n",iz,req[reqindex-1]); + offset+=idims[0]*idims[1]; + } + // break if outside of z-range (dangerous if non-canonical proc layout) +} + +void MPIO::waitForSlice(int z,double *slicebuffer,double *destbuffer,MPI_Request *req){ + if(!isRoot()) return; + // could do this 8k at a time + // loop for each p of pe's + // if within z-range, compute nelem based on dims at p + // wait for current request. + // re-copy based on offset & origin + if(CollectTime) sliceallwait.start(); + for(int p=0,reqindex=0;p=idims[2]) continue; + MPI_Status stat; + //printf("waitfor(%u):MPI_Request=%u\n",iz,req[reqindex]); + if(CollectTime) slicewait.start();// this is a timer (start the timer) + comm.wait(req[reqindex++],stat); // frees request object too + if(CollectTime) slicewait.stop(); + // get information out of the status object!!!! + if(CollectTime) slicecollect.start(); + int offset = iorigin[1]*globaldims[0] + iorigin[0]; + for(int idx=0,pos=offset,j=0;j1){ + fprintf(stderr,"MPIO only accepts a single IO node right now.\n"); + fprintf(stderr,"You chose %u io nodes\n",count); + fprintf(stderr,"I will select only the first one\n"); + } + for(root=-1,p=0;preserveChunk operation + if(isRoot()) file->reserveStream(IObase::Float32,3,globaldims); + int writecount=0; + for(int i=1;iwriteStream(slicebuffer[2],globaldims[0]*globaldims[1]); + slicewrite.stop(); + } + } + if(isRoot()){ + int n=globaldims[2]-1; + waitForSlice(n,slicebuffer[(n)%2],slicebuffer[2],recvreq[(n)%2]); + file->writeStream(slicebuffer[2],globaldims[0]*globaldims[1]); + writecount+=globaldims[0]*globaldims[1]; + // do requestfree (double-buffered request free-s) + for(int i=0;i<3;i++) delete slicebuffer[i]; // free everything up + for(int i=0;i<2;i++) delete recvreq[i]; + } +} + +void MPIO::asyncWrite(double *data){ + if(sendreq) return; + sendreq = new MPI_Request[localdims[2]]; + typedef double *doubleP; + // int sliceindex=0; + doubleP slicebuffer[3]; // double-buffer the slices as they arrive + typedef MPI_Request *MPI_RequestP; + MPI_RequestP recvreq[2]; + // the third one is a scratch buffer for reorganizing the slice + if(isRoot()){ + for(int i=0;i<3;i++) slicebuffer[i] = new double[globaldims[0]*globaldims[1]]; + for(int i=0;i<2;i++) recvreq[i] = new MPI_Request[comm.numProcs()]; + } + if(isRoot()){ + // puts("request initial slice"); + requestSlice(0,slicebuffer[0],recvreq[0]); + } + // not good! Everyone is sending a slice here! + sendSlice(0,data,sendreq); + // hide latency behind the costly io->reserveChunk operation + if(isRoot()) file->reserveStream(IObase::Float64,3,globaldims); + int writecount=0; + for(int i=1;iwriteStream(slicebuffer[2],globaldims[0]*globaldims[1]); + slicewrite.stop(); + } + } + if(isRoot()){ + int n = globaldims[2]-1; + waitForSlice(n,slicebuffer[(n)%2],slicebuffer[2],recvreq[(n)%2]); + file->writeStream(slicebuffer[2],globaldims[0]*globaldims[1]); + writecount+=globaldims[0]*globaldims[1]; + // do requestfree (double-buffered request free-s) + for(int i=0;i<3;i++) delete slicebuffer[i]; // free everything up + for(int i=0;i<2;i++) delete recvreq[i]; + } +} +void MPIO::asyncFinalize(){ + MPI_Status stat; + if(!sendreq) return; + for(int i=0;i +#include "MPIutils.hh" +#include "MPIO.hh" + +void MPIO::sendSlice(int z,float *data,MPI_Request *req){ + int iz = z - localorigin[2]; + if(iz<0 || iz>=localdims[2]) return; + //printf("PE(%u) send slice z=%u. iz=%u\n",myid,z,iz); + // z == the tag + //printf("localdims[0]*localdims[1]=%u iz=%u\n",localdims[0]*localdims[1],iz); + // if(isRoot()) + //comm.iSend(root,z,localdims[0]*localdims[1], + // data+localdims[0]*localdims[1]*iz,req[iz]); + //else + comm.isSend(root,z,localdims[0]*localdims[1], + data+localdims[0]*localdims[1]*iz,req[iz]); + //for(int i=0;i<4;i++) //printf("\tslicedata[%u]@z(%u) = %f\n",i,iz,(data+localdims[0]*localdims[1]*iz)[i]); + //printf("PE(%u) send %u complete\n",myid,iz); +} + +void MPIO::requestSlice(int z,float *slicebuffer,MPI_Request *req){ + // skip to z + //loop (foreach p of pe's) + if(!isRoot()) return; + //printf("PE(%u) request slice %u\n",myid,z); + for(int offset=0,p=0,reqindex=0;p=idims[2]) continue; + comm.iRecv(p,z,idims[0]*idims[1],slicebuffer+offset,req[reqindex++]); + //printf("reqslice(%u):MPI_Request=%u\n",iz,req[reqindex-1]); + offset+=idims[0]*idims[1]; + } + // break if outside of z-range (dangerous if non-canonical proc layout) +} + +void MPIO::waitForSlice(int z,float *slicebuffer,float *destbuffer,MPI_Request *req){ + if(!isRoot()) return; + // could do this 8k at a time + // loop for each p of pe's + // if within z-range, compute nelem based on dims at p + // wait for current request. + // re-copy based on offset & origin + sliceallwait.start(); + for(int p=0,reqindex=0;p=idims[2]) continue; + MPI_Status stat; + //printf("waitfor(%u):MPI_Request=%u\n",iz,req[reqindex]); + slicewait.start(); + comm.wait(req[reqindex++],stat); // frees request object too + slicewait.stop(); + // get information out of the status object!!!! + slicecollect.start(); + int offset = iorigin[1]*globaldims[0] + iorigin[0]; + for(int idx=0,pos=offset,j=0;j1){ + fprintf(stderr,"MPIO only accepts a single IO node right now.\n"); + fprintf(stderr,"You chose %u io nodes\n",count); + fprintf(stderr,"I will select only the first one\n"); + } + for(root=-1,p=0;preserveChunk operation + if(isRoot()) file->reserveStream(IObase::Float32,3,globaldims); + int writecount=0; + for(int i=1;iwriteStream(slicebuffer[2],globaldims[0]*globaldims[1]); + slicewrite.stop(); + } + } + if(isRoot()){ + waitForSlice(i-1,slicebuffer[(i-1)%2],slicebuffer[2],recvreq[(i-1)%2]); + file->writeStream(slicebuffer[2],globaldims[0]*globaldims[1]); + writecount+=globaldims[0]*globaldims[1]; + // do requestfree (double-buffered request free-s) + for(i=0;i<3;i++) delete slicebuffer[i]; // free everything up + for(i=0;i<2;i++) delete recvreq[i]; + } + MPI_Status stat; + for(i=0;i +#include "vatoi.hh" +#include "IEEEIO.hh" +#include "MPIutils.hh" +#include "MPIO.hh" +#include "Timer.hh" + +int StupidProcLayoutSeive(int np,int decomp[3]){ + // Brute-Force method + // stupidly attempts all decomposition combinations + // and filters out unusable combinations. + // trys to select minimum surface area processor arrangement + int minarea = np*np*np; // impossibly high value + for(int i=1;i<=np;i++){ + for(int j=1;i*j<=np;j++){ + for(int k=1;i*j*k<=np;k++){ + if(i*j*k!=np) continue; + int area = i+j+k; // area metric (optimizing this weakly minimizes surface area) + if(arearank()) usage(); + } + } + void usage(){ + printf("Usage: %s <-verbose> <-dims int,int,int> <-dimtype global|local>", + programname); + printf("\tverbose: Opens file for reading after complete and prints all values.\n"); + printf("\tdims: Set the dimensions of the dataset. By default this is per-cpu.\n"); + printf("\t\tThis can be Global dimensions if you use -dimtype flag.\n"); + printf("\t\tDefault is 20,20,20.\n"); + printf("\tdimtype: \'global\' makes dimensions apply to the overall dataset\n"); + printf("\t\tregardless of number of processors and \'local\' is per-processor.\n"); + printf("\t\tThe default is per-processor.\n"); + } + void printStatus(FILE *f=stdout){ + fprintf(f,"%s: verbose=%u dims=%u,%u,%u dimtype=%s\n", + programname,verbose, + dims[0],dims[1],dims[2], + (dimtype==Local)?"Local":"Global"); + fprintf(f,"\t Buffer Cache is at %u bytes\n",bufsize); + } +}; + +int main(int argc,char *argv[]){ + MPIenv env(argc,argv); // start MPI threads + MPIcomm *comm = env.getComm(); + CommandLine cmdln(argc,argv,comm); + + int origin[3],dims[3]; + int proclayout[3],area; + int nghost=1; + area=StupidProcLayoutSeive(comm->numProcs(),proclayout); + // if(!comm->rank()) { + cmdln.printStatus(); + fprintf(stderr,"Proclayout = %u : %u,%u,%u\n",area, + proclayout[0],proclayout[1],proclayout[2]); + //} + for(int i=0;i<3;i++) dims[i]=cmdln.dims[i]; + if(cmdln.dimtype==CommandLine::Global) + for(int i=0;i<3;i++) dims[i]/=proclayout[i]; // create dims for layout computation + for(int p=0,k=0;krank()){ + // assumes same dims per process + origin[0]=dims[0]*i; + origin[1]=dims[1]*j; + origin[2]=dims[2]*k; + for(int n=0;n<3;n++){ + if(origin[n]-nghost>0) {origin[n]-=nghost; dims[n]+=(nghost);} + dims[n]+=nghost; + } + if(cmdln.dimtype==CommandLine::Global){ + // compute remainder for globaldims + if(k==(proclayout[2]-1)) + dims[2]=cmdln.dims[2]-origin[2]; + if(j==(proclayout[1]-1)) + dims[1]=cmdln.dims[1]-origin[1]; + if(i==(proclayout[0]-1)) + dims[0]=cmdln.dims[0]-origin[0]; + } + } + } + } + } + fprintf(stderr,"PE(%u) origin{%u,%u,%u} localdims{%u,%u,%u} nghost=%u\n", + comm->rank(),origin[0],origin[1],origin[2], + dims[0],dims[1],dims[2],nghost); + int size=1; + for(int i=0;i<3;i++) size*=dims[i]; + // Everybody allocates their own local data + float *data = new float[size]; + for(int i=0;irank()){ // only PE0 needs to open a file + IEEEIO *iofile; + file = iofile = new IEEEIO("mpdata.raw",IObase::Write); + if(cmdln.bufsize>0) + iofile->bufferOn(cmdln.bufsize); + } + else file=0; // else it is null + + MPIO *pfile = new MPIO(file,*comm); // but everyone creates the pfile + pfile->setLocalDims(3,origin,dims); + // if(cmdln.syncsends) pfile->useSyncrhonousSend(); + // puts("Write"); + comm->barrier(); + double stime = MPI_Wtime(); // start timing + //Timer t; + // t.start(); + for(int i=0;irank()==0) fprintf(stderr,"Trial %4u\n",i); + comm->barrier(); + pfile->write(data); + } + comm->barrier(); // synchronize completion + double etime = MPI_Wtime(); + // t.end(); + if(!comm->rank()){ + printf("\nElapsed time to write=%lf\n",etime-stime); + } + puts("done writing"); + delete pfile; + if(file) delete file; + delete data; + if(!comm->rank()){ + file = new IEEEIO("mpdata.raw",IObase::Read); + int ndims[3],nrank; + IObase::DataType dt; + file->readInfo(dt,nrank,ndims); + printf("IO performance = %f Megabytes/sec\n", + (float)(cmdln.ntrials)*(float)(IObase::nBytes(dt,nrank,ndims))/(1024*1024*(etime-stime))); + printf("Read mpdata.raw: rank=%u dims=%u,%u,%u\n",nrank,ndims[0],ndims[1],ndims[2]); + if(cmdln.verbose){ // dangerous on T3E + data = new float[IObase::nElements(nrank,ndims)]; + file->read(data); + for(int k=0,p=0;k=bufsize) + MPI_Buffer_attach(tmp,size); // reattach + else { + delete tmp; + attach(bufsize); + } + } + else + MPI_Buffer_attach(tmp,size); // reattach + /* fails if existing buffer was too small and + the source process deallocates the buffer without getting + a handle to it. + Can also fail if malloc != new on that architecture. + */ +} + + +// Must watch buffer attachment from external processes +MPIbuffer *MPIcomm::buffer; +MPI_Status MPIcomm::defstat; diff --git a/src/MPIutils.hh b/src/MPIutils.hh new file mode 100644 index 0000000..e4da9d4 --- /dev/null +++ b/src/MPIutils.hh @@ -0,0 +1,389 @@ +#ifndef __MPIUTILS_HH_ +#define __MPIUTILS_HH_ + +#include +#include +#include + +struct HpfBlockType { // or just HPFblock + enum Type {Block,None}; +}; + +/* +struct MPItype { + enum Type { +};*/ + +class MPIbuffer { + char *mybuf; + int bufsize; + void attach(int size); + void detach(); +public: + MPIbuffer(int size); + ~MPIbuffer(); + void resize(int size); + void grow(int size); + void check(); +}; +/* +class MPIthread{ +public: + MPI_Comm createCommunicator(); + int getRank(); + int growBufferTo(int size); + int snapBufferTo(int size); + int getTypeSize(MPI_Datatype type); +}; +*/ +/* Everything is inlined... this is a wrapper after all */ + +class MPIcomm { + int mypid; + int nprocs; + MPI_Comm comm; + int default_tag; + static MPIbuffer *buffer; +public: + static MPI_Status defstat; + MPIcomm(MPI_Comm commworld = MPI_COMM_WORLD): + comm(commworld),default_tag(0){ + // since these don't change, optimize by assigning + // to class variables to reduce subroutine call overhead + MPI_Comm_rank(comm,&mypid); + MPI_Comm_size(comm,&nprocs); + } + double time(){return MPI_Wtime();} + int numProcs() { return nprocs; } + int rank() { return mypid; } + void setDefaultTag(int d){ default_tag=d; } + inline int send(int dest,int tag,MPI_Datatype type,int nelem,void *data){ + return MPI_Send(data,nelem,type,dest,tag,comm); + } + inline int send(int dest,MPI_Datatype type,int nelem,void *data){ + return send(dest,default_tag,type,nelem,data); + } + inline int send(int dest,int nelem,float *data){ + return send(dest,default_tag,MPI_FLOAT,nelem,data); + } + inline int send(int dest,int nelem,double *data){ + return send(dest,default_tag,MPI_DOUBLE,nelem,data); + } + inline int send(int dest,int nelem,int *data){ + return send(dest,default_tag,MPI_INT,nelem,data); + } + inline int send(int dest,int nelem,char *data){ + return send(dest,default_tag,MPI_CHAR,nelem,data); + } + inline int recv(int src,int tag,MPI_Datatype type,int nelem,void *data,MPI_Status &s=MPIcomm::defstat){ + return MPI_Recv(data,nelem,type,src,tag,comm,&s); + } + inline int recv(MPI_Datatype type,int nelem,void *data,MPI_Status &s=MPIcomm::defstat){ + return recv(MPI_ANY_SOURCE,MPI_ANY_TAG,type,nelem,data,s); + } + + inline int recv(int src,int nelem,float *data,MPI_Status &s=MPIcomm::defstat){ + return recv(src,MPI_ANY_TAG,MPI_FLOAT,nelem,data,s); + } + inline int recv(int src,int nelem,double *data,MPI_Status &s=MPIcomm::defstat){ + return recv(src,MPI_ANY_TAG,MPI_DOUBLE,nelem,data,s); + } + inline int recv(int src,int nelem,int *data,MPI_Status &s=MPIcomm::defstat){ + return recv(src,MPI_ANY_TAG,MPI_INT,nelem,data,s); + } + inline int recv(int src,int nelem,char *data,MPI_Status &s=MPIcomm::defstat){ + return recv(src,MPI_ANY_TAG,MPI_CHAR,nelem,data,s); + } + + inline int recv(int nelem,float *data,MPI_Status &s=MPIcomm::defstat){ + return recv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_FLOAT,nelem,data,s); + } + inline int recv(int nelem,double *data,MPI_Status &s=MPIcomm::defstat){ + return recv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_DOUBLE,nelem,data,s); + } + inline int recv(int nelem,int *data,MPI_Status &s=MPIcomm::defstat){ + return recv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_INT,nelem,data,s); + } + inline int recv(int nelem,char *data,MPI_Status &s=MPIcomm::defstat){ + return recv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_CHAR,nelem,data,s); + } + // Need support for + // S, B, R sends + // Buffered: Need to preallocate or auto-alloc back buffers. + // Synchronous: Blocks until matching receive posted + // Ready: Error unless matching receive has already been posted. + void setBufferSize(int nbytes){ + if(buffer) buffer->resize(nbytes); + else buffer = new MPIbuffer(nbytes); + } + void setBufferSize(MPI_Datatype type,int nelem){ + // compute size + int elemsize = 8; + if(buffer) buffer->resize(nelem*elemsize); + else buffer = new MPIbuffer(nelem*elemsize); + } + void growBufferSize(int nbytes){ + if(buffer) buffer->grow(nbytes); + else buffer = new MPIbuffer(nbytes); + } + void growBufferSize(MPI_Datatype type,int nelem){ + // compute size + int elemsize = 8; + if(buffer) buffer->grow(nelem*elemsize); + else buffer = new MPIbuffer(nelem*elemsize); + } + inline int bSend(int dest,int tag,MPI_Datatype type,int nelem,void *data){ + // need to get MPI size for the datatype + if(!buffer) growBufferSize(nelem*8); + return MPI_Bsend(data,nelem,type,dest,tag,comm); + } + inline int bSend(int dest,MPI_Datatype type,int nelem,void *data){ + return bSend(dest,default_tag,type,nelem,data); + } + + inline int bSend(int dest,int nelem,float *data){ + return bSend(dest,default_tag,MPI_FLOAT,nelem,data); + } + inline int bSend(int dest,int nelem,double *data){ + return bSend(dest,default_tag,MPI_DOUBLE,nelem,data); + } + inline int bSend(int dest,int nelem,int *data){ + return bSend(dest,default_tag,MPI_INT,nelem,data); + } + inline int bSend(int dest,int nelem,char *data){ + return bSend(dest,default_tag,MPI_CHAR,nelem,data); + } + inline int iSend(int dest,int tag,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + // need to get MPI size for the datatype + return MPI_Isend(data,nelem,type,dest,tag,comm,&req); + } + inline int iSend(int dest,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + return iSend(dest,default_tag,type,nelem,data,req); + } + + inline int iSend(int dest,int tag,int nelem,float *data,MPI_Request &req){ + return iSend(dest,tag,MPI_FLOAT,nelem,data,req); + } + inline int iSend(int dest,int tag,int nelem,double *data,MPI_Request &req){ + return iSend(dest,tag,MPI_DOUBLE,nelem,data,req); + } + inline int iSend(int dest,int tag,int nelem,int *data,MPI_Request &req){ + return iSend(dest,tag,MPI_INT,nelem,data,req); + } + inline int iSend(int dest,int tag,int nelem,char *data,MPI_Request &req){ + return iSend(dest,tag,MPI_CHAR,nelem,data,req); + } + + inline int iSend(int dest,int nelem,float *data,MPI_Request &req){ + return iSend(dest,default_tag,MPI_FLOAT,nelem,data,req); + } + inline int iSend(int dest,int nelem,double *data,MPI_Request &req){ + return iSend(dest,default_tag,MPI_DOUBLE,nelem,data,req); + } + inline int iSend(int dest,int nelem,int *data,MPI_Request &req){ + return iSend(dest,default_tag,MPI_INT,nelem,data,req); + } + inline int iSend(int dest,int nelem,char *data,MPI_Request &req){ + return iSend(dest,default_tag,MPI_CHAR,nelem,data,req); + } + + inline int isSend(int dest,int tag,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + // need to get MPI size for the datatype + return MPI_Issend(data,nelem,type,dest,tag,comm,&req); + } + inline int isSend(int dest,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + return isSend(dest,default_tag,type,nelem,data,req); + } + + inline int isSend(int dest,int tag,int nelem,float *data,MPI_Request &req){ + return isSend(dest,tag,MPI_FLOAT,nelem,data,req); + } + inline int isSend(int dest,int tag,int nelem,double *data,MPI_Request &req){ + return isSend(dest,tag,MPI_DOUBLE,nelem,data,req); + } + inline int isSend(int dest,int tag,int nelem,int *data,MPI_Request &req){ + return isSend(dest,tag,MPI_INT,nelem,data,req); + } + inline int isSend(int dest,int tag,int nelem,char *data,MPI_Request &req){ + return isSend(dest,tag,MPI_CHAR,nelem,data,req); + } + + inline int isSend(int dest,int nelem,float *data,MPI_Request &req){ + return isSend(dest,default_tag,MPI_FLOAT,nelem,data,req); + } + inline int isSend(int dest,int nelem,double *data,MPI_Request &req){ + return isSend(dest,default_tag,MPI_DOUBLE,nelem,data,req); + } + inline int isSend(int dest,int nelem,int *data,MPI_Request &req){ + return isSend(dest,default_tag,MPI_INT,nelem,data,req); + } + inline int isSend(int dest,int nelem,char *data,MPI_Request &req){ + return isSend(dest,default_tag,MPI_CHAR,nelem,data,req); + } + + inline int ibSend(int dest,int tag,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + // need to get MPI size for the datatype + if(!buffer) growBufferSize(nelem*8); + return MPI_Ibsend(data,nelem,type,dest,tag,comm,&req); + } + inline int ibSend(int dest,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + return ibSend(dest,default_tag,type,nelem,data,req); + } + inline int iRecv(int src,int tag,MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + return MPI_Irecv(data,nelem,type,src,tag,comm,&req); + } + inline int iRecv(MPI_Datatype type,int nelem,void *data,MPI_Request &req){ + return iRecv(MPI_ANY_SOURCE,MPI_ANY_TAG,type,nelem,data,req); + } + + inline int iRecv(int src, int tag, int nelem,float *data,MPI_Request &req){ + return iRecv(src,tag,MPI_FLOAT,nelem,data,req); + } + inline int iRecv(int src, int tag, int nelem,double *data,MPI_Request &req){ + return iRecv(src,tag,MPI_DOUBLE,nelem,data,req); + } + inline int iRecv(int src, int tag, int nelem,int *data,MPI_Request &req){ + return iRecv(src,tag,MPI_INT,nelem,data,req); + } + inline int iRecv(int src, int tag, int nelem,char *data,MPI_Request &req){ + return iRecv(src,tag,MPI_CHAR,nelem,data,req); + } + + inline int iRecv(int nelem,float *data,MPI_Request &req){ + return iRecv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_FLOAT,nelem,data,req); + } + inline int iRecv(int nelem,double *data,MPI_Request &req){ + return iRecv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_DOUBLE,nelem,data,req); + } + inline int iRecv(int nelem,int *data,MPI_Request &req){ + return iRecv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_INT,nelem,data,req); + } + inline int iRecv(int nelem,char *data,MPI_Request &req){ + return iRecv(MPI_ANY_SOURCE,MPI_ANY_TAG,MPI_CHAR,nelem,data,req); + } + // waiting routines + int wait(MPI_Request &req,MPI_Status &stat){ + return MPI_Wait(&req,&stat); + } + int test(MPI_Request &req,MPI_Status &stat,int &flag){ + return MPI_Test(&req,&flag,&stat); + } + int requestFree(MPI_Request &req){ + return MPI_Request_free(&req); + } + int waitAny(int nrequests,MPI_Request *requestarray,int &completed,MPI_Status &stat){ + return MPI_Waitany(nrequests,requestarray,&completed,&stat); + } + int waitAll(int nreq, MPI_Request *reqarray,MPI_Status *statarray){ + return MPI_Waitall(nreq,reqarray,statarray); + } + int probe(int source,int tag,MPI_Status &stat){ + return MPI_Probe(source,tag,comm,&stat); + } + int probe(int &flag,MPI_Status &stat){ + return MPI_Probe(MPI_ANY_SOURCE,MPI_ANY_TAG,comm,&stat); + } + int iProbe(int source,int tag,int &flag,MPI_Status &stat){ + return MPI_Iprobe(source,tag,comm,&flag,&stat); + } + int iProbe(int &flag,MPI_Status &stat){ + return MPI_Iprobe(MPI_ANY_SOURCE,MPI_ANY_TAG,comm,&flag,&stat); + } + //-collective comm-- + int gather(int root,MPI_Datatype type,int localnelem,void *senddata,void *recvdata){ + return MPI_Gather(senddata,localnelem,type,recvdata,localnelem,type,root,comm); + } + + int gather(int root,int localnelem,float *senddata,float *recvdata){ + return MPI_Gather(senddata,localnelem,MPI_FLOAT,recvdata,localnelem,MPI_FLOAT,root,comm); + } + int gather(int root,int localnelem,double *senddata,double *recvdata){ + return MPI_Gather(senddata,localnelem,MPI_DOUBLE,recvdata,localnelem,MPI_DOUBLE,root,comm); + } + int gather(int root,int localnelem,int *senddata,int *recvdata){ + return MPI_Gather(senddata,localnelem,MPI_INT,recvdata,localnelem,MPI_INT,root,comm); + } + int gather(int root,int localnelem,char *senddata,char *recvdata){ + return MPI_Gather(senddata,localnelem,MPI_CHAR,recvdata,localnelem,MPI_CHAR,root,comm); + } + + int gatherv(int root,MPI_Datatype type, + int localnelem,int *globalnelem,int *displacements, + void *senddata,void *recvdata){ + return MPI_Gatherv(senddata,localnelem,type, + recvdata,globalnelem,displacements,type,root,comm); + } + int allgather(MPI_Datatype type,int nelem,void *senddata,void *recvdata){ + return MPI_Allgather(senddata,nelem,type,recvdata,nelem,type,comm); + } + int alltoall(MPI_Datatype type,int nelem,void *senddata,void *recvdata){ + return MPI_Alltoall(senddata,nelem,type,recvdata,nelem,type,comm); + } + int scatter(int root,MPI_Datatype type,int localnelem,void *senddata,void *recvdata){ + return MPI_Scatter(senddata,localnelem,type,recvdata,localnelem,type,root,comm); + } + int scatter(int root,int localnelem,float *senddata,float *recvdata){ + return MPI_Scatter(senddata,localnelem,MPI_FLOAT,recvdata,localnelem,MPI_FLOAT,root,comm); + } + int scatter(int root,int localnelem,double *senddata,double *recvdata){ + return MPI_Scatter(senddata,localnelem,MPI_DOUBLE,recvdata,localnelem,MPI_DOUBLE,root,comm); + } + int scatter(int root,int localnelem,int *senddata,int *recvdata){ + return MPI_Scatter(senddata,localnelem,MPI_INT,recvdata,localnelem,MPI_INT,root,comm); + } + int scatter(int root,int localnelem,char *senddata,char *recvdata){ + return MPI_Scatter(senddata,localnelem,MPI_CHAR,recvdata,localnelem,MPI_CHAR,root,comm); + } + int scatterv(int root,MPI_Datatype type, + int localnelem,int *globalnelem,int *displacements, + void *senddata,void *recvdata){ + return MPI_Scatterv(senddata,globalnelem,displacements,type, + recvdata,localnelem,type,root,comm); + } + void print(char *s){ + for(int i=0,last=numProcs();i SphereList; + sphere *s; + SphereList.reset(); + while(s=SphereList.getNext()) + s->visible=1; +------------------------------------------------------------*/ +// #include +// #include +// #include +// #include "NewString.H" + +#define FOREACH(item,list) list.reset(); while(item=list.getNext()) +#define PFOREACH(item,list) list->reset(); while(item=list->getNext()) + +template +class OrderedList +{ + class LLink + { + public: + T data; + LLink *next,*prev; + LLink(T d,LLink *nxt,LLink *prv=0): + data(d),next(nxt),prev(prv) + { + if(nxt) + nxt->prev=this; + if(prv) + prv->next=this; + } + ~LLink() + { + if(prev) + prev->next=next; + if(next) + next->prev=prev; + } + }; + LLink *head,*current,*tail; + int size; +public: + T nullentry; + OrderedList():head(0),size(0),current(0),nullentry(0){} + OrderedList(OrderedList &src):head(0),size(0),current(0),nullentry(0){ + T elem; + FOREACH(elem,src) + this->add(elem); + } + ~OrderedList(){ + while(head) { + LLink *tmp=head->next; + delete head; + head=tmp; + } + } + void add(T data) + { + head=new LLink(data,head); + size++; + } + inline void addToHead(T data){add(data);} + void addToTail(T data){ + // Whaaaaaa! Totally Bogus Man!! + // This type aint complete!!! + } + void insertAfterCurrent(T data){ + if(!current || !current->next) + addToTail(data); + else + current=new LLink(data,current->next,current); + } + void insertBeforeCurrent(T data) { + if(!current) + addToTail(data); + else{ + if(!current->prev) + add(data); + else + new LLink(data,current,current->prev); + } + } + void remove(T data) + { + for(LLink *tmp=head;tmp;tmp=tmp->next) { + if(tmp->data==data){ + if(tmp==head) head=tmp->next; + if(tmp==current) current=tmp->next; + delete tmp; + size--; + } + } + } + void reset() { current=head; } + T getNext() { + T rval; + if(!current) return nullentry; + rval=current->data; + current=current->next; + return rval; + } + inline int getSize(){return size;} + OrderedList &operator=(OrderedList &src){ + if(this==&src) return *this; + T elem; + FOREACH(elem,src) + this->add(elem); + return *this; + } +}; + +#endif // __ORDEREDLIST__TMPL_ diff --git a/src/Reader.cc b/src/Reader.cc new file mode 100644 index 0000000..b243113 --- /dev/null +++ b/src/Reader.cc @@ -0,0 +1,126 @@ +#include +#include +#include "Reader.hh" + +AttribInfoGroup::AttribInfoGroup(IOdataset *ds):dataset(ds){ + nilattrib.name[0]='\0'; + nilattrib.datatype=IObase::Error; + nilattrib.nelements=0; +} + +AttributeInfo &AttribInfoGroup::operator[](char *name){ + for(int i=0;ireadAttribute(index,data); +} + +void IOdataset::update(){ + int i; + // read values + file.seek(index); + file.readInfo(datatype,rank,dims); + typesize=IObase::sizeOf(datatype); + for(i=0,nelements=1;i attribs; + IOdataset *dataset; +public: + AttributeInfo nilattrib; + AttribInfoGroup(IOdataset *ds); + ~AttribInfoGroup(){/*puts("Delete AttribInfoGroup");*/ } + inline void setSize(int sz) { + attribs.setSize(sz); + } + inline int getSize() { + return attribs.getSize(); + } + inline AttributeInfo &operator[](int index){ + attribs[index].index=index; + attribs[index].dataset = dataset; + return attribs[index]; + } + AttributeInfo &operator[](char *name); + AttribInfoGroup(AttribInfoGroup &src); + AttribInfoGroup &operator=(AttribInfoGroup &src); +}; + +class IOdataset { + IObase &file; + void update(); +public: + int index; + int rank; // should put in constructor for const + int dims[5]; + long nbytes; + long nelements; + IObase::DataType datatype; + int typesize; + + + FlexArray annotation; + int nannotations; + //FlexArray attribute; + AttribInfoGroup attribute; + int nattributes; + + IOdataset(IObase &infile,int idx); + IOdataset(IOdataset &src); + ~IOdataset(){/*puts("delete IOdataset");*/} + IOdataset &operator=(IOdataset &src); + int readAttribute(int index,void *data); + int attributeIndex(char *name); + int read(void *data); +}; + +class Reader { + IObase &file; +public: + int ndatasets; + Reader(IObase &infile):file(infile){ + ndatasets=file.nDatasets(); + } + ~Reader(){/*puts("Delete Reader");*/} + inline IOdataset operator[](int index){ + IOdataset ds(file,index); // to satisfy GCC 2.95-2 + return ds; + } +}; + +#endif diff --git a/src/SampleAmrReader.cc b/src/SampleAmrReader.cc new file mode 100644 index 0000000..ea2b51b --- /dev/null +++ b/src/SampleAmrReader.cc @@ -0,0 +1,74 @@ +#include +#include +#include +#include "AmrFileReader.hh" + +int main(int argc,char *argv[]){ + IEEEIO *file; + AmrFileReader *amrfile; + + if (argc < 2) { + fprintf(stderr,"Usage: SampleAmrReader AMRfile\n"); + exit(0); + } + + printf("Open the file named %s\n\n",argv[1]); + file = new IEEEIO(argv[1],IObase::Read); + + if (!file->isValid()) { + fprintf(stderr,"Couldn't open %s for reading\n",argv[1]); + exit(0); + } + + printf("Now we put the file into an AMR parsing framework\n\n"); + amrfile = new AmrFileReader(*file); + + printf("Number of Levels = %u\n\n",amrfile->nLevels()); + + int min,max; + amrfile->getTimeRange(min,max); + + printf("The time range of AMR data in this file\n (in terms of finest-level-of-resolution timesteps) = %u:%u\n\n",min,max); + printf("Lets tell the driver to load up all of the grids for the first timestep\n\n"); + + amrfile->showAllLevels(); + amrfile->setTime(min); + + printf("========================> ActiveGrids are (all levels)...\n"); + amrfile->printActiveGrids(); + // printf("========================> Grid Info is...\n"); + // amrfile->printGridInfo(); + + printf("\nLet's hide level %d\n",amrfile->nLevels() - 2); + amrfile->hideLevel(amrfile->nLevels() - 2); + printf("Let's hide level %d\n",amrfile->nLevels() - 1); + amrfile->hideLevel(amrfile->nLevels() - 1); + printf("Tell the driver to load up the active grids for the first timestep\n"); + amrfile->setTime(min); + printf("========================> ActiveGrids are (all but finest level)...\n"); + amrfile->printActiveGrids(); + + printf("\nActually load the grid data into %u standard arrays\n",amrfile->getNumGrids()); + AmrGrid *grids = new AmrGrid[amrfile->getNumGrids()]; + amrfile->getGrids(grids); // that loaded all of the data + + printf("We read %u grids\n\n",amrfile->getNumGrids()); + + printf("Let's grab the grids into a flexarray (a dynamically resizable array)\n"); + FlexArray gridarray; + amrfile->getGrids(gridarray); + + printf("We read %u grids\n",gridarray.getSize()); + + // You can access individual grids with gridarray[] + + // Take a look at AmrGrid.hh to see whats in the datastruct + // or take a look at docs + // http://infinite-entropy.lbl.gov/FlexIO/AmrGrid.html + + // To get rid of the data associated with these grids we can do a + // amrfile->setDataLoadingOff(); // this deletes the data arrays + // amrfile->setDataLoadingOn(); // reloads the data arrays from disk + + return 1; +} diff --git a/src/SlaveIO.cc b/src/SlaveIO.cc new file mode 100644 index 0000000..bb14b09 --- /dev/null +++ b/src/SlaveIO.cc @@ -0,0 +1,169 @@ +#include "SlaveIO.hh" +#ifndef WIN32 +#include +#include +#include +#include +#else +#include +#endif + +#include +#include +#include +#include + +#ifdef T3E +#include +#endif + +#ifdef SGI +#include +#endif + +// Win32/Solaris lseek crap... +#if defined(WIN32) || defined(SOLARIS) || defined(sun) +#define L_INCR SEEK_CUR +#ifndef L_SET // for that wanky Solaris compiler +#define L_SET SEEK_SET +#endif +#define L_XTND SEEK_END +#endif +// T3E lseek crap... +#ifdef T3E // I'm a T3E and I ignore ANSI/Posix standards +#define L_INCR SEEK_CUR +#define L_SET SEEK_SET +#define L_XTND SEEK_END +#endif + +SlaveIO::SlaveIO():fid(-1){} +SlaveIO::SlaveIO(char *name){ + fid = open(name,O_RDWR,0644); // should fail if file doesn't exist +} +SlaveIO::~SlaveIO(){ + if(fid>=0) close(fid); + fid=-1; // closed state +} +int SlaveIO::writeTo(void *data,Long8 len,Long8 offset){ + lseek(fid,offset,L_SET); // seek from beginning of file + return write(fid,data,len); +} + +#ifdef SGI +SGISlaveIO::SGISlaveIO(char *name):SlaveIO(name){} +// use writepos elemental operation rather than separate lseek +int SGISlaveIO::writeTo(void *data,Long8 len,Long8 offset){ + return pwrite64(fid,data,len,offset); +} + +AIOSlaveIO::AIOSlaveIO(char *name):SlaveIO(name),write_complete(0){ + // init AIO (check global var for that) +} +AIOSlaveIO::~AIOSlaveIO(){ + // flush file first (make sure it is flushed) + if(fid>=0) close(fid); + fid=-1; +} +int AIOSlaveIO::writeTo(void *data,Long8 len, Long8 offset){ + return 1; +} +void AIOSlaveIO::sync(){ + // do wait on the file operation +} + +#endif // SGI + +#ifdef T3E + +FFSlaveIO::FFSlaveIO(char *name,char *optionstring){ + struct ffsw ffopens_status; + + fid = ffopens(name,O_RDWR,0644,0, 0, &ffopens_status,optionstring); +} +FFSlaveIO::FFSlaveIO(char *name,int bufsize,int numbufs){ + char optionstring[256]; + int cblks; + long cbits; + struct statfs statfs_info; + struct ffsw ffopens_status; + sprintf(optionstring,"bufa.bufsize=%u.num_buffers=%u",bufsize,numbufs); + fid = ffopens(name,O_RDWR,0644,0, 0, &ffopens_status,optionstring); + ffwrite(fid,optionstring,255); // bogus write to testfile + ffclose(name); // now close it + statfs(name,&statfs_info,sizeof(statfs_info),0); + cbits=0; + cbits|=(1<<24); + cbits|=(1<<06); + cbits|=(1<<26); + cbits|=(1<<23); + cblks=100; + fid = ffopens(name,O_WRONLY|O_PLACE,O_IWRITE|O_IREAD, + cbits,cblks,&ffopens_status,LAYERS); // ? + system("setf -n32768b:128b -c -p 24:06:23:26 bla"); // ? +} +FFSlaveIO::FFSlaveIO(char *name){ + struct ffsw ffopens_status; + + fid = ffopens(name,O_RDWR,0644,0, 0, &ffopens_status, "bufa.bufsize=256.num_buffers=4"); +} +FFSlaveIO::~FFSlaveIO(){ + if(fid>=0) ffclose(fid); + fid=-1; // closed state +} +int FFSlaveIO::writeTo(void *data,Long8 len,Long8 offset){ + ffseek(fid,offset,L_SET); // seek from beginning of file + return ffwrite(fid,data,len); +} + +#endif // T3E + +#ifdef SGI + +DirectSlaveIO::DirectSlaveIO(char *name):SlaveIO(name){ + struct dioattr dio; + dfid = open(name,O_WRONLY|O_DIRECT,0644); // unbuffered writes + fcntl(dfid,F_DIOINFO,&dio); + blocksize = dio.d_miniosz; + maxiosize = dio.d_maxiosz; + memoryalignment = dio.d_mem; + diobuffersize=8*blocksize; + diobuffer = (char*)memalign(memoryalignment,8*blocksize); +} + +DirectSlaveIO::~DirectSlaveIO(){ + if(fid>=0) close(fid); + fid=-1; // closed state + if(dfid>=0) close(dfid); + dfid=-1; +} +int DirectSlaveIO::writeTo(void *vdata,Long8 len,Long8 offset){ + char *data = (char *)vdata; + Long8 startlen,midlen,endlen; + Long8 startoffset,midoffset,endoffset; + + // compute starts based on blocksize + startlen = offset % blocksize; // so now we have the start remainder + endlen = (offset+len) % blocksize; // computed end-remainder + midlen = len - (startlen+endlen); + + // compute offsets + startoffset = offset; + midoffset = startoffset + startlen; + endoffset = midoffset + midlen; + + // should probably use aio for the end-writes + pwrite64(fid,data,startlen,startoffset); // should use write + // try this with AIO as well perhaps + lseek(dfid,midoffset,L_SET); + for(register int off=0;offmidlen)?midlen-off:diobuffersize; + memcpy(diobuffer,data+off+startlen,sz); + write(dfid,data+startlen,sz); // write direct and unbuffered + } + // now here we use the blockbuffer to manage writing of + // the non-aligned portions of the data + pwrite64(fid,data+startlen+midlen,endlen,endoffset); + // block at the end if AIO +} + +#endif // SGI diff --git a/src/SlaveIO.hh b/src/SlaveIO.hh new file mode 100644 index 0000000..83665de --- /dev/null +++ b/src/SlaveIO.hh @@ -0,0 +1,60 @@ +#ifndef __SLAVEIO_HH_ +#define __SLAVEIO_HH_ +#include + +class SlaveIO { +protected: + int fid; +public: + SlaveIO(); + SlaveIO(char *name); + virtual ~SlaveIO(); + virtual int writeTo(void *data,Long8 len,Long8 offset); +}; + +#ifdef SGI +class SGISlaveIO : public SlaveIO { +public: + SGISlaveIO(char *name); + // use writepos elemental operation rather than separate lseek + virtual int writeTo(void *data,Long8 len,Long8 offset); +}; + +class AIOSlaveIO : public SlaveIO { + int write_complete; +public: + AIOSlaveIO(char *name); + ~AIOSlaveIO(); + virtual int writeTo(void *data,Long8 len, Long8 offset); + void sync(); +}; + +#endif // SGI + +#ifdef T3E +class FFSlaveIO : public SlaveIO { +public: + FFSlaveIO(char *name,char *optionstring); + FFSlaveIO(char *name,int bufsize,int numbufs); + FFSlaveIO(char *name); + virtual ~FFSlaveIO(); + virtual int writeTo(void *data,Long8 len,Long8 offset); +}; +#endif // T3E + +#ifdef SGI + +class DirectSlaveIO : public SlaveIO { + int dfid; + int blocksize,maxiosize,memoryalignment; + char *diobuffer; + int diobuffersize; +public: + DirectSlaveIO(char *name); + virtual ~DirectSlaveIO(); + virtual int writeTo(void *data,Long8 len,Long8 offset); +}; + +#endif // SGI + +#endif diff --git a/src/SockIOreader.cc b/src/SockIOreader.cc new file mode 100644 index 0000000..392d28a --- /dev/null +++ b/src/SockIOreader.cc @@ -0,0 +1,346 @@ +#include +#include +#include +#include +#include +#include +#include +#include "FlexArrayTmpl.H" + +#include "SockIOreader.hh" + +#if defined(T3E) || defined(__hpux) +#define SIGNAL_CAST +#else +#define SIGNAL_CAST (SIG_PF) +#endif + +// Globals +FlexArray sock_io_readers; +void IOsigHandler(int sig); +void reaper(int sig); + +// enable signals (needs a refcount) +class SigMgr { + static int sigrefcount; + static int nwatchers; +public: + static void AddObserver(){ + nwatchers++; + } + static void RemoveObserver(){ + nwatchers--; + // should check refcount status change + } + static void SigOn(){ + //puts("sigOn"); + sigrefcount++; + if(sigrefcount>nwatchers){ + // error + sigrefcount=nwatchers; + puts("SigMgr: Error... the Signal refcount is > numwatchers"); + puts("correcting"); + } + if(sigrefcount==nwatchers){ + // call the handlertest just in case + //IOsigHandler((int)SIGIO); + for(int i=0; isigHandler(SIGIO); + } + signal(SIGIO,SIGNAL_CAST IOsigHandler); // reenable the signal handler + signal(SIGURG,SIGNAL_CAST IOsigHandler);// reenable the signal handler + } + } + // disable signals until elemental IO operation completes + static void SigOff(){ + //puts("sigOff"); + sigrefcount--; + if(sigrefcount<0){ + puts("SigMgr::SigOff(): Signal refcount < 0... correcting"); + sigrefcount=0; + } + signal(SIGIO,SIG_DFL); // prevent double-interrupt + signal(SIGURG,SIG_DFL); + } +}; + +int SigMgr::sigrefcount=0; +int SigMgr::nwatchers=0; + +// If any IO event occurs, this will call handlers for all availible SockIOreaders +// to see if they have an event to take care of. +void IOsigHandler(int sig){ + //puts("SigHandler: IO Interrupt"); + SigMgr::SigOff(); + // So here we look at the global list of SockIOreaders and pass the event on + for(int i=0; isigHandler(sig); + } + SigMgr::SigOn(); +} + +// This gobbles up zombie children... kind of like Night of the Living Dead +void reaper(int sig){ + puts("Reaper: Child Interrupt"); +#ifndef T3E + // Eat dead children :b + struct rusage status; + int statptr; + while(wait3(&statptr,WNOHANG,&status)>=0) {} // get all the deadsters +#endif + + signal(SIGCHLD,SIGNAL_CAST reaper); // reenable the signal handler +} + +// Alarm handler to escape from hanging socket reads (crash in mid-send) +jmp_buf senv,tenv; +void timeout(int sig){ + signal(SIGALRM,SIGNAL_CAST timeout); // reset the handler + longjmp(tenv,1); // jump to the error recovery vector +} + +/* +void InterruptRecovery(int sig){ + SockIOwriter::halt(); // kill app on first opportunity + if(SockIOwriter::sendInProgress()>0){ + signal(SIGALRM,SIGNAL_CAST timeout); // reset the handler + longjmp(tenv,1); + } + else + exit(0); +} +*/ + +// kludge +int SockIOreader::blockingRead(void *buffer,int size){ + int nremaining,nreceived; + if(!connected_client) return 0; + // read in 1k blocks (perhaps have 15-30sec timeout) + // should be able to set variable blocksize + for(nremaining=size;nremaining>0;nremaining-=nreceived) + { + nreceived=connected_client->read((char*)buffer,nremaining); + if (nreceived<1) // read error + return size-nremaining; + } + return size; // can return alt value if timeout occurs +} +//======================================================================================= + +void SockIOreader::sigHandler(int sig){ + // do a select... + RawPort *port = master_mux.select(); + if(port){ + if(connected_client) + //pending++; // (if we didn't prefer new clients....) but.... + delete connected_client; // has preference for new clients!! + // pref for new clients is good for error recovery. (eg. death of client program) + puts("\nOpen New Client Port\n"); + connected_client = ServerPort.accept(); + mux.addInport(connected_client); // add to select mux list + // close and reopent the file trunc + delete scratchfile; + scratchfile=new IEEEIO(scratchfilename,IObase::Write); + delete scratchfile; + scratchfile=new IEEEIO(scratchfilename,IObase::Append); // kludge to purge file + } + scratchfile->seek(scratchfile->nDatasets()-1); + while(mux.select()>0){ + int dims[5]; + char name[128]; + int bufsize; + void *current_buffer; + blockingRead(¤t_rec,sizeof(RecordHdr)); + switch(current_rec.recordtype){ + case 1: // data record + blockingRead(¤t_data_rec,sizeof(DataRecordHdr)); + blockingRead(dims,sizeof(int)*current_data_rec.rank); + bufsize=current_data_rec.datasize; + break; + case 2: // annotation record + // do nothing for now. + bufsize=current_rec.recordsize; + break; + case 3: // attribrecord + blockingRead(¤t_att_rec,sizeof(AttributeRecordHdr)); + blockingRead(name,current_att_rec.namesize); + bufsize=current_att_rec.datasize; + break; + } + current_buffer = new char[bufsize]; + blockingRead(current_buffer,bufsize); + // now commit it to disk + switch(current_rec.recordtype){ + case 1: + scratchfile->write(IObase::Int2DataType(current_data_rec.numbertype), + current_data_rec.rank, + dims, + current_buffer); + break; + case 2: + scratchfile->writeAnnotation((char*)current_buffer); + break; + case 3: + scratchfile->writeAttribute(name,IObase::Int2DataType(current_att_rec.numbertype), + bufsize/IObase::sizeOf(IObase::Int2DataType(current_att_rec.numbertype)), + current_buffer); + break; + } + delete current_buffer; + current_buffer=0; + } + if (current_ds > 0) + scratchfile->seek(current_ds); +} + +//------------------------core stuff..................... +SockIOreader::SockIOreader(CONST char *scratchfilenm,int port):IObase(scratchfilenm,IObase::Read), + scratchfile(0),ServerPort(port), + pending(0),connected_client(0){ + current_ds = -1; + strcpy(scratchfilename,scratchfilenm); + scratchfile=new IEEEIO(scratchfilename,IObase::Write); + delete scratchfile;// kludge to purge file + scratchfile=new IEEEIO(scratchfilename,IObase::Append); + // sockport is open, now set up the select + fprintf(stderr,"ServerPort validity=%u\n",ServerPort.isAlive()); + master_mux.addInport(&ServerPort); + // the master mux should always return immediately + // (a non-blocking select()) + master_mux.setTimeout(0,0); // seconds and microseconds =0 + mux.setTimeout(0,0); + // set signals for capturing events + sock_io_readers.append(this); // append to handler list + SigMgr::AddObserver(); + puts("Signals On"); + SigMgr::SigOn(); + signal(SIGCHLD,SIGNAL_CAST reaper); // reenable the signal reaper handler + puts("construction completed"); +} + +SockIOreader::SockIOreader(CONST char *scratchfilenm,int port,int windowsize): + IObase(scratchfilenm,IObase::Read), + scratchfile(0),ServerPort(port,windowsize), + pending(0),connected_client(0){ + current_ds = -1; + strcpy(scratchfilename,scratchfilenm); + scratchfile=new IEEEIO(scratchfilename,IObase::Write); + delete scratchfile;// kludge to purge file + scratchfile=new IEEEIO(scratchfilename,IObase::Append); + // sockport is open, now set up the select + fprintf(stderr,"ServerPort validity=%u\n",ServerPort.isAlive()); + master_mux.addInport(&ServerPort); + // the master mux should always return immediately + // (a non-blocking select()) + master_mux.setTimeout(0,0); // seconds and microseconds =0 + mux.setTimeout(0,0); + // set signals for capturing events + sock_io_readers.append(this); // append to handler list + SigMgr::AddObserver(); + puts("Signals On"); + SigMgr::SigOn(); + signal(SIGCHLD,SIGNAL_CAST reaper); // reenable the signal reaper handler + puts("construction completed"); +} + +SockIOreader::~SockIOreader(){ + SigMgr::SigOff(); + SigMgr::RemoveObserver(); + // shut all of the sockets down + if(connected_client) + delete connected_client; // need to remove from mux list + connected_client=0; +} + +// should check server status too +int SockIOreader::isValid() { + if(scratchfile && connected_client) return 1; + return 0; +} + +// could use overloading to differentiate type here... (but I'm going simple) +int SockIOreader::readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims){ + // just hand this off to the datafile (and hope that APPEND mode works correctly) + SigMgr::SigOff(); + int retval = scratchfile->readInfo(typeID,rank,dims,maxdims); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::read(void *data){ + SigMgr::SigOff(); + int retval = scratchfile->read(data); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::seek(int dataset_index){ + SigMgr::SigOff(); + current_ds=scratchfile->seek(dataset_index); + int retval = current_ds; + SigMgr::SigOn(); + return retval; +} +int SockIOreader::nDatasets(){ + SigMgr::SigOff(); + int retval = scratchfile->nDatasets(); // must not interrupt these operations... + SigMgr::SigOn(); + return retval; +} +int SockIOreader::readAnnotationInfo(int number,int &length){ // returns length (-1 if none left) + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readAnnotationInfo(number,length); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::readAnnotation(int number,char *annotation,int maxsize){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readAnnotation(number,annotation,maxsize); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::nAnnotations(){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->nAnnotations(); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readAttributeInfo(number,name,typeID,nelem,maxnamelen); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem){ // returns number + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readAttributeInfo(name,typeID,nelem); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::readAttribute(int number,void *data){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readAttribute(number,data); + SigMgr::SigOn(); + return retval; +} +int SockIOreader::nAttributes(){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->nAttributes(); + SigMgr::SigOn(); + return retval; +} +//-----------------Chunking Utilities.................. +int SockIOreader::readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data){ + SigMgr::SigOff(); + scratchfile->seek(current_ds); + int retval = scratchfile->readChunk(chunkdims,chunkorigin,data); + SigMgr::SigOn(); + return retval; +} diff --git a/src/SockIOreader.hh b/src/SockIOreader.hh new file mode 100644 index 0000000..19f16bf --- /dev/null +++ b/src/SockIOreader.hh @@ -0,0 +1,141 @@ +#ifndef __SOCKIOREADER_HH_ +#define __SOCKIOREADER_HH_ + +#include "Arch.h" +#include "IO.hh" +#include "IEEEIO.hh" +#include "RawTCP.H" +#include "PortMux.H" + +/*========================================================================= +class: SockIOreader +description: Implements IEEEIO IO interface described in + http://bach.ncsa.uiuc.edu/IEEEIO over a socket connection. + The interface is read-only. This is the client and the SockIOwriter + is a server which sends data out to the SockIOreader from the + application. All data is cached in an IEEEIO file on the client + end (this side) for rapid local access by the client application. + +Problems: The background IO methods are kludgy at best. Currently it + depends on SigIO in order to determine when some new data is availible + on the socket. However, it is very difficult to demultiplex that + signal when you have more than one instance of SockIOreader active. + + Need a garaunteed method to determine if a client has dropped it connection. + A dropped connection can cause a lockup if it occurs during a blocking read. + This needs to have a SigALRM in order to recover from such errors. +===========================================================================*/ +//void IOsigHandler(int sig); // prototype + +class SockIOreader : public IObase { + + // The following data structures come straight out of IEEEIO and + // are necessary for interpreting the data coming in through the + // socket connection. Other than that, you can completely ignore them + // or refer directly to the docs in IEEEIO.hh if you really feel the + // need to understand what is happening here. + enum RecordType {DataRecord=1,AnnotationRecord,AttributeRecord}; + +#ifdef __hpux +// silly HPUX compiler doesn't allow FileHdr access to btorder... +public: +#endif + + // Structure for determining the native byte-order of data stored in the file + union btorder { + char c[4]; // write as int, read as int + int i; + }; + + // File header describes how many data records are in the file and what the + // version of the IEEEIO wrote this data. + struct FileHdr { + // do magic twice so we can figure out which byte-order + // the current machine is in addition (without hardcoding) in + // addition to which byte order the file is in + btorder magic; + btorder byteorder; + Long ndatasets; + short majorversion; + short minorversion; + }; + + // At the head of each data or attribute record. Identifies the type of + // record and how large it is so that it can be skipped if it doesn't contain + // relevant data. + struct RecordHdr { + int recordtype; + Long recordsize; + int sequenceID; + }; + + // This immediately follows a RecordHeader if the record contains raw data. + // this stores the number of dimensions and the datatype of the record + struct DataRecordHdr { + Long datasize; + int numbertype; + int rank; + }; + + // The immediately follows the RecordHeader if the record contains a + // NetCDF attribute. It stores the datatype, name and datasize of the + // attribute vector. + struct AttributeRecordHdr { + Long datasize; + int numbertype; + int namesize; // attributes are named + }; + + char scratchfilename[256]; // name of scratchfile in which to store the IEEEIO data + IEEEIO *scratchfile; // IEEEIO file descriptor for the scratch file + FastTCPserver ServerPort; // Server port from which connections from SockIOwriters are accept()'ed + RawTCPport *connected_client; // Only one client can be attached at a time. + //**** State information for IEEEIO management + RecordHdr current_rec; + DataRecordHdr current_data_rec; + AttributeRecordHdr current_att_rec; + //**** master_mux is the serverport (accept calls) and mux is the connected ports (new data) + PortMux master_mux,mux; + int n_complete_ds,current_ds,last_ds; // number of completely received datasets + current&last + int pending; // Flag if a new dataset transfer is currently in progress in the background. + + // Make this functionality inacessible since this class is read-only. + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data){return 0;} + virtual int writeAnnotation(CONST char *annotation){return 0;} + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data){return 0;} + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){return 0;} + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims){return 0;} + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data){return 0;} + virtual int writeStream(void *data,int length){return 0;} +protected: + int blockingRead(void *buffer,int size); // kludge + //static void halt(){} + //static int sendInProgress(){return 0;} +public: + void sigHandler(int sig); + friend void IOsigHandler(int *handler); // give the sighandler internal access to sigHandler(); + //------------------------core stuff..................... + SockIOreader(CONST char *scratchfilenm,int port); + SockIOreader(CONST char *scratchfilenm,int port,int tcpwindowsize); + virtual ~SockIOreader(); + // should check server status too + virtual int isValid(); + // could use overloading to differentiate type here... (but I'm going simple) + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3); + virtual int read(void *data); + virtual int seek(int dataset_index); + virtual int nDatasets(); + virtual int readAnnotationInfo(int number,int &length); + virtual int readAnnotation(int number,char *annotation,int maxsize=128); + virtual int nAnnotations(); + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128); + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem); + virtual int readAttribute(int number,void *data); + virtual int nAttributes(); + //-----------------Chunking Utilities.................. + //---Not implemented quite yet on server side, but you can read in chunks on client. + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data); + virtual int readStream(void *data,int length){return 0;} +}; + +#endif diff --git a/src/SockIOwriter.cc b/src/SockIOwriter.cc new file mode 100644 index 0000000..c68c557 --- /dev/null +++ b/src/SockIOwriter.cc @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include "SockIOwriter.hh" + +SockIOwriter::SockIOwriter(CONST char *hostname,int port):IObase(hostname,IObase::Write), + clientsock(0),ndatasets(0),datasetnumber(-1){ + //RawTCPclient *clientsock = new RawTCPclient(hostname,port); + clientsock = new RawTCPclient(hostname,port); // One Megabyte window + fprintf(stderr,"ClientSock=%lu\n",(long)clientsock); + // this will block until it connects +} + +SockIOwriter::SockIOwriter(CONST char *hostname,int port,int windowsize):IObase(hostname,IObase::Write), + clientsock(0),ndatasets(0),datasetnumber(-1){ + clientsock = new FastTCPclient(hostname,port,windowsize); // open bigwindow socket + fprintf(stderr,"Open ClientSock=%lu with %u windowsize\n",(long)clientsock,windowsize); +} + +SockIOwriter::~SockIOwriter(){ + delete clientsock; +} + +int SockIOwriter::isValid(){ + if(clientsock && clientsock->isAlive()) + return 1; + else + return 0; +} + +// could use overloading to differentiate type here... (but I'm going simple) +int SockIOwriter::write(IObase::DataType typeID,int rank,CONST int *dims,void *data){ + register int i; + Int sdims[5]; + for (i = 0; i < rank ; i++) + sdims[i] = dims[i]; + RecordHdr rec; + DataRecordHdr hdr; + if(!isValid()){ + puts("no valid connection"); + return 0; + } + for(i=0,hdr.datasize=1;igetPortNum()); + fprintf(stderr,"Socket validity=%u\n",clientsock->isAlive()); + int sz = RecordHdr::write(rec, clientsock); + sz = DataRecordHdr::write(hdr, clientsock); + + //clientsock->write((char*)(&rec),sizeof(rec)); + //clientsock->write((char*)(&hdr),sizeof(hdr)); + clientsock->write((char*)sdims,rank*sizeof(Int)); + return clientsock->write((char*)data,hdr.datasize); +} + +int SockIOwriter::writeAnnotation(CONST char *annotation){ + RecordHdr rec; + int stringlen=strlen(annotation)+1; + rec.recordtype=AnnotationRecord; + rec.recordsize=stringlen; + if(datasetnumber>=0) rec.sequenceID=datasetnumber; + else rec.sequenceID=current_rec.sequenceID; + clientsock->write((char*)(&rec),sizeof(RecordHdr)); + return clientsock->write((char*)annotation,stringlen); +} + +// Write a NetCDF attribute across the socket connection +int SockIOwriter::writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data){ + int i; + AttributeRecordHdr attrib; + RecordHdr rec; + int stringlen=strlen(name)+1; + + attrib.datasize=length*sizeOf(typeID); + attrib.namesize=stringlen; + attrib.numbertype=typeID; + rec.recordtype=AttributeRecord; + rec.recordsize=attrib.datasize+attrib.namesize+AttributeRecordHdr::size(); + if(datasetnumber>=0) rec.sequenceID=datasetnumber; + else rec.sequenceID=current_rec.sequenceID; // a kludge for error immunity + +// clientsock->write((char*)(&rec),sizeof(RecordHdr)); +// clientsock->write((char*)(&attrib),sizeof(AttributeRecordHdr)); + + RecordHdr::write(rec, clientsock); + attrib.write(clientsock); + + clientsock->write((char*)name,stringlen); + return clientsock->write((char*)(data),length*sizeOf(typeID)); +} + + diff --git a/src/SockIOwriter.hh b/src/SockIOwriter.hh new file mode 100644 index 0000000..96a6223 --- /dev/null +++ b/src/SockIOwriter.hh @@ -0,0 +1,181 @@ +#ifndef __SOCKIOWRITER_HH_ +#define __SOCKIOWRITER_HH_ + +#include "IO.hh" +#include "Arch.h" +#include "RawTCP.H" +#include "PortMux.H" + +/*==================================================== +class: sockIOwriter +description: This class extends the IO & IEEEIO architecture + to write data across a newtork socket. Please + consult http://bach.ncsa.uiuc.edu/IEEEIO for details + on how IEEEIO works. This interface only works + for *writing* data (write-only interface). + + The writer opens a socket to the destination address + and then ships data to the destination processor + whenever a write occurs. Sending is immediate. + There is no local caching (all caching is on the + client/reader-side). It could be double-buffered but + this would cause problems for MPI jobs on distributed + memory machines like the T3E and SP2. +problems: All sends are in the foreground. This can hurt + application performance, but we can't afford double-buffering + because of the memory limitations of distributed memory machines. + (a background send would require double buffering but we + can't afford the memory to do that on a distributed memory + machine). +======================================================*/ + +class SockIOwriter : public IObase { + enum RecordType {DataRecord=1,AnnotationRecord,AttributeRecord}; + +#ifdef __hpux +// silly HPUX compiler won't give FileHdr access to btorder... +public: +#endif + + union btorder { + char c[4]; // write as int, read as int + Int i; + }; + + struct FileHdr { + // do magic twice so we can figure out which byte-order + // the current machine is in addition (without hardcoding) in + // addition to which byte order the file is in + btorder magic; + btorder byteorder; + Long ndatasets; + short majorversion; + short minorversion; + static int write(FileHdr &rec, RawTCPclient *clientsock){ +#ifdef T3E + // T3E pads structures and Unions (even if embedded in other structures). + // So we can't simply write the entire structure in-place. Must write + // each component of the structure independently. + // do it the stupid way first + // would be smarter to pack buffers really + int r=0; + r+=clientsock->write((char *)(rec.magic.c),4); + r+=clientsock->write((char *)(rec.byteorder.c),4); + r+=clientsock->write((char *)&(rec.ndatasets),4); + // this may be incorrect, but it will work for now + // It assumes the low order bytes will be first to + // be written. + r+=clientsock->write((char *)&(rec.majorversion),2); + r+=clientsock->write((char *)&(rec.minorversion),2); + return r; +#else + // problem if this includes pointers to static methods + // will require an extra degree of inheritance. (inherit + // from a base structure. + return clientsock->write((char *)&rec,sizeof(FileHdr)); +#endif + } + }; + + struct RecordHdr { + Int recordtype; + Long recordsize; + Int sequenceID; + + static int write(RecordHdr &rec,RawTCPclient *clientsock){ +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + int r=0; + r+=clientsock->write((char *)&(rec.recordtype),4); + r+=clientsock->write((char *)&(rec.recordsize),4); + r+=clientsock->write((char *)&(rec.sequenceID),4); + return r; +#else + return clientsock->write((char *)&rec,sizeof(RecordHdr)); +#endif + } + }; + + struct DataRecordHdr { + Long datasize; + Int numbertype; + Int rank; + static int write(DataRecordHdr &rec, RawTCPclient *clientsock){ +#ifdef T3E + // do it the stupid way first + // would be smarter to pack buffers really + int r=0; + r+=clientsock->write((char *)&(rec.datasize),4); + r+=clientsock->write((char *)&(rec.numbertype),4); + r+=clientsock->write((char *)&(rec.rank),4); + return r; +#else + return clientsock->write((char *)&rec,sizeof(DataRecordHdr)); +#endif + } + + }; + + struct AttributeRecordHdr { + Long datasize; + Int numbertype; + Int namesize; // attributes are named + + /// Alignment-save write + int write(RawTCPclient *clientsock) + { + /// shouldn't there be some hton() conversion?? + int r = clientsock->write(&datasize , 4); + r+= clientsock->write(&numbertype, 4); + r+= clientsock->write(&namesize , 4); + return r; + } + + static int size() { return 12; } + }; + + virtual int readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims=3){ return 0; } + virtual int read(void *data){ return 0; } + virtual int seek(int dataset_index){ return 0; } + virtual int nDatasets() { return 0; } + virtual int readAnnotationInfo(int number,int &length){ return 0; } // returns length (-1 if none left) + virtual int readAnnotation(int number,char *annotation,int maxsize=128){ return 0; } + virtual int nAnnotations(){ return 0; } // returns number + virtual int readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen=128) + { return 0; } + virtual int readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem){ return 0; } // returns number + virtual int readAttribute(int number,void *data){ return 0; } + virtual int nAttributes(){ return 0; } + virtual int readChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data){ return 0; } + virtual int readStream(void *data,int length){return 0;} + RawTCPclient *clientsock; + int ndatasets,datasetnumber; + RecordHdr current_rec; +public: + //------------------------core stuff..................... + SockIOwriter(CONST char *hostname,int port); + SockIOwriter(CONST char *hostname,int port,int tcpwindowsize); + virtual ~SockIOwriter(); + virtual int isValid(); + // could use overloading to differentiate type here... (but I'm going simple) + virtual int write(IObase::DataType typeID,int rank,CONST int *dims,void *data); + virtual int writeAnnotation(CONST char *annotation); + virtual int writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data); + //-----------------Chunking Utilities.................. + virtual int reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){ + return 0; // this will require a fourth data descriptor type + } + virtual int reserveStream(IObase::DataType typeID,int rank,CONST int *dims){ + return 0; // this will require a fourth data descriptor type + } + virtual int writeChunk(CONST int *chunkdims,CONST int *chunkorigin,void *data){ + // need to fix this + return 0; + } + virtual int writeStream(void *data,int length){return 0;} + + RawTCPclient*TCPclient() const { return clientsock; } +}; + +#endif diff --git a/src/Timer.cc b/src/Timer.cc new file mode 100644 index 0000000..5e4d937 --- /dev/null +++ b/src/Timer.cc @@ -0,0 +1,44 @@ +#include +#include "Timer.hh" +#include +int Timer::start(){ + // struct timezone tz; + if(running) return 0; // already running + running=1; + times(&tm); // set current time + gettimeofday(&tv,0); + return 1; +} + +int Timer::stop(){ + // timezone tz; + tms tmc; // current time + timeval tvc; // current realtime + if(!running) return 0; // already stopped + running=0; + // copy back current time + gettimeofday(&tvc,0); + times(&tmc); + treal += ((double)(tvc.tv_sec - tv.tv_sec) + + ((double)(tvc.tv_usec - tv.tv_usec))/1000000.0L); + tuser += (double)(tmc.tms_utime-tm.tms_utime)/CLK_TCK; + tsystem += (double)(tmc.tms_stime-tm.tms_stime)/CLK_TCK; + return 1; +} + +void Timer::elapsedTimeSeconds(double &system,double &user,double &real){ + int wasrunning=running; + stop(); + system=tsystem; + user=tuser; + real=treal; + if(wasrunning) start(); +} + +void Timer::print(char *preface,FILE *f){ + double s,u,r; + elapsedTimeSeconds(s,u,r); + fprintf(f,"%s: SystemTime=%lfs\tUserTime=%lfs\tRealTime=%lfs\n", + preface,s,u,r); +} + diff --git a/src/Timer.hh b/src/Timer.hh new file mode 100644 index 0000000..e801cf3 --- /dev/null +++ b/src/Timer.hh @@ -0,0 +1,39 @@ +#ifndef __TIMER_HH_ +#define __TIMER_HH_ +#include +#include +#include +#include + +class Timer { + int running; + double treal,tuser,tsystem; + tms tm; + timeval tv; +public: + Timer() { reset(); } + void reset(){ + treal=tuser=tsystem=0; + running=0; + } + int start(); + int stop(); + void elapsedTimeSeconds(double &system,double &user,double &real); + void elapsedTimeSeconds(float &system,float &user,float &real){ + double s,u,r; + elapsedTimeSeconds(s,u,r); + system=s; user=u; real=r; + } + void print(char *preface="",FILE *f=stdout); +}; + +class Counter { + int count; +public: + Counter():count(0){} + void reset() {count = 0;} + int incr(){ return count++;} + int nCount() { return count;} +}; + +#endif diff --git a/src/Vec3f.hh b/src/Vec3f.hh new file mode 100644 index 0000000..c9e58d1 --- /dev/null +++ b/src/Vec3f.hh @@ -0,0 +1,278 @@ +#ifndef __VEC3F_HH_ +#define __VEC3F_HH_ + +#include +#include + + //CAPI:verb SqrDistancePt3 +#define PF_SQUARE(_x) ((_x)*(_x)) +#define PF_MIN2(a,b) ((a) < (b) ? (a) : (b)) +#define PF_MAX2(a,b) ((a) > (b) ? (a) : (b)) +#define PF_MIN3(a,b,c) ((a) < (b) ? PF_MIN2(a,c) : PF_MIN2(b,c)) +#define PF_MAX3(a,b,c) ((a) > (b) ? PF_MAX2(a,c) : PF_MAX2(b,c)) +#define PF_MIN4(a,b,c,d) ((a) < (b) ? PF_MIN3(a,c,d) : PF_MIN3(b,c,d)) +#define PF_MAX4(a,b,c,d) ((a) > (b) ? PF_MAX3(a,c,d) : PF_MAX3(b,c,d)) +#define PF_CLAMP(_x, _lo, _hi) \ + (((_x) < (_lo)) ? (_lo) : (_x) > (_hi) ? (_hi) : (_x)) + +/* + * PF_ABS is faster than calling fabsf + * PF_ABSLT etc are faster than (PF_ABS(x1) < x2) + */ +#define PF_ABS(_x1) ((_x1 < 0) ? -(_x1) : (_x1)) +#define PF_ABSLT(_x1,_x2) ((_x1) < (_x2) && -(_x1) < (_x2)) +#define PF_ABSGT(_x1,_x2) ((_x1) > (_x2) || -(_x1) > (_x2)) +#define PF_ABSLE(_x1,_x2) ((_x1) <= (_x2) && -(_x1) <= (_x2)) +#define PF_ABSGE(_x1,_x2) ((_x1) >= (_x2) || -(_x1) >= (_x2)) +/* + * Speed oriented macros + */ +#define PF_PI 3.14159265358979323846f /* F for SP float */ +#define PF_PI_D 3.14159265358979323846 /* slower DP for more precision */ + +#define PF_DEG2RAD(x) ((x)*PF_PI /180.0f) +#define PF_DEG2RAD_D(x) ((x)*PF_PI_D/180.0) + +#define PF_RAD2DEG(x) ((x)*180.0f/PF_PI) +#define PF_RAD2DEG_D(x) ((x)*180.0 /PF_PI_D) + +#define PF_HUGEVAL 3.40282347e+37f + + +/* macro for fast square roots */ +/* thresholds chosen so it's no worse than pfSqrt() */ +#define PF_SQRT1(_x) \ + (((_x) > 0.9996f && (_x) < 1.001f) ? \ + 0.5f + 0.5f*(_x) : \ + pfSqrt(_x)) + +#define PF_1OVERSQRT1(_x) \ + (((_x) > 0.9996f && (_x) < 1.001f) ? \ + 1.5f - 0.5f*(_x) : \ + 1.0f/pfSqrt(_x)) + +struct Vec3f { + // PFSTRUCT_DECLARE + +public: + float vec[3]; + +public: + // constructors and destructors + //CAPI:private + Vec3f(float _x, float _y, float _z) { set(_x, _y, _z); } + Vec3f(float *_p) { set(_p); } + Vec3f() {}; + +public: + // sets and gets + //CAPI:arrayclass + //CAPI:verb SetVec3 + void set(float _x, float _y, float _z) { + vec[0] = _x; + vec[1] = _y; + vec[2] = _z; + } + void set(float *_p){ + vec[0]=_p[0]; + vec[1]=_p[1]; + vec[2]=_p[2]; + } + +public: + // other functions + //CAPI:verb + void copy(const Vec3f& _v) { *this = _v; } + int equal(const Vec3f& _v) const { + return (vec[0] == _v[0] && + vec[1] == _v[1] && + vec[2] == _v[2]); + } + int almostEqual(const Vec3f& _v, float _tol) const; + + void negate(const Vec3f& _v) { + vec[0] = -_v[0]; + vec[1] = -_v[1]; + vec[2] = -_v[2]; + } + + float dot(const Vec3f& _v) const { + return (vec[0] * _v[0] + + vec[1] * _v[1] + + vec[2] * _v[2]); + } + + void add(const Vec3f& _v1, const Vec3f& _v2) { + vec[0] = _v1[0] + _v2[0]; + vec[1] = _v1[1] + _v2[1]; + vec[2] = _v1[2] + _v2[2]; + } + + void sub(const Vec3f& _v1, const Vec3f& _v2) { + vec[0] = _v1[0] - _v2[0]; + vec[1] = _v1[1] - _v2[1]; + vec[2] = _v1[2] - _v2[2]; + } + + void scale(float _s, const Vec3f& _v) { + vec[0] = _s * _v[0]; + vec[1] = _s * _v[1]; + vec[2] = _s * _v[2]; + } + + void addScaled(const Vec3f& _v1, float _s, const Vec3f& _v2) { + vec[0] = _v1[0] + _s * _v2[0]; + vec[1] = _v1[1] + _s * _v2[1]; + vec[2] = _v1[2] + _s * _v2[2]; + } + + void combine(float _a, const Vec3f& _v1, float _b, const Vec3f& _v2) { + vec[0] = _a * _v1[0] + _b * _v2[0]; + vec[1] = _a * _v1[1] + _b * _v2[1]; + vec[2] = _a * _v1[2] + _b * _v2[2]; + } + + + float sqrDistance(const Vec3f& _v) const { + return (PF_SQUARE(vec[0] - _v[0]) + + PF_SQUARE(vec[1] - _v[1]) + + PF_SQUARE(vec[2] - _v[2])); + } + void norm(const Vec3f& _v1, const Vec3f& _v2, const Vec3f& _v3){ + Vec3f s1,s2; + s1 = _v1-_v2; + s2 = _v3-_v2; + cross(s1,s2); + normalize(); + } + float normalize(){ + float len=length(); + if(len==0) this->set(len,len,len); + vec[0]/=len; vec[1]/=len; vec[2]/=len; + return len; + } + float length() const{ + return sqrt(PF_SQUARE(vec[0]) + + PF_SQUARE(vec[1]) + + PF_SQUARE(vec[2])); + } + //CAPI:verb DistancePt3 + float distance(const Vec3f& _v) const{ + return sqrt(this->sqrDistance(_v)); + } + void cross(const Vec3f& v1, const Vec3f& v2){ + float temp[3]; + + temp[0] = (v1[1] * v2[2]) - (v1[2] * v2[1]); + temp[1] = (v1[2] * v2[0]) - (v1[0] * v2[2]); + temp[2] = (v1[0] * v2[1]) - (v1[1] * v2[0]); + set(temp); + } + void cross(const Vec3f& v2){ + float temp[3]; + + temp[0] = (vec[1] * v2[2]) - (vec[2] * v2[1]); + temp[1] = (vec[2] * v2[0]) - (vec[0] * v2[2]); + temp[2] = (vec[0] * v2[1]) - (vec[1] * v2[0]); + set(temp); + } + /*CAPI:verb XformVec3 + void xformVec(const Vec3f& _v, const pfMatrix& _m); + + //CAPI:verb XformPt3 + void xformPt(const Vec3f& _v, const pfMatrix& _m); + + //CAPI:verb FullXformPt3 + void fullXformPt(const Vec3f& _v, const pfMatrix& _m);*/ + +public: + // Operators + float& operator [](int i) { return vec[i]; } + + const float& operator [](int i) const { return vec[i]; } + + int operator ==(const Vec3f& _v) const { + return vec[0] == _v[0] && vec[1] == _v[1] && vec[2] == _v[2]; + } + int operator !=(const Vec3f& _v) const { + return !(*this == _v); + } + +public: + // Vec3f operators (N.B. return by value can be slow) + + Vec3f operator -() const { + return Vec3f(-vec[0], -vec[1], -vec[2]); + } + + Vec3f operator +(const Vec3f& _v) const { + return Vec3f(vec[0]+_v[0], vec[1]+_v[1], vec[2]+_v[2]); + } + + Vec3f operator -(const Vec3f& _v) const { + return Vec3f(vec[0]-_v[0], vec[1]-_v[1], vec[2]-_v[2]); + } + + friend inline Vec3f operator *(float _s, const Vec3f&); + friend inline Vec3f operator *(const Vec3f& _v, float _s); + friend inline Vec3f operator /(const Vec3f& _v, float _s); + // friend inline Vec3f operator *(const Vec3f& _v, const pfMatrix& _m); + +public: + // Assignment Operators + Vec3f& operator =(const Vec3f& _v) { + vec[0] = _v[0]; + vec[1] = _v[1]; + vec[2] = _v[2]; + return *this; + } + + Vec3f& operator *=(float _s) { + vec[0] *= _s; + vec[1] *= _s; + vec[2] *= _s; + return *this; + } + + Vec3f& operator /=(float _s) { + _s = 1.0/_s; + return *this *= _s; + } + + Vec3f& operator +=(const Vec3f& _v) { + vec[0] += _v[0]; + vec[1] += _v[1]; + vec[2] += _v[2]; + return *this; + } + + Vec3f& operator -=(const Vec3f& _v) { + vec[0] -= _v[0]; + vec[1] -= _v[1]; + vec[2] -= _v[2]; + return *this; + } +}; + + +inline Vec3f operator *(float _s, const Vec3f& _v) { + return Vec3f(_v[0]*_s, _v[1]*_s, _v[2]*_s); +} + +inline Vec3f operator *(const Vec3f& _v, float _s) { + return Vec3f(_v[0]*_s, _v[1]*_s, _v[2]*_s); +} + +inline Vec3f operator /(const Vec3f& _v, float _s) { + _s = 1.0f/_s; + return Vec3f(_v[0]*_s, _v[1]*_s, _v[2]*_s); +} + +//inline Vec3f operator *(const Vec3f& _v, const pfMatrix& _m) { + // transform as point (w=1), assuming affine transformation + // i.e. does not use slower dst.xformFullPt(). +// Vec3f dst; dst.xformPt(_v, _m); return dst; +//} + +#endif + diff --git a/src/WildWriter.cc b/src/WildWriter.cc new file mode 100644 index 0000000..b6bcf9c --- /dev/null +++ b/src/WildWriter.cc @@ -0,0 +1,609 @@ +#include +#include +#include "WildWriter.hh" + +//#define DISKBLOCKSIZE 8192 + +void WildWriterB::beginDataset(int numnodes, + int numcells, + IObase::DataType datacomponenttype, + int numdatacomponents, + int *componentsizes, + char *componentnames, + char componentnameseparator){ + int i; + nnodes=numnodes; + ncells=numcells; + comptype=datacomponenttype; + ncomp = numdatacomponents; + compsizes.setSize(ncomp); + if(componentsizes){ + for(i=0,totalcomp=1;i=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={3,0}; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } + } + */ + +void WildWriterB::endNodes(){ + // Flush buffers for final writeChunk() + //setMode(Idle); + int origin[2]={0,0},dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=bufferindex; + origin[1]=masterindex-bufferindex; + // Flush buffers for final writeChunk() + // dump the remainder of buffer + file.writeChunk(dims,origin,buffer); + bufferindex=0; +} + +void WildWriterB::beginCells(){ + int dims[2]={9,0}; + dims[1]=ncells; + file.reserveChunk(IObase::Int32,2,dims); + bufferindex=masterindex=0; + segsize=BLOCKSIZE/(9*sizeof(int)); +} +void WildWriterB::beginCells(int numcells){ + int dims[2]={9,0}; + ncells=numcells; + dims[1]=ncells; + file.reserveChunk(IObase::Int32,2,dims); + bufferindex=masterindex=0; + segsize=BLOCKSIZE/(9*sizeof(int)); +} +/* + inline void addCell(int level,int *neighborlist){ + //checkMode(WriteCells); + int *copyptr=(int *)buffer; + int index=bufferindex*9; + // copy into master buffer. + copyptr[index+i]=level; + for(int i=0;i<8;i++) + copyptr[index+i+1]=neighborlist[i]; + bufferindex++; + masterindex++; + if(bufferindex>=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={3,0}; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } + } + */ + +void WildWriterB::endCells(){ + // Flush buffers for final writeChunk() + //setMode(Idle); + int origin[2]={0,0},dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=bufferindex; + origin[1]=masterindex-bufferindex; + // Flush buffers for final writeChunk() + // dump the remainder of buffer + file.writeChunk(dims,origin,buffer); + bufferindex=0; +} +void WildWriterB::beginData(){ + int dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=nnodes; + file.reserveChunk(comptype,2,dims); + bufferindex=masterindex=0; + segsize=BLOCKSIZE/(totalcomp*IObase::sizeOf(comptype)); +} + +void WildWriterB::beginData(IObase::DataType datacomponenttype, + int numdatacomponents, + int *componentsizes, + char *componentnames, + char componentnameseparator){ + int dims[2]={0,0}; + int i; + comptype=datacomponenttype; + ncomp = numdatacomponents; + compsizes.setSize(ncomp); + if(componentsizes){ + for(i=0,totalcomp=1;i=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } +} +*/ +void WildWriterB::endData(){ + int origin[2]={0,0},dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=bufferindex; + origin[1]=masterindex-bufferindex; + // Flush buffers for final writeChunk() + // dump the remainder of buffer + file.writeChunk(dims,origin,buffer); + bufferindex=0; +} + +void WildWriterB::endDataset() { + // flush all buffers (not really necessary in "dumb mode") + // and make certain ncells & nnodes have been written + // delete the master buffer if dynamically allocated +} + +//#include "declare_extern.h" + +void WriteNodes(char *filename){ + int i,j,k,d,cell_id,vertex_id; + // FILE *fp; + // char output_file[16]; + treenode *gp; + // Later On, we'll need to keep the file open persistently + IObase *iofile = new IEEEIO(filename,IObase::Write); + WildWriterB *file = new WildWriterB(*iofile); + + for ( d=0 ; d<=total_depth ; d++ ) + for ( i=0 ; i<=(x[d]-1) ; i++ ) { + gp = start_x[d][i]; + do { + if ((gp->xyz[0] < xmax-e)&& + (gp->xyz[1] < ymax-e)&& + (gp->xyz[2] < zmax-e)){ + cell_id++; + if (connectivity) { + if (gp->sib[1] != NULL) + if ((gp->sib[1]->xyz[0] < xmax-e)&& + (fabs(gp->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)) + cell_id++; + + if (gp->sib[3] != NULL) + if ((gp->sib[3]->xyz[1] < ymax-e)&& + (fabs(gp->sib[3]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)) + cell_id++; + + if ((gp->sib[1] != NULL)&&(gp->sib[3] != NULL)) + if (gp->sib[3]->sib[1] != NULL) + if ((gp->sib[3]->sib[1]->xyz[0] < xmax-e)&& + (gp->sib[3]->sib[1]->xyz[1] < ymax-e)&& + (fabs(gp->sib[3]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[3]->sib[1]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)) + cell_id++; + + if (gp->sib[5] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + cell_id++; + + if (gp->sib[5] != NULL) + if (gp->sib[5]->sib[1] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (gp->sib[5]->sib[1]->xyz[0] < xmax-e)&& + (fabs(gp->sib[5]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + cell_id++; + + if (gp->sib[5] != NULL) + if (gp->sib[5]->sib[3] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (gp->sib[5]->sib[3]->xyz[1] < ymax-e)&& + (fabs(gp->sib[5]->sib[3]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + cell_id++; + + if (gp->sib[5] != NULL) + if ((gp->sib[5]->sib[3] != NULL)&&(gp->sib[5]->sib[1] != NULL)) + if (gp->sib[5]->sib[3]->sib[1] != NULL) + if ((gp->sib[5]->sib[3]->sib[1]->xyz[0] < xmax-e)&& + (gp->sib[5]->sib[3]->sib[1]->xyz[1] < ymax-e)&& + (gp->sib[5]->sib[3]->sib[1]->xyz[2] < zmax-e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + cell_id++; + } + } + gp = gp->sib[1]; + } while (gp != NULL); + } + for ( d=0 ; d<=total_depth ; d++ ) + for ( i=0 ; i<=(x[d]-1) ; i++ ) { + gp = start_x[d][i]; + + do { + if ((gp->xyz[0] < xmax-e)&& + (gp->xyz[1] < ymax-e)&& + (gp->xyz[2] < zmax-e)) { + if (d == 0) { + gp->hex_id[0] = vertex_id+1; + gp->hex_id[1] = vertex_id+2; + gp->hex_id[2] = vertex_id+3; + gp->hex_id[3] = vertex_id+4; + gp->hex_id[4] = vertex_id+5; + gp->hex_id[5] = vertex_id+6; + gp->hex_id[6] = vertex_id+7; + gp->hex_id[7] = vertex_id+8; + vertex_id += 8; + } + else { + gp->hex_id[0] = gp->par->hex_id[gp->par_grid_point]; + gp->hex_id[1] = vertex_id+1; + gp->hex_id[2] = vertex_id+2; + gp->hex_id[3] = vertex_id+3; + gp->hex_id[4] = vertex_id+4; + gp->hex_id[5] = vertex_id+5; + gp->hex_id[6] = vertex_id+6; + gp->hex_id[7] = vertex_id+7; + vertex_id += 7; + } + } + gp = gp->sib[1]; + } while (gp != NULL); + } + + // Set the var names + char str[256]; + str[0]='\0'; + for(i=0;ibeginDataset(vertex_id, /* number of vertices */ + cell_id, /* number of cells */ + IObase::Float32, /* datatype for the data components */ + variables, /* number of data components */ + 0,/* no array for componentsizes implies each is a scalar */ + str,','); /* names */ + /* Now do the nodes */ + file->beginNodes(); + for ( d=0 ; d<=total_depth ; d++ ) + for ( i=0 ; i<=(x[d]-1) ; i++ ) { + gp = start_x[d][i]; + do { + if ((gp->xyz[0] < xmax-e)&& + (gp->xyz[1] < ymax-e)&& + (gp->xyz[2] < zmax-e)) { + float coords[3]; + if (d == 0){ + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[0], */ + coords[0]=gp->xyz[0]; + coords[1]=gp->xyz[1]; + coords[2]=gp->xyz[2]; + file->addNode(coords); + } + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[1], */ + coords[0]=gp->xyz[0]+info[d][0]; + coords[1]=gp->xyz[1]; + coords[2]=gp->xyz[2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[2],*/ + coords[0]=gp->xyz[0]; + coords[1]=gp->xyz[1]+info[d][1]; + coords[2]=gp->xyz[2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[3],*/ + coords[0]=gp->xyz[0]+info[d][0]; + coords[1]=gp->xyz[1]+info[d][1]; + coords[2]=gp->xyz[2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[4], */ + coords[0]=gp->xyz[0]; + coords[1]=gp->xyz[1]; + coords[2]=gp->xyz[2]+info[d][2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[5], */ + coords[0]=gp->xyz[0]+info[d][0]; + coords[1]=gp->xyz[1]; + coords[2]=gp->xyz[2]+info[d][2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[6], */ + coords[0]=gp->xyz[0]; + coords[1]=gp->xyz[1]+info[d][1]; + coords[2]=gp->xyz[2]+info[d][2]; + file->addNode(coords); + + /* fprintf(fp,"%d %f %f %f\n",gp->hex_id[7], */ + coords[0]=gp->xyz[0]+info[d][0]; + coords[1]=gp->xyz[1]+info[d][1]; + coords[2]=gp->xyz[2]+info[d][2]; + file->addNode(coords); + } + gp = gp->sib[1]; + } while (gp != NULL); + } + file->endNodes(); + + file->beginCells(); + for ( cell_id=0,d=0 ; d<=total_depth ; d++ ){ + int cellvec[8],level; + level=d; + for ( i=0 ; i<=(x[d]-1) ; i++ ) { + gp = start_x[d][i]; + do { + if ((gp->xyz[0] < xmax-e)&& + (gp->xyz[1] < ymax-e)&& + (gp->xyz[2] < zmax-e)) { + cell_id++; + + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->hex_id[4]; + cellvec[1]=gp->hex_id[5]; + cellvec[2]=gp->hex_id[7]; + cellvec[3]=gp->hex_id[6]; + cellvec[4]=gp->hex_id[0]; + cellvec[5]=gp->hex_id[1]; + cellvec[6]=gp->hex_id[3]; + cellvec[7]=gp->hex_id[2]; + file->addCell(level,cellvec); + if (connectivity) { + if (gp->sib[1] != NULL) + if ((gp->sib[1]->xyz[0] < xmax-e)&& + (fabs(gp->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)) + { + cell_id++; + + // fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->hex_id[5]; + cellvec[1]=gp->sib[1]->hex_id[4]; + cellvec[2]=gp->sib[1]->hex_id[6]; + cellvec[3]=gp->hex_id[7]; + cellvec[4]=gp->hex_id[1]; + cellvec[5]=gp->sib[1]->hex_id[0]; + cellvec[6]=gp->sib[1]->hex_id[2]; + cellvec[7]=gp->hex_id[3]; + file->addCell(level,cellvec); + } + + if (gp->sib[3] != NULL) + if ((gp->sib[3]->xyz[1] < ymax-e)&& + (fabs(gp->sib[3]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)) + { + cell_id++; + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]= gp->hex_id[6]; + cellvec[1]=gp->hex_id[7]; + cellvec[2]=gp->sib[3]->hex_id[5]; + cellvec[3]= gp->sib[3]->hex_id[4]; + cellvec[4]=gp->hex_id[2]; + cellvec[5]=gp->hex_id[3]; + cellvec[6]= gp->sib[3]->hex_id[1]; + cellvec[7]= gp->sib[3]->hex_id[0]; + file->addCell(level,cellvec); + } + + if ((gp->sib[1] != NULL)&&(gp->sib[3] != NULL)) + if (gp->sib[3]->sib[1] != NULL) + if ((gp->sib[3]->sib[1]->xyz[0] < xmax-e)&& + (gp->sib[3]->sib[1]->xyz[1] < ymax-e)&& + (fabs(gp->sib[3]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[3]->sib[1]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)) + { + cell_id++; + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]= gp->hex_id[7]; + cellvec[1]= gp->sib[1]->hex_id[6]; + cellvec[2]= gp->sib[3]->sib[1]->hex_id[4]; + cellvec[3]= gp->sib[3]->hex_id[5]; + cellvec[4]= gp->hex_id[3]; + cellvec[5]= gp->sib[1]->hex_id[2]; + cellvec[6]= gp->sib[3]->sib[1]->hex_id[0]; + cellvec[7]= gp->sib[3]->hex_id[1]; + file->addCell(level,cellvec); + } + + if (gp->sib[5] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + { + cell_id++; + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->sib[5]->hex_id[0]; + cellvec[1]=gp->sib[5]->hex_id[1]; + cellvec[2]=gp->sib[5]->hex_id[3]; + cellvec[3]=gp->sib[5]->hex_id[2]; + cellvec[4]= gp->hex_id[4]; + cellvec[5]=gp->hex_id[5]; + cellvec[6]=gp->hex_id[7]; + cellvec[7]= gp->hex_id[6]; + file->addCell(level,cellvec); + } + + if (gp->sib[5] != NULL) + if (gp->sib[5]->sib[1] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (gp->sib[5]->sib[1]->xyz[0] < xmax-e)&& + (fabs(gp->sib[5]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + { + cell_id++; + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->sib[5]->hex_id[1]; + cellvec[1]= gp->sib[5]->sib[1]->hex_id[0]; + cellvec[2]= gp->sib[5]->sib[1]->hex_id[2]; + cellvec[3]= gp->sib[5]->hex_id[3]; + cellvec[4]= gp->hex_id[5]; + cellvec[5]= gp->sib[1]->hex_id[4]; + cellvec[6]= gp->sib[1]->hex_id[6]; + cellvec[7]= gp->hex_id[7]; + file->addCell(level,cellvec); + } + + if (gp->sib[5] != NULL) + if (gp->sib[5]->sib[3] != NULL) + if ((gp->sib[5]->xyz[2] < zmax-e)&& + (gp->sib[5]->sib[3]->xyz[1] < ymax-e)&& + (fabs(gp->sib[5]->sib[3]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)&& + (fabs(gp->sib[5]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + { + cell_id++; + + //fprintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->sib[5]->hex_id[2]; + cellvec[1]=gp->sib[5]->hex_id[3]; + cellvec[2]=gp->sib[5]->sib[3]->hex_id[1]; + cellvec[3]=gp->sib[5]->sib[3]->hex_id[0]; + cellvec[4]=gp->hex_id[6]; + cellvec[5]=gp->hex_id[7]; + cellvec[6]=gp->sib[3]->hex_id[5]; + cellvec[7]=gp->sib[3]->hex_id[4]; + file->addCell(level,cellvec); + } + + if (gp->sib[5] != NULL) + if ((gp->sib[5]->sib[3] != NULL)&&(gp->sib[5]->sib[1] != NULL)) + if (gp->sib[5]->sib[3]->sib[1] != NULL) + if ((gp->sib[5]->sib[3]->sib[1]->xyz[0] < xmax-e)&& + (gp->sib[5]->sib[3]->sib[1]->xyz[1] < ymax-e)&& + (gp->sib[5]->sib[3]->sib[1]->xyz[2] < zmax-e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[0]-gp->xyz[0]) <= info[d][0]+info[d][0]+e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[1]-gp->xyz[1]) <= info[d][1]+info[d][1]+e)&& + (fabs(gp->sib[5]->sib[3]->sib[1]->xyz[2]-gp->xyz[2]) <= info[d][2]+info[d][2]+e)) + { + cell_id++; + //rintf(fp,"%d 1 hex %d %d %d %d %d %d %d %d\n",cell_id, + cellvec[0]=gp->sib[5]->hex_id[3]; + cellvec[1]=gp->sib[5]->sib[1]->hex_id[2]; + cellvec[2]=gp->sib[5]->sib[3]->sib[1]->hex_id[0]; + cellvec[3]=gp->sib[5]->sib[3]->hex_id[1]; + cellvec[4]=gp->hex_id[7]; + cellvec[5]=gp->sib[1]->hex_id[6]; + cellvec[6]=gp->sib[3]->sib[1]->hex_id[4]; + cellvec[7]=gp->sib[3]->hex_id[5]; + file->addCell(level,cellvec); + } + } + } + gp = gp->sib[1]; + } while (gp != NULL); + } + } + file->endCells(); // Done with writing Cells + //rintf(fp,"%d",variables); + //for ( i=1 ; i<=(variables-1) ; i++ ) + // fprintf(fp," 1"); + // fprintf(fp," 1\n"); + file->beginData(); // Start writing Data + //for ( i=1 ; i<=variables ; i++ ) + // fprintf(fp,"v%d, 1b/in**2\n",i); + for ( d=0 ; d<=total_depth ; d++ ) + for ( i=0 ; i<=(x[d]-1) ; i++ ) { + gp = start_x[d][i]; + do { + if ((gp->xyz[0] < xmax-e)&& + (gp->xyz[1] < ymax-e)&& + (gp->xyz[2] < zmax-e)) { + if (d == 0) { // The toplevel + for ( k=0 ; k<=7 ; k++ ) { + /* fprintf(fp,"%d ",gp->hex_id[k]); + for ( j=0 ; j<=(variables-2) ; j++ ) + fprintf(fp,"%f ",gp->u[k][t[d][0]][j]); + fprintf(fp,"%f\n",gp->u[k][t[d][0]][variables-1]);*/ + file->addData(gp->u[k][t[d][0]]); + } + } + else { + for ( k=1 ; k<=7 ; k++ ) { + /*fprintf(fp,"%d ",gp->hex_id[k]); + for ( j=0 ; j<=(variables-2) ; j++ ) + fprintf(fp,"%f ",gp->u[k][t[d][0]][j]); + fprintf(fp,"%f\n",gp->u[k][t[d][0]][variables-1]);*/ + file->addData(gp->u[k][t[d][0]]); + } + } + } + gp = gp->sib[1]; + } while (gp != NULL); + } + file->endData(); + file->endDataset(); +} diff --git a/src/WildWriter.h b/src/WildWriter.h new file mode 100644 index 0000000..c2b4a3b --- /dev/null +++ b/src/WildWriter.h @@ -0,0 +1,7 @@ +#ifndef __WILDWRITER_H_ +#define __WILDWRITER_H_ + +#include "declare_extern.h" +void WriteNodes(char *filename); + +#endif diff --git a/src/WildWriter.hh b/src/WildWriter.hh new file mode 100644 index 0000000..a391ea3 --- /dev/null +++ b/src/WildWriter.hh @@ -0,0 +1,142 @@ +#ifndef __WILDWRITER_HH_ +#define __WILDWRITER_HH_ + +#include +#include +#include + +#define DISKBLOCKSIZE 8192 +#define BLOCKSIZE 2*DISKBLOCKSIZE + +// Does not assume contiguous data (writes in chunks) +class WildWriterB { + IObase &file; + int nnodes,ncells,ncomp; + char buffer[BLOCKSIZE]; // could dynamically allocate + FlexArray compnames; + int totalcomp; + IObase::DataType comptype; + FlexArray compsizes; + int bufferindex,masterindex,segsize; +public: + WildWriterB(IObase &descriptor):file(descriptor){ + } + ~WildWriterB(){} + void beginDataset(int numnodes, + int numcells, + IObase::DataType datacomponenttype, + int numdatacomponents, + int *componentsizes, + char *componentnames, + char componentnameseparator); + + void beginNodes(int numnodes); + void beginNodes(); + inline void addNode(float *coords){ + // attrib WildNode[%u] (should buffer internally) + // but we can only chunk on Datasets :( + // so collect data in 8k buffers + //checkMode(WriteNodes); + float *copyptr=(float *)buffer; + // copy into master buffer. + int index=bufferindex*3; + for(int i=0;i<3;i++) copyptr[index+i]=coords[i]; + bufferindex++; + masterindex++; + if(bufferindex>=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={3,0}; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } + } + void endNodes(); + void beginCells(int numcells); + void beginCells(); + inline void addCell(int level,int *neighborlist){ + // checkMode(WriteCells); + int *copyptr=(int *)buffer; + int index=bufferindex*9; + // copy into master buffer. + copyptr[index+1]=level; + for(int i=0;i<8;i++) + copyptr[index+i+1]=neighborlist[i]; + bufferindex++; + masterindex++; + if(bufferindex>=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={3,0}; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } + } + void endCells(); + void beginData(); + void beginData(IObase::DataType datacomponenttype, + int numdatacomponents, + int *componentsizes, + char *componentnames, + char componentnameseparator); + inline void addData(void *data){ + // checkMode(WriteCells); + if(comptype==IObase::Float32){ + float *copyptr=(float *)buffer; + float *dptr=(float*)data; + int index = bufferindex*totalcomp*sizeof(double); + for(int i=0;i=segsize){ // dump the buffer to disk + int origin[2]={0,0},dims[2]={0,0}; + dims[0]=totalcomp; + dims[1]=segsize; + origin[1]=masterindex-segsize; + file.writeChunk(dims,origin,buffer); + bufferindex=0; // reset the bufferindex for next seg + } + } + void endData(); + void endDataset() ; +}; + +extern "C" { +#include "WildWriter.h" +} + +#endif + +/* +// Assumes Contiguous Data +class WildWriterA { + IO &file; +public: + WildWriter(IO &descriptor):file(descriptor){ + } + ~WildWriter(){ + } + // All nodes for all levels + void writeNodes(int numnodes,float *node_coords){ + int dims[2]={3,0}; + dims[1]=numnodes; + file.write(IObase::Float32,2,dims,node_coords); + file.writeAttribute("WildNodes",IObase::Int,0,dims); + } + // Must Be Hexahedral Cells + void writeCells(int level,int ncells,int *celllist){ + + } + // Assumes Node-centered data + void writeData(char *name,IObase::DataType type,int veclen,void *data){ + + } +}; +*/ diff --git a/src/WriteHLL.cc b/src/WriteHLL.cc new file mode 100644 index 0000000..cdb8095 --- /dev/null +++ b/src/WriteHLL.cc @@ -0,0 +1,229 @@ +#include +#include +#include +#include +#include "WriteHLL.hh" + +// declare a new dataset +void WriteHLL::newDataset(int ndims,long npoints){ + int dt=1; + current_ndims=ndims; + file.write(IObase::Int32,dt,&dt,&ndims); // single integer (ndims) + switch(ndims){ + case 1: + current_cellsize=2; + current_celltype="line"; + break; + case 2: + current_cellsize=4; + current_celltype="quad"; + break; + case 3: + current_cellsize=8; + current_celltype="hex"; + break; + default: + fprintf(stderr,"WriteHLL:newDataset(), ndims=%d is invalid\n",ndims); + break; + } + current_npoints=npoints; + file.writeAttribute("cellsize",IObase::Int32,1,¤t_cellsize); + file.writeAttribute("celltype",IObase::String,strlen(current_celltype),current_celltype); +} +// each array is npoints long +void WriteHLL::writeCoords(void *xcoords,void *ycoords,void *zcoords){ + if(xcoords) + file.writeAttribute("xcoords",IObase::Float32,current_npoints,xcoords); + if(ycoords) + file.writeAttribute("ycoords",IObase::Float32,current_npoints,ycoords); + if(zcoords) + file.writeAttribute("zcoords",IObase::Float32,current_npoints,zcoords); +} + +void WriteHLL::writeCoordsXYZ(void *xyzcoordsp){ // this is npoints *3 long + register long s,d,last=current_npoints*3; + float *xyzcoords=(float*)xyzcoordsp; + char coordname[32]; + float *coords = new float[current_npoints]; + strcpy(coordname,"xcoords"); + for(int i=0;i=1 && xcoords) + idx=file.readAttributeInfo("xcoords",dt,npoints); + if(idx>=0 && npoints==current_npoints) + file.readAttribute(idx,xcoords); + if(current_ndims>=1 && ycoords) + idx=file.readAttributeInfo("ycoords",dt,npoints); + if(idx>=0 && npoints==current_npoints) + file.readAttribute(idx,ycoords); + if(current_ndims>=1 && zcoords) + idx=file.readAttributeInfo("zcoords",dt,npoints); + if(idx>=0 && npoints==current_npoints) + file.readAttribute(idx,zcoords); +} +// will assume ncells=npoints unless overridden. +void ReadHLL::readConnectivity(int *cells){ + int arraysize,idx; + IObase::DataType dt; + idx=file.readAttributeInfo("cells",dt,arraysize); + file.readAttribute(idx,cells); +} + +// npoints data points since the data is vertex-centered +// each dataset can be of independent type +void ReadHLL::readData(char *name,void *data){ + char dname[128]; + IObase::DataType datatype; + int len,idx; + sprintf(dname,"data_%s",name); + idx=file.readAttributeInfo(dname,datatype,len); + file.readAttribute(idx,data); +} + + + +IOFile *HLLnewWriter(IOFile *file){ + IObase *iofile = (IObase *)file; + return (IOFile *)(new WriteHLL(*iofile)); +} +void HLLdeleteWriter(IOFile *file){ + if(!file) return; + WriteHLL *h = (WriteHLL *)file; + delete h; +} + +void HLLsetCoordType(IOFile *handle,int coordtype){ + WriteHLL *h = (WriteHLL *)handle; + h->setCoordType(IObase::Int2DataType(coordtype)); +} + +void HLLsetIndexType(IOFile *handle,int indextype){ + WriteHLL *h = (WriteHLL *)handle; + h->setIndexType(IObase::Int2DataType(indextype)); +} + +void HLLnewDataset(IOFile *handle,int ndims,long npoints){ + WriteHLL *h = (WriteHLL *)handle; + h->newDataset(ndims,npoints); +} +void HLLwriteCoords(IOFile *handle, + float *xcoords,float *ycoords,float *zcoords){ + WriteHLL *h = (WriteHLL *)handle; + h->writeCoords(xcoords,ycoords,zcoords); +} +void HLLwriteCoordsXYZ(IOFile *handle,float *xcoords){ + WriteHLL *h = (WriteHLL *)handle; + h->writeCoordsXYZ(xcoords); +} +void HLLwriteConnectivity(IOFile *handle,int *cells,int ncells){ + WriteHLL *h = (WriteHLL *)handle; + h->writeConnectivity(cells,ncells); +} +void HLLwriteData(IOFile *handle,char *dataname,int datatype, + void *data,int veclen){ + WriteHLL *h = (WriteHLL *)handle; + h->writeData(dataname,IObase::Int2DataType(datatype),data,veclen); +} + +IOFile *HLLnewReader(IOFile *base){ + IObase *iofile = (IObase *)base; + return (IOFile *)(new ReadHLL(*iofile)); +} +void HLLdeleteReader(IOFile *handle){ + if(!handle) return; + ReadHLL *h = (ReadHLL *)handle; + delete h; +} + +void HLLselectDataset(IOFile *handle, + int index,int *ndims,int *npoints, + int *ncells,int *ndata){ + ReadHLL *h = (ReadHLL *)handle; + h->selectDataset(index,*ndims,*npoints,*ncells,*ndata); +} +void HLLreadDataInfo(IOFile *handle,char *names[], + int *datatypes,int *veclens){ + ReadHLL *h = (ReadHLL *)handle; + h->readDataInfo(names,datatypes,veclens); +} +void HLLreadCoords(IOFile *handle, + float *xcoords,float *ycoords,float *zcoords){ + ReadHLL *h = (ReadHLL *)handle; + h->readCoords(xcoords,ycoords,zcoords); +} +void HLLreadConnectivity(IOFile *handle,int *cells){ + ReadHLL *h = (ReadHLL *)handle; + h->readConnectivity(cells); +} +void HLLreadData(IOFile *handle,char *name,void *data){ + ReadHLL *h = (ReadHLL *)handle; + h->readData(name,data); +} + diff --git a/src/WriteHLL.h b/src/WriteHLL.h new file mode 100644 index 0000000..7d02130 --- /dev/null +++ b/src/WriteHLL.h @@ -0,0 +1,32 @@ + +#ifndef __HLL_WRITER_H_ +#define __HLL_WRITER_H_ + +IOFile *HLLnewWriter(IOFile *file); +void HLLdeleteWriter(IOFile *file); + +void HLLsetCoordType(IOFile *handle,int coordtype); +void HLLsetIndexType(IOFile *handle,int indextype); +void HLLnewDataset(IOFile *handle,int ndims,long npoints); +void HLLwriteCoords(IOFile *handle, + void *xcoords,void *ycoords,void *zcoords); +void HLLwriteCoordsXYZ(IOFile *handle,void *xcoords); +void HLLwriteConnectivity(IOFile *handle,void *cells,long ncells); +void HLLwriteData(IOFile *handle,char *dataname,int datatype, + void *data,int veclen); + +IOFile *HLLnewReader(IOFile *base); +void HLLdeleteReader(IOFile *handle); + +void HLLselectDataset(IOFile *handle, + int index,int *ndims,int *npoints, + int *ncells,int *ndata); +void HLLreadDataInfo(IOFile *handle,char *names[], + int *datatypes,int *veclens); +void HLLreadCoords(IOFile *handle, + float *xcoords,float *ycoords,float *zcoords); +void HLLreadConnectivity(IOFile *handle,int *cells); +void HLLreadData(IOFile *handle,char *name,void *data); + + +#endif diff --git a/src/WriteHLL.hh b/src/WriteHLL.hh new file mode 100644 index 0000000..90c4ba1 --- /dev/null +++ b/src/WriteHLL.hh @@ -0,0 +1,52 @@ +#ifndef __HLL_WRITER_HH_ +#define __HLL_WRITER_HH_ +#include + +class WriteHLL { + IObase &file; + int current_npoints,current_cellsize,current_ndims; + char *current_celltype; + IObase::DataType coordtype,indextype; +public: + WriteHLL(IObase &iofile):file(iofile),current_npoints(0), + coordtype(IObase::Float32),indextype(IObase::Int32){} + ~WriteHLL(){} + // declare a new dataset + void newDataset(int ndims,long npoints); + void setCoordType(IObase::DataType dt){ coordtype=dt; } + void setIndexType(IObase::DataType dt){ indextype=dt; } + // each array is npoints long + void writeCoords(void *xcoords,void *ycoords=0,void *zcoords=0); // for 3D + void writeCoordsXYZ(void *xcoords); // for Packed Coords (any dimension) + // will assume ncells=npoints unless overridden. + void writeConnectivity(void *cells,long ncells=-1); // implicit cellsize + void writeConnectivity(int cellsize,void *cells,long ncells=-1); + // npoints data points since the data is vertex-centered + // each dataset can be of independent type + void writeData(char *dataname,IObase::DataType datatype, + void *data,int veclen=1); +}; + +class ReadHLL { + IObase &file; + int current_npoints,current_ncells,current_cellsize,current_ndims; +public: + ReadHLL(IObase &iofile): + file(iofile),current_npoints(0),current_ncells(0), + current_cellsize(0),current_ndims(0){} + ~ReadHLL(){} + // declare a new dataset + void selectDataset(int index,int &ndims,int &npoints,int &ncells,int &ndata); + // each array is npoints long + void readDataInfo(char *names[],IObase::DataType *datatypes,int *veclens); + void readDataInfo(char *names[],int *datatypes,int *veclens); + void readCoords(float *xcoords,float *ycoords=0,float *zcoords=0); + void readConnectivity(int *cells); + // npoints data points since the data is vertex-centered + // each dataset can be of independent type + void readData(char *name,void *data); +}; +extern "C" { +#include "WriteHLL.h" + } +#endif diff --git a/src/Writer.cc b/src/Writer.cc new file mode 100644 index 0000000..e904f64 --- /dev/null +++ b/src/Writer.cc @@ -0,0 +1,169 @@ +#include +#include "Writer.hh" + +void Writer::writeBounds(){ + if(!ddelta || !dorigin) return; + /* + if(extsize!=drank){ + if(dext) delete dext; + dext=new double[drank]; + }*/ + for(int i=0;isetRank(rank); +} + +void WRsetType(WRFile afile,int numbertype){ + Writer *w = (Writer*)afile; + w->setType(IObase::Int2DataType(numbertype)); +} + +void WRsetParams(WRFile afile, + int rank,int *dims,int type, + double *origin,double *delta){ + Writer *w = (Writer*)afile; + w->setParams(rank,dims,IObase::Int2DataType(type),origin,delta); +} + +void WRsetDims(WRFile afile,int *dims){ + Writer *w = (Writer*)afile; + w->setDims(dims); +} + +void WRsetRankDims(WRFile afile,int rank, int *dims){ + Writer *w = (Writer*)afile; + w->setDims(rank,dims); +} + +void WRsetOrigin(WRFile afile,double *origin){ + Writer *w = (Writer*)afile; + w->setOrigin(origin); +} + +void WRsetDelta(WRFile afile,double *delta){ + Writer *w = (Writer*)afile; + w->setOrigin(delta); +} + +void WRwrite(WRFile afile,void *data){ + Writer *w = (Writer*)afile; + w->write(data); +} + +void WRwriteChunk(WRFile afile){ + Writer *w = (Writer*)afile; + w->reserveChunk(); +} + +void WRwriteChunk(WRFile afile,int *dims,int *origin,void *data){ + Writer *w = (Writer*)afile; + w->writeChunk(dims,origin,data); +} diff --git a/src/Writer.h b/src/Writer.h new file mode 100644 index 0000000..99500df --- /dev/null +++ b/src/Writer.h @@ -0,0 +1,23 @@ +#ifndef __WRITER_H_ +#define __WRITER_H_ + +#include "Arch.h" + +typedef IOFile WRFile;/* its the same, but it is a different object underneath */ +WRFile WRbeginFile PROTO((IOFile *descriptor)); +void WRendFile PROTO((WRFile afile)); + +void WRsetRank PROTO((WRFile afile,int rank)); +void WRsetType PROTO((WRFile afile,int numbertype)); +void WRsetParams PROTO((WRFile afile, + int rank,int *dims,int type, + double *origin,double *delta)); +void WRsetDims PROTO((WRFile afile,int *dims)); +void WRsetRankDims PROTO((WRFile afile,int rank, int *dims)); +void WRsetOrigin PROTO((WRFile afile,double *origin)); +void WRsetDelta PROTO((WRFile afile,double *delta)); +void WRwrite PROTO((WRFile afile,void *data)); +void WRreserveChunk PROTO((WRFile afile)); +void WRwriteChunk PROTO((WRFile afile,int *dims,int *origin,void *data)); +#endif + diff --git a/src/Writer.hh b/src/Writer.hh new file mode 100644 index 0000000..94f2a70 --- /dev/null +++ b/src/Writer.hh @@ -0,0 +1,37 @@ +#ifndef __UNIWRITER_HH_ +#define __UNIWRITER_HH_ + +#include "IO.hh" + +class Writer { +protected: + IObase &file; + int drank; + //int *ddims; + int ddims[5]; + IObase::DataType dtypeID; + // double *ddelta,*dorigin,*dext; + double ddelta[5],dorigin[5],dext[5]; + int extsize; + virtual void writeBounds(); +public: + Writer(IObase &outfile); + virtual ~Writer(); + virtual void setRank(int rank); // more efficient to set rank once for all + virtual void setDims(int *dims);//only if rank has been set(should have flag) + virtual void setDims(int rank,int *dims); + virtual void setType(IObase::DataType typeID); + virtual void setOrigin(double *origin); + virtual void setDelta(double *delta); + virtual void setParams(int rank,int *dims,IObase::DataType typeID, + double *origin,double *delta); + virtual void write(void *data); + virtual void reserveChunk(); + virtual void writeChunk(int *chunkdims,int *chunkorigin,void *data); +}; + +extern "C" { +#include "Writer.h" +} + +#endif diff --git a/src/boxinbox.cc b/src/boxinbox.cc new file mode 100644 index 0000000..c5864fc --- /dev/null +++ b/src/boxinbox.cc @@ -0,0 +1,156 @@ + +#include +#include +#include + +#include +#include "AMRwriter.hh" +typedef char *charp; +struct CommandLine { + char *programname; + charp infile[32]; + char outfile[128]; + int maxlevel; + + void setDefaults(){ + programname=""; + for(int i=0;i<32;i++) infile[i]=0; + strcpy(outfile,"amrout.ieee"); + maxlevel=0; + } + + CommandLine(){ + setDefaults(); + } + + CommandLine(int argc,char *argv[]){ + setDefaults(); + parse(argc,argv); + } + + void parse(int argc,char *argv[]){ + programname=argv[0]; + for(int i=1;i ... -o \n",programname); + puts("Files must appear in order as they are read in."); + } +}; + +int main(int argc, char *argv[]){ + CommandLine cmdln(argc,argv); + typedef IEEEIO *IEEEIOp; + int ninfiles; + IEEEIOp infid[32],outfid; + AMRwriter *amrfile; + int i; + + for(i=0;iisValid()) { + printf("file %s is not an IEEEIO file\n",cmdln.infile[i]); + exit(0); + } + else + printf("Opening file %s as level %u for reading\n", + cmdln.infile[i],i); + } + outfid = new IEEEIO(cmdln.outfile,IObase::Write); + if(!outfid->isValid()) { + printf("file %s could not be opened for writing\n",cmdln.outfile); + exit(0); + } + amrfile = new AMRwriter(*outfid); + printf("Opened file %s for output\n",cmdln.outfile); + + // lets get info about the toplevel grid + IObase::DataType type; + int rank,dims[3]; + int nelements,attribnum; + double delta[3],timestep,origin[3]; + + infid[0]->seek(0); + infid[0]->readInfo(type,rank,dims); + amrfile->setType(type); + + // read delta (spacing between grid points at toplevel grid) + attribnum=infid[0]->readAttributeInfo("delta",type,nelements); + infid[0]->readAttribute(attribnum,delta); + // read timestep size (in floating point realtime) + //attribnum=infid[0]->readAttributeInfo("",type,nelements); + //infid[0]->readAttribute(attribnum,timestep); + timestep=1.0; + // read origin (floating point origin). + attribnum=infid[0]->readAttributeInfo("origin",type,nelements); + infid[0]->readAttribute(attribnum,origin); + + printf("Setting toplevel params origin[%lf,%lf,%lf],Timestep[%lf],delta[%lf,%lf,%lf],maxlevel[%u]\n", + origin[0],origin[1],origin[2], + timestep, + delta[0],delta[1],delta[2], + cmdln.maxlevel); + amrfile->setTopLevelParameters(rank,origin,delta,timestep,cmdln.maxlevel); + amrfile->setRefinement(1, // timerefinement of 1 because we currently + // don't save intermedite timesteps. In the future + // this would be 2 if you dump the intermediate + // timesteps + 2 // spatial refinement between levels is 2 in each + // dimension + ); + // now we read all of the data from the input files + // and write them out into the AMR file + for(int n=0,ndatasets=infid[0]->nDatasets();nseek(n); // make everyone seek to the same place + amrfile->setTime(n); + // this is assuming that all levels are dumped at the same time + // rather than dumping them at the rate which they are computed. + // (eg. this is a snapshot of the entire heirarchy at each timestep). + // however this library can handle each level stepping at a different + // rate. + printf("Readinfo on %u\n",n); + infid[level]->readInfo(type,rank,dims); // read in the data from src file + printf("Info is type(%u) rank(%u) dims[%u,%u,%u]\n", + type,rank,dims[0],dims[1],dims[2]); + data = new char[IObase::nBytes(type,rank,dims)]; // allocate space + infid[level]->read(data); // read the actual data in + amrfile->setLevel(level); // set the level to write to in amr output file + // read the floating point origin attribute + attribnum=infid[level]->readAttributeInfo("origin",type,nelements); + infid[level]->readAttribute(attribnum,origin); // read it + // write out the data to the AMR file + amrfile->write(origin,dims,data); // write the data out + delete data; // free the data storage + } + } +} diff --git a/src/chunkSpeed.cc b/src/chunkSpeed.cc new file mode 100644 index 0000000..757c7e1 --- /dev/null +++ b/src/chunkSpeed.cc @@ -0,0 +1,179 @@ +#include +#include +#include "IEEEIO.hh" +#include "vatoi.hh" +#include + +double MPI_Wtime(){ + timeval tv; + gettimeofday(&tv); + return tv.tv_sec + tv.tv_usec/1000000.0l; +} +int StupidProcLayoutSeive(int np,int decomp[3]){ + // Brute-Force method + // stupidly attempts all decomposition combinations + // and filters out unusable combinations. + // trys to select minimum surface area processor arrangement + int minarea = np*np*np; // impossibly high value + for(int i=1;i<=np;i++){ + for(int j=1;i*j<=np;j++){ + for(int k=1;i*j*k<=np;k++){ + if(i*j*k!=np) continue; + int area = i+j+k; // area metric (optimizing this weakly minimizes surface area) + if(area <-dims int,int,int> <-dimtype global|local>", + programname); + printf("\tnp: Number of virtual processors (pretends to be parallel)\n"); + printf("\tverbose: Opens file for reading after complete and prints all values.\n"); + printf("\tdims: Set the dimensions of the dataset. By default this is per-cpu.\n"); + printf("\t\tThis can be Global dimensions if you use -dimtype flag.\n"); + printf("\t\tDefault is 20,20,20.\n"); + printf("\tdimtype: \'global\' makes dimensions apply to the overall dataset\n"); + printf("\t\tregardless of number of processors and \'local\' is per-processor.\n"); + printf("\t\tThe default is per-processor.\n"); + } + void printStatus(FILE *f=stdout){ + fprintf(f,"%s: np=%u verbose=%u dims=%u,%u,%u dimtype=%s\n", + programname,np,verbose, + dims[0],dims[1],dims[2], + (dimtype==Local)?"Local":"Global"); + } +}; + +int main(int argc,char *argv[]){ + CommandLine cmdln(argc,argv); + + typedef int Array[3]; + //int origin[3],dims[3]; + Array *vorigin,*vdims; + int *origin,*dims; + int proclayout[3],area; + area=StupidProcLayoutSeive(cmdln.np,proclayout); + cmdln.printStatus(); + printf("Proclayout = %u : %u,%u,%u\n",area, + proclayout[0],proclayout[1],proclayout[2]); + vorigin = new Array[cmdln.np]; + vdims = new Array[cmdln.np]; + int i; + for(int p=0;pmaxsize) maxsize=size; + } + size = maxsize; // for convenience + } + float *data = new float[size]; + for(i=0;i0) + file->bufferOn(cmdln.bufsize); + double stime = MPI_Wtime(); + for(i=0;i<3;i++){ // do this 3 times + file->reserveChunk(IObase::Float32,3,globaldims); + for(int p=0;pwriteChunk(origin,dims,data); // should be same as MPIO file contents + } + } + double etime = MPI_Wtime(); + printf("Elapsed time to write=%lf\n",etime-stime); + printf("IO performance = %f Megabytes/sec\n", + IObase::nBytes(IObase::Float32,3,globaldims)/(1024*1024*(etime-stime))); + delete file; + delete data; +} diff --git a/src/convert2native.cc b/src/convert2native.cc new file mode 100644 index 0000000..eb14dae --- /dev/null +++ b/src/convert2native.cc @@ -0,0 +1,50 @@ +#include +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" +int main(int argc,char *argv[]){ + if(argc!=3){ + printf("Correct usage is %s \n",argv[0]); + exit(1); // failure code + } + IObase *infile=new IEEEIO(argv[1],IObase::Read); + if(!infile->isValid()){printf("cant read %s\n",argv[1]); exit(0);} + IObase *outfile=new IEEEIO(argv[2],IObase::Create); + if(!outfile->isValid()){ + printf("cant write %s\n",argv[2]); + delete infile; + exit(0); + } + for(int i=0;inDatasets();i++){ + int rank,dims[5]; + IObase::DataType type; + char *data; + + fprintf(stderr,".%u",i); + infile->readInfo(type,rank,dims); + { + int j,sz; + for(j=0,sz=1;jread(data); + outfile->write(type,rank,dims,data); + delete data; // OK, so I'm not being smart about mem allocation here + for(int j=0;jnAttributes();j++){ + char name[256]; // should be big enough + int length; + fprintf(stderr,"a"); + infile->readAttributeInfo(j,name,type,length); + data = new char[length * IObase::sizeOf(type)]; + infile->readAttribute(j,data); + outfile->writeAttribute(name,type,length,data); + delete data; + } + } + puts(""); + delete infile; + delete outfile; + return 0; // success code +} diff --git a/src/copyperf.cc b/src/copyperf.cc new file mode 100644 index 0000000..2f9950a --- /dev/null +++ b/src/copyperf.cc @@ -0,0 +1,43 @@ +#include +#include +#include +#include +#include "vatoi.hh" +#include "Timer.hh" + +int main(int argc,char *argv[]){ + // compare speed of bcopy to character loop + if(argc<2){ + puts("need to define buffer length"); + exit(0); + } + long size = vatoi(argv[1]); + int ntimes = 1; + register int n; + register long i; + if(argc>2) + ntimes = vatoi(argv[2]); + printf("Buffer is %lu bytes %u times\n",size,ntimes); + Timer t1,t2; + char *dst = new char[size]; + char *src = new char[size]; + // prime the caches + for(i=0;i +#include +#include +#include +#include +#include +#include +#include + + +#define MINBLOCKSIZE (1*1024) +#define MAXBLOCKSIZE (512*1024) /* multiple of MINBLOCKSIZE */ + +#define MAXFILESIZE (128*1024*1024) /* multiple of MAXBLOCKSIZE */ +#define DATAFILE "bla" +#define STATFILE "ffio.c" + +#define LAYERS "" /*bufa.bufsize=1024.num_buffers=1"*/ + +#ifdef T3E +#define S_IWRITE 00200 +#define S_IREAD 00400 +#endif + + +int main (int argc, char *argv []) +{ + int i, blocksize, rank=3; + int outfile; + void *data; + struct tms starttime, stoptime; + double utime, stime; + int open_mode; + int cblks; /* size = cblks * 512 words */ + long cbits; + char layers [256]; + struct ffsw ffopens_status; +#ifdef T3E + struct statfs statfs_info; +#endif + + + data = (void *) calloc (sizeof (char), MAXBLOCKSIZE); + if (! data) { + printf ("Couldn't allocate enough memory\n"); + exit (1); + } + + /* set file open parameters */ +#ifdef T3E +#if 0 + if (statfs (STATFILE, &statfs_info, sizeof (statfs_info), 0) < 0) { + perror ("statfs() failed: "); + exit (1); + } + printf ("secondary partitions' bitmask: 0x%lx\n", statfs_info.f_secparts); + + cbits = 0; + cbits |= (1 << 24); + cbits |= (1 << 06); + cbits |= (1 << 26); + cbits |= (1 << 23); +#endif + open_mode = O_WRONLY | O_CREAT | O_PLACE; + cbits = 0; + cblks = 100; +#else + open_mode = O_WRONLY | O_CREAT; + cbits = 0; + cblks = 0; +#endif + + for (blocksize = MINBLOCKSIZE; blocksize <= MAXBLOCKSIZE; blocksize *= 2) { + + times (&starttime); + + /* open the file */ + outfile = ffopens (DATAFILE, open_mode, S_IWRITE | S_IREAD, + cbits, cblks, &ffopens_status, LAYERS); + if (! outfile) { + perror ("ffopens() failed: "); + exit (1); + } + + /* system ("setf -n32768b:128b -c -p 24:06:23:26 bla");*/ + + /* write some data */ + for (i = 0; i < MAXFILESIZE / blocksize; i++) + if (ffwrite (outfile, data, blocksize) < 0) { + perror ("ffwrite() failed: "); + exit (1); + } + + /* close and remove the file */ + ffclose (outfile); + remove (DATAFILE); + + times (&stoptime); + utime = (stoptime.tms_utime -starttime.tms_utime) / (double) CLK_TCK; + stime = (stoptime.tms_stime -starttime.tms_stime) / (double) CLK_TCK; + printf ("blocksize [bytes]: %d\ttimes(u/s) [s]: %f %f\tbandwidth [MB/s]: %f\n", + blocksize, utime, stime, + MAXFILESIZE / (utime + stime) / (1024*1024)); + } + free (data); + + return (0); +} diff --git a/src/ioconvert.cc b/src/ioconvert.cc new file mode 100644 index 0000000..c816df0 --- /dev/null +++ b/src/ioconvert.cc @@ -0,0 +1,94 @@ +#include +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" +#include "HDFIO.hh" + +char *programname; +void usage(){ + printf("Correct usage is %s [-swapbytes]\n",programname); + puts("-swapbytes requests opposite of native byte-order for IEEEIO output"); + puts("The default is to write IEEE files in native byte-order"); + exit(1); // failure code +} + +int main(int argc,char *argv[]){ + programname=argv[0]; // for usage/error_exit routine + if(argc<3) usage(); + int i,swap; + int sindex=0,dindex=0,findex=0; + IObase *infile,*outfile; + HDFIO *hdffile; + int hdfin=0; + for(i=1;iisValid()){ + printf("cant read %s\n",argv[sindex]); + usage(); + } + + // for the outfile, + if(d_ext && !strcmp(d_ext,".hdf")) + outfile=new HDFIO(argv[dindex],IObase::Create); + else // assume its raw + outfile=new IEEEIO(argv[dindex],IObase::Create,swap); // swap only affects IEEEIO output + if(!outfile->isValid()){ + printf("cant write %s\n",argv[dindex]); + delete infile; + usage(); + } + + // Now do the conversion + for(i=0;inDatasets();i++){ + int rank,dims[5]; + IObase::DataType type; + char *data; + infile->seek(i); + if(hdfin && hdffile->isCoord()) continue; // skip coord vars + fprintf(stderr,".%u",i); + infile->readInfo(type,rank,dims); + { + int j,sz; + for(j=0,sz=1;jread(data); + outfile->write(type,rank,dims,data); + delete data; // OK, so I'm not being smart about mem allocation here + for(int j=0;jnAttributes();j++){ + char name[256]; // should be big enough + int length; + fprintf(stderr,"a"); + infile->readAttributeInfo(j,name,type,length); + data = new char[length * IObase::sizeOf(type)]; + infile->readAttribute(j,data); + outfile->writeAttribute(name,type,length,data); + delete data; + } + } + puts(""); + delete outfile; + // delete infile; + return 0; // success code +} diff --git a/src/ioinfo.cc b/src/ioinfo.cc new file mode 100644 index 0000000..91e487d --- /dev/null +++ b/src/ioinfo.cc @@ -0,0 +1,281 @@ +#include +#include +#include "Arch.h" +#include "IO.hh" +#include "IEEEIO.hh" + +#ifdef WITH_HDF4 +#include "HDFIO.hh" +#endif +#ifdef WITH_HDF5 +#include "H5IO.hh" +#endif + +struct CmdlnParams { + char *programname; + char *filename,*filetype; + int showdatasetinfo,showannotationinfo,showattribinfo; + int showdatamax,showannotationmax,showattribmax; + int showdatastats,showattribstats; + + void setDefaults(){ + programname=""; + filename=0; + filetype=0; + showdatasetinfo=1; + showannotationinfo=0; + showattribinfo=0; + showdatamax=0; + showannotationmax=0; + showattribmax=0; + showdatastats=0; + showattribstats=0; + } + + CmdlnParams(){ + setDefaults(); + } + + CmdlnParams(int argc,char *argv[]){ + setDefaults(); + parse(argc,argv); + } + + void parse(int argc,char *argv[]){ + programname=argv[0]; + for(int i=1;iisValid()){ + printf("%s: The file %s is not a valid %s file... sorry\n", + cmdln.programname,cmdln.filename,cmdln.filetype); + exit(1); + } + int ndatasets=infile->nDatasets(); + printf("Number of datasets=%d\n",ndatasets); + puts ("==========================="); + + // OK... now its time for da main event loop.... + for(i=0;ireadInfo(datatype,rank,dims); + + printf("Datatype=%s Rank=%u Dims=",Typename(datatype),rank); + for(j=0;j0 && dims[0]>0) + buffer=new char[idims[0] * IObase::sizeOf(datatype)]; + //infile->readChunk(buffer); + delete buffer; + delete idims; + } +#endif + int nattribs=infile->nAttributes(); + int nannotations=infile->nAnnotations(); + printf("Annotations: %u\n",nannotations); + printf("Attributes: %u\n",nattribs); + + if(cmdln.showattribinfo){ + for(j=0;jreadAttributeInfo(j,attribname,datatype,length); + printf("\tAttribute[%u] Name=%s Type=%s Length=%u\n", + j,attribname,Typename(datatype),length); + if(cmdln.showattribmax || cmdln.showattribstats){ + //printf("Length of Attribute=%u for total bytes=%u\n",length,IObase::sizeOf(datatype)); + void *dataptr; + dataptr=0; + if(IObase::sizeOf(datatype)>0 && length>0) + dataptr=new char[length * IObase::sizeOf(datatype)]; + else { + //puts("no data to display"); + continue; // no data to display + } + + infile->readAttribute(j,dataptr); + switch(datatype){ + case IObase::Char8:{ + char *d=(char*)dataptr; + d[length]='\0'; + //puts("show char data"); + printf("\t%s string[%u]:= %s\n",attribname,length,d); + }break; + case IObase::Int8: + case IObase::uInt8:{ + char *d=(char*)dataptr; + for(int k=0;k=0x20 && d[k]<=0x7e) + printf("\t%s[%u]:=%c\n",attribname,k,d[k]); + else { + int intchar=(unsigned int)(d[k]); + printf("\t%s[%u]:=%u\n",attribname,k,intchar); + } + }break; + case IObase::Int16:{ + short *d=(short*)dataptr; + for(int k=0;k-----"); + break; + } + if(dataptr) + delete dataptr; + } + } + } + } + puts("Closing file"); + delete infile; + puts("***done"); + return 0; +} diff --git a/src/rawSpeed.cc b/src/rawSpeed.cc new file mode 100644 index 0000000..9f7e4b0 --- /dev/null +++ b/src/rawSpeed.cc @@ -0,0 +1,83 @@ +#include +#include +#include "IEEEIO.hh" +#include "vatoi.hh" +#include +double MPI_Wtime(){ + timeval tv; + gettimeofday(&tv,0); + return tv.tv_sec + tv.tv_usec/1000000.0l; +} + +class CommandLine { +public: + int dims[3]; + char *programname; + int bufsize; + int ntrials; + void setDefaults(){ + dims[0]=dims[1]=dims[2]=128; + bufsize=0; + ntrials=40; + } + CommandLine(int argc,char *argv[]){ + setDefaults(); + parse(argc,argv); + } + void parse(int argc,char *argv[]){ + programname=argv[0]; + for(int i=1;i -n \n", + programname); + printf("\tdims: Set the dimensions of the dataset.\n"); + printf("\tn: Set number of trials of writing the dataset.\n"); + printf("\tbuffer: Set buffer cache size in bytes.\n"); + } + void printStatus(FILE *f=stdout){ + fprintf(f,"%s: dims=%u,%u,%u\n", + programname, + dims[0],dims[1],dims[2]); + } +}; + +int main(int argc,char *argv[]){ + CommandLine cmdln(argc,argv); + + int size=IObase::nElements(3,cmdln.dims); + int i; + float *data = new float[size]; + for(i=0;i0) file->bufferOn(cmdln.bufsize); + double stime = MPI_Wtime(); + for(i=0;ireserveStream(IObase::Float32,3,cmdln.dims); + file->writeStream(data,size); + } + if(file) delete file; // make sure the file is deleted + double etime = MPI_Wtime(); + printf("Elapsed time to write=%lf\n",etime-stime); + printf("IO performance = %f Megabytes/sec\n", + (float)(IObase::nBytes(IObase::Float32,3,cmdln.dims))*(float)(cmdln.ntrials)/(1024*1024*(etime-stime))); + delete data; +} + + diff --git a/src/testBigWriter.cc b/src/testBigWriter.cc new file mode 100644 index 0000000..7f71555 --- /dev/null +++ b/src/testBigWriter.cc @@ -0,0 +1,158 @@ +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" +#include "Reader.hh" +#include "Writer.hh" +#include "Timer.hh" +// #include "vatoi.hh" + +int main(int argc,char *argv[]){ + float *data = new float[256*256*256]; + float *buffer = data; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int rank=3; + int dims[3]={256,256,256}; + //int dims[3]={1,1,1}; + int ngigs = 5; + Timer t; + char label[31]; + Writer *writer; + IEEEIO *iefile; + IObase *outfile = iefile = new IEEEIO("data3d.raw",IObase::Create); + //iefile->bufferOn(128*1024); // set up a 128k write buffer + if(argc>=2) ngigs=atoi(argv[1]); + int ndatawrites = (int)(((double)ngigs*1024.0L*1024.0L*1024.0L) / (256.0L*256.0L*256.0L*4.0L)); + + printf("==========================================\n"); + printf("ngigs=%u ndatawrites=%u each of size %f megs\n", + ngigs,ndatawrites,256.0*256.0*256.0*4.0/(1024*1024)); + writer = new Writer(*outfile); + writer->setParams(rank,dims,IObase::Float32,origin,dx); + // data[0]=1.0; + int i; + for(i=0;i<256*256*256;i++) + data[i]=(float)i; + t.start(); + for(i=0;isetDims(dims); + writer->write(data); + //outfile->pause(); + //puts("paused"); + //outfile->resume(); + //puts("resumed"); + t.elapsedTimeSeconds(s,u,r); + sprintf(label,"mylabel.%04u",i); + printf("Cycle[%u] label[%s] %fGigs %fMegs/sec\n", + i,label, + (float)(((double)i*256.0L*256.0L*256.0L*4.0L)/(1024.0L*1024.0L*1024.0L)), + (float)(((double)i*256.0L*256.0L*256.0L*4.0L)/(1024.0L*1024.0L))/r); + //puts("after mylabel"); + outfile->writeAttribute("Mylabel",IObase::Char,31,label); + } + + /* puts("\tnow seek to end\n"); + outfile->seek(outfile->nDatasets()); + + puts("\treserve a chunk"); + outfile->reserveChunk(IObase::Float32,rank,dims); + puts("\tWrite a stream fo 40x40x40"); + outfile->writeStream(data,40*40*20); + puts("\tWrite the next stream of 40x40x20"); + outfile->writeStream(data+40*40*20,40*40*20);*/ + puts("\t writer done!!\n\n"); + + delete writer; + delete outfile; + /* + puts("Start appending"); + outfile = new IEEEIO("data3d.raw",IObase::Append); + printf("Isvalid? %d\n",outfile->isValid()); + + outfile->reserveStream(IObase::Float32,rank,dims); + outfile->writeStream(data,40*40*20); + outfile->writeStream(data+40*40*20,40*40*20); + printf("nrecords=%u\n",outfile->nDatasets()); + delete outfile; + + puts("Done appending : Reopen for reading."); + */ + //exit(0); + puts("start reader***************************"); + Reader *reader; + IObase *infile = new IEEEIO("data3d.raw",IObase::Read); + //printf("nrecords=%u\n",outfile->nDatasets()); + // reader = new Reader(*infile); + int ndatasets=infile->nDatasets(); + printf("Number of datasets=%d\n",ndatasets); + t.reset(); + t.start(); + for(i=0;ireadInfo(datatype,rank,dims); + printf("Data info dt=%u,rank=%u,dims=%u,%u,%u\n", + (int)(datatype),rank,dims[0],dims[1],dims[2]); + r=infile->read(buffer); + // r=infile->readStream(buffer,dims[0]*dims[1]*dims[2]); + t.elapsedTimeSeconds(s,u,rl); + printf("\tread %d elements\n",r); + printf("\tReadDataset[%u] %fGigs %fMegs/sec\n", + i, + (float)(((double)i*256.0L*256.0L*256.0L*4.0L)/(1024.0L*1024.0L*1024.0L)), + (float)(((double)i*256.0L*256.0L*256.0L*4.0L)/(1024.0L*1024.0L))/rl); + for(j=0;j<10;j++) + printf("Data[%u]=%f\n",j,buffer[j]); + puts("***done printing data"); + int nattribs=infile->nAttributes(); + printf("Number of Attributes=%d\n",nattribs); + for(j=0;jreadAttributeInfo(j,attribname,datatype,length); + printf("\tAttribute[%u] name=%s\n",j,attribname); + switch(datatype){ + case IObase::Float32:{ + //float buf[5]; + puts("Float"); + printf("length=%u\n",length); + } break; + case IObase::Float64:{ + double buf[5]; + puts("Double"); + printf("length=%u\n",length); + infile->readAttribute(j,buf); + for(int k=0;kreadAttribute(j,buf); + printf("len=%u val=[%s]\n",length,buf); + break; + } + default: + printf("unknown type %d\n",(int)datatype); + break; + } + } + } + //delete reader; + delete infile; + puts("done"); + return 0; +} diff --git a/src/testChunkWriter.cc b/src/testChunkWriter.cc new file mode 100644 index 0000000..e35c159 --- /dev/null +++ b/src/testChunkWriter.cc @@ -0,0 +1,64 @@ +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" + +int main(int argc,char *argv[]){ + float data[40*40*40]; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int rank=3; + int dims[3]={40,40,40}; + IObase *outfile = new IEEEIO("data3d.raw",IObase::Create); + int i,k; + for(i=0;i<40*40*40;i++) + data[i]=(float)i; + + puts("reserving chunk for z-slicing"); + outfile->reserveChunk(IObase::Float32,rank,dims); + for(i=0;i<40;i+=10){ + int cdims[3]={40,40,10}; + int corigin[3]={0,0,0}; + corigin[2]=i; + outfile->writeChunk(cdims,corigin,data); + } + + puts("reserving chunk for y-slicing"); + outfile->reserveChunk(IObase::Float32,rank,dims); + for(i=0;i<40;i+=10){ + int cdims[3]={40,10,40}; + int corigin[3]={0,0,0}; + corigin[1]=i; + outfile->writeChunk(cdims,corigin,data); + } + + puts("reserving chunk for x-slicing"); + outfile->reserveChunk(IObase::Float32,rank,dims); + for(i=0;i<40;i+=10){ + int cdims[3]={10,40,40}; + int corigin[3]={0,0,0}; + corigin[0]=i; + outfile->writeChunk(cdims,corigin,data); + } + + + puts("reserving chunk for domain-block chunking (10x10x10 blocks)"); + for(int x=0;x<40;x+=10){ + int cdims[3]={10,10,10}; + for(int y=0;y<40;y+=10){ + for(int z=0;z<40;z+=10){ + int corigin[3]; + corigin[0]=x; + corigin[1]=y; + corigin[2]=z; + outfile->writeChunk(cdims,corigin,data); + } + } + } + + puts("done... deleting"); + delete outfile; + puts("done"); + return 1; +} + diff --git a/src/testSockread.cc b/src/testSockread.cc new file mode 100644 index 0000000..723d1a8 --- /dev/null +++ b/src/testSockread.cc @@ -0,0 +1,29 @@ +#include +#include +#include "SockIOreader.hh" + +void main(int argc,char *argv[]){ + // Open a SockIOreader using 512k TCP windowsize + SockIOreader *reader= new SockIOreader("scratch.raw",7052,512*1024); + puts("begin\n"); + while(reader->nDatasets()<4){ + int ndsets=reader->nDatasets(); + fprintf(stderr,"reader->nDatasets()=%u\r",ndsets); + } + // now go through and verify each dataset + for(int i=0;i<4;i++){ + float buffer[16*16*16]; + int rank,dims[3]; + IObase::DataType type; + reader->seek(i); // seek to dataset + reader->readInfo(type,rank,dims); + printf("Dataset[%u]: Rank=%u Dims={%u,%u,%u}\n",i,rank,dims[0],dims[1],dims[2]); + reader->read(buffer); + puts("Print out dataset info to verify correctness"); + for(int j=0;j +#include +#include "SockIOwriter.hh" + +void main(int argc,char *argv[]){ + // Open a SockIOwriter using 512k TCP windowsize + SockIOwriter *writer= new SockIOwriter("localhost",7052,512*1024); + puts("begin\n"); + float data[16*16*16]; // send 64^3 data for performance tests + int rank=3; + int dims[3]={16,16,16}; + + for(int i=0;i<16*16*16;i++) data[i]=(float)i; + for(i=0;i<4;i++){ + fprintf(stderr,"Writing Dataset %u\n",i); + fprintf(stderr,"Wrote %u characters\n", + writer->write(IObase::Float32,rank,dims,data)); + fprintf(stderr,"\tWrote Dataset %u\n",i); + sleep(1); + } +} diff --git a/src/testWriter.cc b/src/testWriter.cc new file mode 100644 index 0000000..d5c4ed2 --- /dev/null +++ b/src/testWriter.cc @@ -0,0 +1,80 @@ +#include +#include +#include "IO.hh" +#include "IEEEIO.hh" +// #include "Reader.hh" +#include "Writer.hh" + +int main(int argc,char *argv[]){ + float data[40*40*40]; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int i,rank=3; + int dims[3]={40,40,40}; + Writer *writer; + IObase *outfile = new IEEEIO("data3d.raw",IObase::Create); + writer = new Writer(*outfile); + writer->setParams(rank,dims,IObase::Float32,origin,dx); + // data[0]=1.0; + for(i=0;i<40*40*40;i++) + data[i]=(float)i; + for(i=0;i<2;i++) + writer->write(data); + + delete writer; + delete outfile; +#if 0 + Reader *reader; + IObase *infile = new IEEEIO("data3d.raw",IObase::Read); + reader = new Reader(*infile); + + for(i=0;indatasets;i++){ + int j; + float buffer[40*40*40]; + for(j=0;j<40*40*40;j++) buffer[j]=0; + (*reader)[i].read(buffer); + for(j=0;j<10;j++) + printf("Data[%u]=%f\n",j,buffer[j]); + puts("***done printing data"); + for(j=0;j<(*reader)[i].nattributes;j++){ + //IOdataset ds=(*reader)[i]; + //char c1,c2; + //int attrlen; + //printf("\tnattribs=%u\n",ds.nattributes); + //c1=ds.attribute[j].name[0]; + //c2=ds.attribute[j].name[0]; + //printf("\tFirst two chars of name [%c][%c]\n",c1,c2); + //attrlen=ds.attribute[j].nelements; + printf("\tAttribute[%u] name=%s\n",j,(*reader)[i].attribute[j].name); + long length=(*reader)[i].attribute[j].nelements; + switch((*reader)[i].attribute[j].datatype){ + case IObase::Float32:{ + //float buf[5]; + puts("Float"); + printf("length=%u\n",length); + } break; + case IObase::Float64:{ + double buf[5]; + puts("Double"); + printf("length=%u\n",length); + (*reader)[i].attribute[j].read(buf); + for(int k=0;k +#include +#include + +#include "FlexArrayTmpl.H" + +struct InnerContainer { + int num; + + InnerContainer(InnerContainer &src){ + this->num=src.num; + } + InnerContainer &operator=(InnerContainer &src){ + if(this==&src) return src; + this->num=src.num; + return *this; + } + InnerContainer(){ + printf("\tNew InnerContainer %lu\n",(unsigned long)this); + num=-1; /* uninitialized */ + } + ~InnerContainer(){ + printf("\tInnerContainer[%lu] destruct %d\n",(unsigned long)this,num); + } +}; + +struct OuterContainer { + int num; + FlexArray inner; + OuterContainer(OuterContainer &src){ + this->num=src.num; + this->inner=src.inner; + } + OuterContainer &operator=(OuterContainer &src){ + if(this==&src) return src; + this->num=src.num; + this->inner=src.inner; + return *this; + } + OuterContainer(){ + printf("New OuterContainer %lu\n",(unsigned long)this); + num=-1; + } + ~OuterContainer(){ + printf("OuterContainer[%lu] destruct %d innersize=%u\n", + (unsigned long)this,num,inner.getSize()); + } +}; + +struct Container { + FlexArray outer; + + Container(int sz){ + int i,j; + outer.setSize(sz); + for(i=0;i +#include +#include "IO.hh" +#include "HDFIO.hh" + +int main(int argc,char *argv[]){ + float data[40*40*40]; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int i; + int rank=3; + int dims[3]={40,40,40}; + IObase *infile; + if(argc>1) + infile = new HDFIO(argv[1],IObase::Read); + else + infile = new HDFIO("data3d.raw",IObase::Read); + // reader = new Reader(*infile); + int ndatasets=infile->nDatasets(); + printf("Number of datasets=%d\n",ndatasets); + for(i=0;ireadInfo(datatype,rank,dims); + printf("Data info dt=%u,rank=%u,dims=%u,%u,%u\n", + (int)(datatype),rank,dims[0],dims[1],dims[2]); + infile->read(buffer); + for(j=0;j<10;j++) + printf("Data[%u]=%f\n",j,buffer[j]); + puts("***done printing data"); + int nattribs=infile->nAttributes(); + printf("Number of Attributes=%d\n",nattribs); + for(j=0;jreadAttributeInfo(j,attribname,datatype,length); + printf("\tAttribute[%u] name=%s\n",j,attribname); + switch(datatype){ + case IObase::Float32:{ + //float buf[5]; + puts("Float"); + printf("length=%u\n",length); + } break; + case IObase::Float64:{ + double buf[5]; + puts("Double"); + printf("length=%u\n",length); + infile->readAttribute(j,buf); + for(int k=0;k +#include +#include "IEEEIO.hh" + +void main(int argc,char *argv[]){ + int i; + float bogusdata[16*16]; + //float attribdata[128]; + int bogusdims[2]={16,16}; + int bogusrank=2; + IO *outfile = new IEEEIO("testfile.raw",IO::Create); + if(!outfile->isValid()){ + perror("IO open failed"); + exit(0); + } + else puts("Writing File"); + for(i=0;i<16*16;i++) + bogusdata[i]=(float)i; + char *string="I am annotation[0]"; + char *name="attrib0"; + for(i=0;i<5;i++){ + outfile->write(IO::Float32,bogusrank,bogusdims,bogusdata); + (string[16])='0'; + for(int j=0;jwriteAnnotation(string); + name[6]='0'; + //if(i<4) + for(j=0;jwriteAttribute(name,IO::Float32,2*j,bogusdata+j); + + } + delete outfile; + puts("##################REOPEN#######################"); + outfile = new IEEEIO("testfile.raw",IO::Read); + + if(!outfile->isValid()){ + perror("IO open failed"); + exit(0); + } + for(i=0;i<10;i++){ + IO::DataType dt; + int idt; + int rank,dims[3]; + for(int j=0;j<16*16;j++) bogusdata[j]=0.0; // clear bogusdata + if(outfile->readInfo(dt,rank,dims)<=0){ + puts("***********************end****************"); + break; + } + outfile->read(bogusdata); + printf("----------------------Data Read[%u]-------------------\n",i); + idt=dt; + printf("\tDatatype=%u rank=%u\n",idt,rank); + for(j=0;j<3;j++) printf("\tDims[%u]=%u\n",j,dims[j]); + puts("+++++++Annotations"); + for(j=0;jnAnnotations();j++){ + char buffer[128]; + outfile->readAnnotation(j,buffer,sizeof(buffer)); + printf("\tAnnotation[%u]=[%s]\n",j,buffer); + } + puts(""); + for(j=0;j<16*16;j++) printf("data[%4u]=%f\n",j,bogusdata[j]); + } + printf("Seek=%d\n",outfile->seek(3)); + for(i=0;i<10;i++){ + IO::DataType dt; + int idt; + int rank,dims[3]; + for(int j=0;j<16*16;j++) bogusdata[j]=0.0; // clear bogusdata + if(outfile->readInfo(dt,rank,dims)<=0){ + puts("***********************end****************"); + break; + } + outfile->read(bogusdata); + printf("----------------------Data Read[%u]-------------------\n",i); + idt=dt; + printf("\tDatatype=%u rank=%u\n",idt,rank); + for(j=0;j<3;j++) printf("\tDims[%u]=%u\n",j,dims[j]); + puts("+++++++Annotations"); + for(j=0;jnAnnotations();j++){ + char buffer[128]; + outfile->readAnnotation(j,buffer,sizeof(buffer)); + printf("\tAnnotation[%u]=[%s]\n",j,buffer); + } + puts("xxxxxxxAttribs"); + int buflen; + IO::DataType attribtype; + for(j=0;jnAttributes();j++){ + float buffer[128]; + char namebuf[128]; + IO::DataType dt; + outfile->readAttributeInfo(j,namebuf,dt,buflen); + printf("\tAttribname[%u] = [%s]\n",j,namebuf); + outfile->readAttribute(j,buffer); + for(int k=0;kreadAttributeInfo("attrib2",attribtype,buflen))>=0){ + float buffer[128]; + outfile->readAttribute(i,buffer); + puts("&&&&&Read [attrib2]"); + for(int k=0;k +#include +#include "IO.hh" +#include "IEEEIO.hh" +#include "Reader.hh" +#include "Writer.hh" + +int main(int argc,char *argv[]){ + float data[4*4*8]; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int i; + int rank=3; + int dims[3]={4,4,8}; + Reader *reader; + IObase *infile; + if(argc>1) + infile = new IEEEIO(argv[1],IObase::Read); + else + infile = new IEEEIO("data3d.raw",IObase::Read); + // reader = new Reader(*infile); + int ndatasets=infile->nDatasets(); + printf("Number of datasets=%d\n",ndatasets); + for(i=0;ireadInfo(datatype,rank,dims); + printf("Data info dt=%u,rank=%u,dims=%u,%u,%u\n", + (int)(datatype),rank,dims[0],dims[1],dims[2]); + infile->read(buffer); + for(j=0;j<8*4*4;j++) + printf("Data[%u]=%f\n",j,buffer[j]); + puts("***done printing data"); + int nattribs=infile->nAttributes(); + printf("Number of Attributes=%d\n",nattribs); + for(j=0;jreadAttributeInfo(j,attribname,datatype,length); + printf("\tAttribute[%u] name=%s\n",j,attribname); + switch(datatype){ + case IObase::Float32:{ + //float buf[5]; + puts("Float"); + printf("length=%u\n",length); + } break; + case IObase::Float64:{ + double buf[5]; + puts("Double"); + printf("length=%u\n",length); + infile->readAttribute(j,buf); + for(int k=0;k +#include +#include "IO.hh" +#include "IEEEIO.hh" +#include "Reader.hh" +#include "Writer.hh" + +int main(int argc,char *argv[]){ + float data[40*40*40]; + double origin[3]={0,0,0}; + double dx[3]={0.25,0.25,0.25}; + int rank=3; + int dims[3]={40,40,40}; + //int dims[3]={1,1,1}; + char label[31]; + Writer *writer; + IEEEIO *iefile; + IObase *outfile = iefile = new IEEEIO("data3d.raw",IObase::Create); + //iefile->bufferOn(128*1024); // set up a 128k write buffer + writer = new Writer(*outfile); + writer->setParams(rank,dims,IObase::Float32,origin,dx); + // data[0]=1.0; + int i; + for(i=0;i<40*40*40;i++) + data[i]=(float)i; + for(i=0;i<4;i++){ + dims[2]=10+i*10; + writer->setDims(dims); + writer->write(data); + //outfile->pause(); + //puts("paused"); + //outfile->resume(); + //puts("resumed"); + sprintf(label,"mylabel.%04u",i); + //puts("after mylabel"); + outfile->writeAttribute("Mylabel",IObase::Char,31,label); + } + + /* puts("\tnow seek to end\n"); + outfile->seek(outfile->nDatasets()); + + puts("\treserve a chunk"); + outfile->reserveChunk(IObase::Float32,rank,dims); + puts("\tWrite a stream fo 40x40x40"); + outfile->writeStream(data,40*40*20); + puts("\tWrite the next stream of 40x40x20"); + outfile->writeStream(data+40*40*20,40*40*20);*/ + puts("\t writer done!!\n\n"); + + delete writer; + delete outfile; + /* + puts("Start appending"); + outfile = new IEEEIO("data3d.raw",IObase::Append); + printf("Isvalid? %d\n",outfile->isValid()); + + outfile->reserveStream(IObase::Float32,rank,dims); + outfile->writeStream(data,40*40*20); + outfile->writeStream(data+40*40*20,40*40*20); + printf("nrecords=%u\n",outfile->nDatasets()); + delete outfile; + + puts("Done appending : Reopen for reading."); + */ + //exit(0); + puts("start reader***************************"); + Reader *reader; + IObase *infile = new IEEEIO("data3d.raw",IObase::Read); + //printf("nrecords=%u\n",outfile->nDatasets()); + // reader = new Reader(*infile); + int ndatasets=infile->nDatasets(); + printf("Number of datasets=%d\n",ndatasets); + for(i=0;ireadInfo(datatype,rank,dims); + printf("Data info dt=%u,rank=%u,dims=%u,%u,%u\n", + (int)(datatype),rank,dims[0],dims[1],dims[2]); + //r=infile->read(buffer); + r=infile->readStream(buffer,dims[0]*dims[1]*dims[2]); + printf("read %d elements\n",r); + for(j=0;j<10;j++) + printf("Data[%u]=%f\n",j,buffer[j]); + puts("***done printing data"); + int nattribs=infile->nAttributes(); + printf("Number of Attributes=%d\n",nattribs); + for(j=0;jreadAttributeInfo(j,attribname,datatype,length); + printf("\tAttribute[%u] name=%s\n",j,attribname); + switch(datatype){ + case IObase::Float32:{ + //float buf[5]; + puts("Float"); + printf("length=%u\n",length); + } break; + case IObase::Float64:{ + double buf[5]; + puts("Double"); + printf("length=%u\n",length); + infile->readAttribute(j,buf); + for(int k=0;kreadAttribute(j,buf); + printf("len=%u val=[%s]\n",length,buf); + break; + } + default: + printf("unknown type %d\n",(int)datatype); + break; + } + } + } + //delete reader; + delete infile; + puts("done"); + return 0; +} diff --git a/src/vatoi.cc b/src/vatoi.cc new file mode 100644 index 0000000..9044cc4 --- /dev/null +++ b/src/vatoi.cc @@ -0,0 +1,22 @@ +#include "vatoi.hh" +#include +#include +#include + +int vatoi(char *p){ + char param[128]; + strcpy(param,p); + char *offset; + int n; + if((offset=strchr(param,'k')) || (offset=strchr(param,'K')) ){ + *offset='\0'; + n=1024; + } + else if((offset=strchr(param,'m')) || (offset=strchr(param,'M')) ){ + *offset='\0'; + n=1024*1024; + } + else n=1; + n*=atoi(param); + return n; +} diff --git a/src/vatoi.hh b/src/vatoi.hh new file mode 100644 index 0000000..be25080 --- /dev/null +++ b/src/vatoi.hh @@ -0,0 +1,6 @@ +#ifndef __VATOI_H_ +#define __VATOI_H_ + +int vatoi(char *p); + +#endif /* __VATOI_H_ */ diff --git a/src/writef77.f b/src/writef77.f new file mode 100644 index 0000000..36a1310 --- /dev/null +++ b/src/writef77.f @@ -0,0 +1,17 @@ + + subroutine openf77() + OPEN(UNIT=10,FILE='f77speed.unf',FORM='UNFORMATTED') + RETURN + END + + subroutine writef77(array) + REAL*8 array(64,64,64) + WRITE(10) array + RETURN + END + + subroutine closef77() + CLOSE(10) + RETURN + END + diff --git a/src/xmlview.cc b/src/xmlview.cc new file mode 100644 index 0000000..bad9443 --- /dev/null +++ b/src/xmlview.cc @@ -0,0 +1,272 @@ +/*-------------------< >--------------------------- + +Currently missing markup for EXTENTS and DIMSCALES +If an attribute is a text string, then it will print the attribute +with a tag of . Otherwise, it will just provide information +about the attribute (the range, length, type, name... etc). + +Does not provide refs for data right now, but I don't think they +are necessary (the query will need to be based on index anyways). + +DTD for HDF XML Markup +---------------------- + + + + + + + + + + + + + + ----------------------------------------------------*/ +#include +#include +#ifdef WITH_HDF4 +#include +#endif +#ifdef WITH_HDF5 +#include +#endif +#include + +char filedrivername[128]; + +#define FindMinMax(dt) { \ + dt *data = (dt*)buffer; \ + min = max = (double)(data[0]); \ + for(int i=1;imax) max=v; \ + } \ + } + +// Print an XML tag for the name of the data element +// tabovername +void PrintNameXML(char *tab,// leading whitespace (for formating) + char *name); +// Print an XML tag for the dimensions of an array +// tabover dim1,dim2..dimN +void PrintDimsXML(char *tab,// leading whitespace (for formating) + int rank, + int *dims); +// Print an XML tag for the length of an array +// tabover length +void PrintLengthXML(char *tab,// leading whitespace (for formating) + int length); +// Print an XML tag for the data type of an array +// Must be one of Float32,Float64,Int16,Int32,Int64,Byte,Char +// Byte indicates data whereas Char indicates text (a string) +// even though both ar 8 bits +// tabover datatype +void PrintTypeXML(char *tab, // OK, you get the picture... + IObase::DataType datatype); + +// Compute the min and max for a data array. +void GetRangeXML(IObase::DataType datatype, + int nelem, + char *buffer, + double &min, + double &max); +// Print an XML tag for the Range of the data (the min/max) +// Uses GetRangeXML. +// tabover min,max +// Problem is that this forces a load of the dataset into memory +// which can be slow and memory intensive. Need to change this +// so that it can load a subset of the data into RAM (load in +// 8k blocks rather than the entire thing). +void PrintRangeXML(char *tab, + IObase::DataType datatype, + int nelem, + char *buffer); + +int main(int argc,char *argv[]){ + sprintf(filedrivername,"ERROR"); + if(argc<2){ + printf("missing filename\n"); + exit(0); + } + IObase *file = 0; + + IEEEIO *ifile = new IEEEIO(argv[1],IObase::Read); + if(!ifile->isValid()){ delete ifile; ifile=0;} + else { + sprintf(filedrivername,"IEEEIO"); + file = ifile; // success + } + +#ifdef WITH_HDF4 + HDFIO *hfile=0; + if(!file){ + hfile = new HDFIO(argv[1],IObase::Read); + if(!hfile->isValid()) {delete hfile; hfile=0;} + else { + sprintf(filedrivername,"HDF4"); + file = hfile; // success + } + } +#else + IObase *hfile=0; +#endif + +#ifdef WITH_HDF5 + H5IO *h5file=0; + if(!file){ + h5file = new H5IO(argv[1],IObase::Read); + if(!h5file->isValid()) {delete h5file; h5file=0;} + else { + sprintf(filedrivername,"HDF5"); + file = h5file; // success + } + } +#endif + + if(!file){ + printf("could not open file %s\n",argv[1]); + exit(0); + } + printf("<%s>\n",filedrivername); + // now say anything you want about the HDF file + for(int n=0,ndatasets=file->nDatasets();n");// begin an sds + if(hfile){ +#ifdef WITH_HDF4 + hfile->readInfo(name,datatype,rank,dims); +#endif + } + else{ + name[0]='\0'; + file->readInfo(datatype,rank,dims); + } + if(strlen(name)>0) + PrintNameXML("\t\t",name); + PrintTypeXML("\t\t",datatype); + PrintDimsXML("\t\t",rank,dims); + if(datatype!=IObase::Char){ + char *buffer = new char[IObase::nBytes(datatype,rank,dims)]; + file->read(buffer); // read the data + PrintRangeXML("\t\t",datatype,IObase::nElements(rank,dims),buffer); + delete buffer; + } + // for now, skip the annotations + for(int an=0,nannotations=file->nAnnotations();anreadAnnotationInfo(an,length); + printf("\t\t %u\n",length); + } + // cycle through each of the attributes + for(int a=0,nattribs=file->nAttributes();a\n"); + file->readAttributeInfo(a,name,datatype,length); + PrintNameXML("\t\t ",name); + PrintTypeXML("\t\t ",datatype); + PrintLengthXML("\t\t ",length); + if(datatype==IObase::Char){ // its a string, so print it + char *s = new char[length+1]; + file->readAttribute(a,s); + printf("\t\t %s\n",s); + delete s; + } + else { + char *buffer = new char[IObase::nBytes(datatype,1,&length)]; + file->readAttribute(a,buffer); // read the data + PrintRangeXML("\t\t",datatype,length,buffer); + delete buffer; + } + printf("\t\t\n"); + } + puts("\t"); + } + printf("\n",filedrivername); + delete file; + return 0; +} + + +void PrintNameXML(char *tab,char *name){ + printf("%s%s\n",tab,name); +} + +void PrintDimsXML(char *tab,int rank,int *dims){ + printf("%s",tab,rank); + printf("%u",dims[0]); for(int i=1;i"); +} + +void PrintLengthXML(char *tab,int length){ + printf("%s%u\n",tab,length); +} + +void PrintTypeXML(char *tab,IObase::DataType datatype){ + printf("%s",tab); + switch(datatype){ + case IObase::Float32: + printf("Float32"); + break; + case IObase::Float64: + printf("Float64"); + break; + case IObase::Int16: + printf("Int16"); + break; + case IObase::Int32: + printf("Int32"); + break; + case IObase::Int64: + printf("Int64"); + break; + case IObase::Byte: + printf("Byte"); + break; + case IObase::Char: + printf("Char"); + break; + default: + printf("Unknown(%d)",(int)datatype); + } + puts(""); +} + + +void GetRangeXML(IObase::DataType datatype,int nelem,char *buffer, + double &min,double &max){ + switch(datatype){ + case IObase::Float32: + FindMinMax(float); + break; + case IObase::Float64: + FindMinMax(double); + break; + case IObase::Int16: + FindMinMax(short); + break; + case IObase::Int32: + FindMinMax(int); + break; + case IObase::Int64: + FindMinMax(long); // well. long long for 32bit compiles + break; + case IObase::Byte: + case IObase::Char: + FindMinMax(char); + break; + default: + //printf("Unknown(%d)",(int)datatype); + return; // don't print + } +} +void PrintRangeXML(char *tab,IObase::DataType datatype,int nelem,char *buffer){ + // now compute the range in a datatype-dependent manner + double min,max; + GetRangeXML(datatype,nelem,buffer,min,max); + printf("%s%lf,%lf\n",tab,min,max); +} -- cgit v1.2.3