From ff5c80e7f3d2d2d3f8ca612488aa229c27bbdd89 Mon Sep 17 00:00:00 2001 From: allen Date: Wed, 20 Sep 2000 10:58:58 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. git-svn-id: http://svn.cactuscode.org/arrangements/CactusIO/IOJpeg/trunk@3 eff87b29-5268-4891-90a3-a07138403961 --- src/DumpVar.c | 155 +++++++++++++++++++++++++++ src/GHExtension.c | 104 ++++++++++++++++++ src/IOJpeg.h | 56 ++++++++++ src/JPEG.c | 301 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/Output2D.c | 182 +++++++++++++++++++++++++++++++ src/ParseGeometry.c | 142 +++++++++++++++++++++++++ src/Startup.c | 47 ++++++++ src/Write2D.c | 168 +++++++++++++++++++++++++++++ src/make.code.defn | 9 ++ 9 files changed, 1164 insertions(+) create mode 100644 src/DumpVar.c create mode 100644 src/GHExtension.c create mode 100644 src/IOJpeg.h create mode 100644 src/JPEG.c create mode 100644 src/Output2D.c create mode 100644 src/ParseGeometry.c create mode 100644 src/Startup.c create mode 100644 src/Write2D.c create mode 100644 src/make.code.defn (limited to 'src') diff --git a/src/DumpVar.c b/src/DumpVar.c new file mode 100644 index 0000000..96613da --- /dev/null +++ b/src/DumpVar.c @@ -0,0 +1,155 @@ + +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "CactusPUGH/PUGHSlab/src/PUGHSlab.h" +#include "IOJpeg.h" + +int IOJpeg_Output(cGH *GH, int index, int timelevel, CCTK_REAL *data, + int sdim, int *hsize, int vtype, FILE *fid); + + +int IOJpeg_DumpVar (cGH *GH, int index, int timelevel, IOJpegGeo_t *geo, FILE *fid) +{ + DECLARE_CCTK_PARAMETERS + void *data=NULL; + int *hsizes, slabstart[SLABSKEL_MAXDIM]; + IOJpegGH *ssGH; + int vtype; + int idim, vdim; + + int sdir[3] = {0,0,0}; + + /* Get the handle for StreamedHDF5 extensions */ + ssGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + /* Allocate buffer to hold actual slab sizes */ + hsizes = (int*)malloc(geo->sdim*sizeof(int)); + + vdim= geo->vdim; + + /* Checks for vartype can go here */ + vtype = CCTK_VarTypeI (index); + + /* TEMPORARY FIX DUE TO INCONSISTENT DIR SPECIFICATION */ + /* direction vector of 1d line in 3d volume */ + if (geo->sdim==1) { + sdir[0] = (geo->direction[0]==0) ? 1:0; + sdir[1] = (geo->direction[0]==1) ? 1:0; + sdir[2] = (geo->direction[0]==2) ? 1:0; + } + /* norm vector of 2d surface in 3d volume */ + else if (geo->sdim==2) + { + sdir[0] = ((geo->direction[0]==1)&&(geo->direction[1]==2)) ? 1:0; + sdir[1] = ((geo->direction[0]==0)&&(geo->direction[1]==2)) ? 1:0; + sdir[2] = ((geo->direction[0]==0)&&(geo->direction[1]==1)) ? 1:0; + } + /* spanning directions for 3d */ + else if (geo->sdim==3) + { + sdir[0] = geo->direction[0]; + sdir[1] = geo->direction[1]; + sdir[2] = geo->direction[2]; + } + else + { + char *fullname = CCTK_FullName (index); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "No 0-dim extraction possible: '%s'", fullname); + free (fullname); + return (-1); + } + + /* Get the start indices for the slab from slab_start. */ + /* Slab_start from the geo structure is not a true start index, it is currently + used as the intersection point of n surfaces , that's why two entries + have to be set to zero in the case of a surface (one entry for line) FIXME */ + for (idim=0;idimslab_start[idim]; + for (idim=0;idimsdim;idim++) + slabstart[geo->direction[idim]]=0; + + /* Data Extraction takes place, data will be gathered onto processor 0 + hyperslab data will be in data, + hyperslab sizes: hsizes[SLAB_DIM]. + */ + if (Hyperslab_GetHyperslab (GH, 0, index, timelevel, geo->sdim, slabstart, + sdir, geo->length, geo->downs, + &data, hsizes) < 0) + { + char *fullname = CCTK_FullName (index); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Failed to extract hyperslab for variable '%s'", fullname); + free (fullname); + return (-1); + } + + /* Output routine for valid fid (was set in Write nD) */ + if (fid) + { + if (IOJpeg_Output(GH, index, timelevel, data, + geo->sdim, hsizes, vtype, fid)<0) { + char *fullname = CCTK_FullName (index); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOJpeg_Output failed for variable '%s'", fullname); + free (fullname); + return (-1); + } + } + + if (data) + free (data); + + return (0); +} + + + +int IOJpeg_Output(cGH *GH, int index, int timelevel, CCTK_REAL *data, + int sdim, int *hsize, int vtype, FILE *fid) +{ + DECLARE_CCTK_PARAMETERS + + unsigned char *dataout=(unsigned char *)malloc(3*hsize[0]*hsize[1]); + CCTK_REAL min,max; + + if (sdim!=2) return(-1); + + if (CCTK_Equals(colormap,"custom")) + { + min = colormap_min; + max = colormap_max; + } + else + { + int reduction_handle,ierr; + reduction_handle = CCTK_ReductionHandle ("maximum"); + ierr = CCTK_Reduce (GH, 0, reduction_handle, 1, + CCTK_VARIABLE_REAL,&max, 1, index); + reduction_handle = CCTK_ReductionHandle ("minimum"); + ierr = CCTK_Reduce (GH, 0, reduction_handle, 1, + CCTK_VARIABLE_REAL,&min, 1, index); + } + + AutoColorDataSlice(hsize[0], + hsize[1], + data, + dataout, + min, + max, + colormap_bias, + colormap_factor); + + WriteJPEGToFileRGB(hsize[0], + hsize[1], + dataout, + colormap_quality, + fid); + + return(1); +} + diff --git a/src/GHExtension.c b/src/GHExtension.c new file mode 100644 index 0000000..a82d359 --- /dev/null +++ b/src/GHExtension.c @@ -0,0 +1,104 @@ +#include +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "cctk_Arguments.h" + +#include "CactusPUGH/PUGH/src/include/pugh.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "IOJpeg.h" + +void IOJpeg_DefaultGeo(cGH *GH, int sdim, IOJpegGeo_t *geo); + +void *IOJpeg_SetupGH (tFleshConfig *config, int convergence_level, cGH *GH) +{ + int numvars,iv; + IOJpegGH *newGH; + + numvars = CCTK_NumVars (); + + newGH = (IOJpegGH *) malloc (sizeof (IOJpegGH)); + newGH->do_out2D = (char *) malloc (numvars * sizeof (char)); + newGH->out2D_last = (int *) malloc (numvars * sizeof (int)); + + /* Allocate geometry structure for each grid variable/array */ + newGH->out_geo = (IOJpegGeo_t**) malloc(SLABSKEL_MAXDIM * sizeof (IOJpegGeo_t)); + for (iv=0;ivout_geo[iv] = (IOJpegGeo_t*) malloc(SLABSKEL_MAXDIM * sizeof (IOJpegGeo_t)); + + return (newGH); +} + + +int IOJpeg_InitGH (cGH *GH) +{ + DECLARE_CCTK_PARAMETERS + int inum; + IOJpegGH *myGH; + const cParamData *paramdata; + + myGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + myGH->out2D_every = out_every > 0 ? out_every : -1; + if (out2D_every > 0) + myGH->out2D_every = out2D_every; + IOUtil_ParseVarsForOutput (out2D_vars, myGH->do_out2D); + + for (inum=0; inumout2D_last [inum] = -1; + } + + /* Deal with the output directories */ + /* Check whether "outdirXD" was set. + If so take this dir otherwise default to "IO::outdir" */ + paramdata = CCTK_ParameterData ("out2D_dir", CCTK_THORNSTRING); + myGH->outdir2D = (paramdata && paramdata->n_set > 0) ? + strdup (out2D_dir) : strdup (outdir); + + /* create the output dir */ + if (CCTK_MyProc (GH) == 0) + { + int i; + i = CCTK_CreateDirectory (0755, myGH->outdir2D); + if (i < 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOASCII_InitGH: Problem creating 2D output directory '%s'", + myGH->outdir2D); + } + if (i > 0) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOASCII_InitGH: 2D output directory '%s' already exists", + myGH->outdir2D); + } + } + + myGH->fileList_2D = NULL; + return (0); +} + + + +void IOJpeg_SliceCenterSetup(CCTK_ARGUMENTS) +{ + DECLARE_CCTK_PARAMETERS + int inum,idim; + IOJpegGeo_t geo_default; + IOJpegGH *myGH; + + myGH = (IOJpegGH *) cctkGH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + /* Loop over all slab dimension */ + for (idim=0;idimout_geo[inum][idim] = geo_default; + } + +} diff --git a/src/IOJpeg.h b/src/IOJpeg.h new file mode 100644 index 0000000..75355e2 --- /dev/null +++ b/src/IOJpeg.h @@ -0,0 +1,56 @@ +#ifdef __cplusplus +extern "C" { +#endif + +#define SLABSKEL_MAXDIM 4 + +#include "StoreNamedData.h" + +/* structure holding information on the output geometry */ +typedef struct IOJpegGeo +{ + int vdim; /* dimension of the gridvariable (dynamic) */ + int sdim; /* dimension of the slab (dynamic) */ + int direction[SLABSKEL_MAXDIM]; /* direction of slab (by parameter) */ + int slab_start[SLABSKEL_MAXDIM];/* global start index (by parameter) */ + int length[SLABSKEL_MAXDIM]; /* requested index slab length (by parameter) */ + int actlen[SLABSKEL_MAXDIM]; /* actual index slab length (by PUGHSlab)*/ + int downs[SLABSKEL_MAXDIM]; /* downsampling (by parameter) */ +} IOJpegGeo_t; + + +/* IOJpeg GH extension structure */ +typedef struct IOJpegGH { + + /* how often to output */ + int out2D_every; + + /* flags indicating output for var [i] */ + char *do_out2D; + + /* directories in which to output */ + char *outdir2D; + + /* the last iteration output */ + int *out2D_last; + + /* geometry information (downsampling, zooming, etc.) */ + IOJpegGeo_t **out_geo; + + /* database for names of output files that were already created */ + pNamedData *fileList_2D; + + +} IOJpegGH; + +/* function prototypes */ +int IOJpeg_Write3D (cGH *GH, int index, const char *alias); +int IOJpeg_Write2D (cGH *GH, int index, const char *alias); +int IOJpeg_Write1D (cGH *GH, int index, const char *alias); + +int IOJpeg_DumpVar (cGH *GH, int index, int timelevel, IOJpegGeo_t *geo, FILE *fid); + + +#ifdef __cplusplus +} // extern "C" +#endif diff --git a/src/JPEG.c b/src/JPEG.c new file mode 100644 index 0000000..0faee6a --- /dev/null +++ b/src/JPEG.c @@ -0,0 +1,301 @@ +#include "cctk.h" + +#include +#include +#include +#include + +#include +#include + +typedef struct jpeg_compress_struct JpgComp; + +#ifndef JpgErr +typedef struct jpeg_error_mgr JpgErr; +#endif + +/* + Image data is an array of unsigned character array of + RGB data. The data is stored in interleaved order. + IE, the first three elements are a byte of Red followed + by a byte of Green and then a byte of Blue for the first + pixel. Data is stored in fortran order (ie. x is fastest + moving dimension). + */ +int WriteJPEGToFileRGB(int nx, /* width of image in pixels */ + int ny, /* height of the image in pixels */ + void *data, /* buffer containing image data */ + int Quality, /* Integer from 0 to 100 */ + FILE* outfile){ /* name of file to store in */ + JpgComp cinfo; + JpgErr jerr; + /* FILE * outfile;*/ + unsigned char *dataRGB = (unsigned char *)data; + JSAMPROW row_pointer=(JSAMPROW)dataRGB; + + memset (&cinfo,0,sizeof(cinfo)); + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + /* Setup JPEG */ + cinfo.image_width = nx ; /* image width and height, in pixels */ + cinfo.image_height = ny; + cinfo.input_components = 3; /* # of color components per pixel=3 RGB */ + cinfo.in_color_space = JCS_RGB; + /* if ((outfile = fopen(FileName, "wb")) == NULL) { + printf("Cannot open file [%s]\n",FileName); + return 0; + } */ + jpeg_stdio_dest(&cinfo, outfile); + jpeg_set_defaults(&cinfo); + jpeg_set_quality (&cinfo,Quality,TRUE); + /* Starting compress */ + jpeg_start_compress(&cinfo, TRUE); + /* Now compress everything one scanline at-a-time */ + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer = (JSAMPROW)(dataRGB+(cinfo.next_scanline*3*nx)); /* in bytes or words? */ + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + /* All done! */ + /* fclose(outfile);*/ + return 1; +} + +/*-------------- + A hack to hijack JPEG's innards to write into a memory buffer +---------------- +/ this defines a new destination manager to store images in memory +/ derived by jdatadst.c */ +typedef struct { + struct jpeg_destination_mgr pub; /* public fields */ + JOCTET *buffer; /* start of buffer */ + int bufsize; /* buffer size */ + int datacount; /* finale data size */ +} memory_destination_mgr; + +typedef memory_destination_mgr *mem_dest_ptr; + +/*---------------------------------------------------------------------------- + / Initialize destination --- called by jpeg_start_compress before any data is actually written. */ + +METHODDEF(void) +init_destination (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = dest->bufsize; + dest->datacount=0; +} + + + +/*---------------------------------------------------------------------------- + / Empty the output buffer --- called whenever buffer fills up. */ +METHODDEF(boolean) +empty_output_buffer (j_compress_ptr cinfo) +{ + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + + dest->pub.next_output_byte = dest->buffer; + dest->pub.free_in_buffer = dest->bufsize; + + return TRUE; +} + + +/*---------------------------------------------------------------------------- + + / Terminate destination --- called by jpeg_finish_compress + / after all data has been written. Usually needs to flush buffer. */ +METHODDEF(void) +term_destination (j_compress_ptr cinfo) +{ + /* expose the finale compressed image size */ + + mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest; + dest->datacount = dest->bufsize - dest->pub.free_in_buffer; + +} + +/*---------------------------------------------------------------------------- +/ Prepare for output to a memory buffer. The caller must have allocate memory +/ to store the compressed image, and supply its size */ +GLOBAL(void) +jpeg_memory_dest (j_compress_ptr cinfo, JOCTET *buffer,int bufsize) +{ + mem_dest_ptr dest; + if (cinfo->dest == NULL) { /* first time for this JPEG object? */ + cinfo->dest = (struct jpeg_destination_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, + sizeof(memory_destination_mgr)); + } + + dest = (mem_dest_ptr) cinfo->dest; + dest->bufsize=bufsize; + dest->buffer=buffer; + dest->pub.init_destination = init_destination; + dest->pub.empty_output_buffer = empty_output_buffer; + dest->pub.term_destination = term_destination; +} + +/******************************************** +Identical in nearly every way to WriteJPEGToFileRGB(), but +it writes into the memory buffer specified. To be safe, its +good to make the memorybuffer the same size as the input image ++ 1024 bytes. It is guaranteed that the image will be less +than this size. In fact, if you use a typical "quality" level +of 75, you can get away with an image which is one quarter that +size. + + ******************************************** */ +int WriteJPEGToMemoryRGB(int nx,int ny, void *data, int Quality, char *memorybuffer,int bufsize){ + JpgComp cinfo; + JpgErr jerr; + FILE * outfile; + unsigned char *dataRGB = (unsigned char *)data; + JSAMPROW row_pointer=(JSAMPROW)dataRGB; + JOCTET *jpgbuff; + mem_dest_ptr dest; + int csize=0; + + /* zero out the compresion info structures and + allocate a new compressor handle */ + memset (&cinfo,0,sizeof(cinfo)); + cinfo.err = jpeg_std_error(&jerr); + jpeg_create_compress(&cinfo); + + /* Setup JPEG datastructures */ + cinfo.image_width = nx ; /* image width and height, in pixels */ + cinfo.image_height = ny; + cinfo.input_components = 3; /* # of color components per pixel=3 RGB */ + cinfo.in_color_space = JCS_RGB; + jpgbuff = (JOCTET*)memorybuffer; + + /* Setup compression and do it */ + jpeg_memory_dest(&cinfo,jpgbuff,bufsize); + jpeg_set_defaults(&cinfo); + jpeg_set_quality (&cinfo,Quality,TRUE); + jpeg_start_compress(&cinfo, TRUE); + /* compress each scanline one-at-a-time */ + while (cinfo.next_scanline < cinfo.image_height) { + row_pointer = (JSAMPROW)(dataRGB+(cinfo.next_scanline*3*nx)); + jpeg_write_scanlines(&cinfo, &row_pointer, 1); + } + jpeg_finish_compress(&cinfo); + /* Now extract the size of the compressed buffer */ + dest=(mem_dest_ptr)cinfo.dest; + csize=dest->datacount; /* the actual compressed datasize */ + /* destroy the compressor handle */ + jpeg_destroy_compress(&cinfo); + return csize; +} + +#define ClampToByte(f) (unsigned char)(f=(f>255)?255:f) +/* Werner's nifty non-linear red-to-blue auto-colormap. + I faked a CCTK_REAL, you can make it the right thing + when integrated with cactus. + + Anyways, the "rdfac" concentrates the colormap when you + use higher values. Typical default value is 32 based + on the current JPEG thorn. + + Next step is to embed some IDL colormaps into the + program. I can do that a bit later. +*/ + +void AutoColorDataSlice(int nx,int ny, /* size of the image x & y */ + CCTK_REAL *datain, /* 2D slice of data input */ + unsigned char *dataout, /* RGB image data output */ + CCTK_REAL min,CCTK_REAL max, /* range of the entire 3D dataset + This could be ranged based + on the values of the slice, + but then that would be a + bit untrustworthy. Its + best to pass in the + range for the entire + dataset or a pre-defined + fixed range. It does + handle clamping of the + range. */ + CCTK_REAL bias, + int rdfac){ + /* Bias allows you to move the spectrum from the Red to the + Blue. A value of 0.5 is the median. So 0.4 biases towards + the Red and 0.6 would bias a little towards the blue. + The range for this parameter would be -1.0 to +1.0. */ + /* CCTK_REAL bias=0.4;*/ + int i,last; + CCTK_REAL F=(CCTK_REAL)rdfac; /* cast to CCTK_REAL... don't know how the original worked at all without a cast */ + for(i=0,last=nx*ny;i0){ + f*=F; + /* Color components biased towards blue */ + dataout[0]=ClampToByte(f); + f*=F; + dataout[1]=ClampToByte(f); + f*=F; + dataout[2]=ClampToByte(f); + } + else { /* f<0 */ + f=-f; + f*=F; + /* reverse color components to bias towards red */ + dataout[2]=ClampToByte(f); + f*=F; + dataout[1]=ClampToByte(f); + f*=F; + dataout[0]=ClampToByte(f); + } + } +} + +#ifdef 0 +int main(int argc,char *argv[]){ + /* OK, lets create a bogus image */ + int nx=512,ny=512; + unsigned char *datargb=(unsigned char *)malloc(3*nx*ny); + CCTK_REAL *data= (CCTK_REAL*)malloc(nx*ny*sizeof(CCTK_REAL)); + int i,j,idx=0; + CCTK_REAL radius=((CCTK_REAL)(nx/4)); + CCTK_REAL min=(CCTK_REAL)(nx*ny),max=-1.0; + int bufsize = nx*ny*3+1024; + char *memorybuffer=(char *)malloc(bufsize); /* safe size for membuf */ + int compressed_size=0; + FILE *outfile; + /* compute a circle by the most inefficient means possible */ + for(j=0,idx=0;jmax) max=val; + if(val +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "IOJpeg.h" + + + +/* function prototypes */ +int IOJpeg_TimeFor2D (cGH *GH, int index); +int IOJpeg_Output2DVarAs (cGH *GH, const char *var, const char *alias); +static void CheckSteerableParameters (IOJpegGH *myGH); + + +int IOJpeg_Output2DGH (cGH *GH) +{ + DECLARE_CCTK_PARAMETERS + int i; + IOJpegGH *myGH; + const char *name; + char *fullname; + int ierr=0; + + /* Get the GH extension for IOJpeg */ + myGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + CheckSteerableParameters (myGH); + + if (myGH->out2D_every <= 0) + return (0); + + /* Loop over all variables */ + for (i = 0; i < CCTK_NumVars (); i++) + { + + if (IOJpeg_TimeFor2D (GH, i)) + { + + name = CCTK_VarName (i); + fullname = CCTK_FullName (i); + + if (!CCTK_Equals(verbose,"no")) + CCTK_VInfo (CCTK_THORNSTRING, "IOJpeg_Output2DGH: fullname / name = " + "%s / %s", fullname, name); + + ierr=IOJpeg_Output2DVarAs (GH, fullname, name); + + free (fullname); + + /* Register variable as having 2D output this iteration */ + myGH->out2D_last [i] = GH->cctk_iteration; + } + } + if (!CCTK_Equals(verbose,"no")) + CCTK_INFO("IOJpeg_Output2DGH Done"); + + return (ierr); +} + + +int IOJpeg_Output2DVarAs (cGH *GH, const char *fullname, const char *alias) +{ + DECLARE_CCTK_PARAMETERS + int index,ierr=0; + + index = CCTK_VarIndex (fullname); + + /* first, check if variable has storage assigned */ + if (! CCTK_QueryGroupStorageI (GH, CCTK_GroupIndexFromVarI (index))) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOJpeg 2D output for '%s' (no storage)", fullname); + return(-1); + } + + if (!CCTK_Equals(verbose,"no")) + CCTK_VInfo (CCTK_THORNSTRING, "IOJpeg_Output2DVarAs: fullname, alias, " + "index = (%s, %s, %d)", fullname, alias, index); + + /* Do the 2D output */ + ierr=IOJpeg_Write2D (GH, index, alias); + + return (ierr); +} + +int IOJpeg_TimeFor2D (cGH *GH, int index) +{ + IOJpegGH *myGH; + + + /* Get the GH extension for IOJpeg */ + myGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + CheckSteerableParameters (myGH); + + /* Check if any output was requested */ + if(myGH->out2D_every <= 0) + return (0); + + /* Check this variable should be output */ + if (! (myGH->do_out2D [index] && GH->cctk_iteration % myGH->out2D_every == 0)) + return (0); + + + /* Check variable not already output this iteration */ + if (myGH->out2D_last [index] == GH->cctk_iteration) + { + CCTK_WARN (2, "Already done 2D output in IOJpeg"); + return (0); + } + + return (1); +} + +int IOJpeg_TriggerOutput2D (cGH *GH, int index) +{ + DECLARE_CCTK_PARAMETERS + IOJpegGH *myGH; + const char *varname; + int ierr=0; + + varname = CCTK_VarName (index); + + myGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + if (!CCTK_Equals(verbose,"no")) + CCTK_VInfo (CCTK_THORNSTRING, "IOJpeg_TriggerOutput2D: varname, index = " + "(%s, %d)", varname, index); + + /* Do the 2D output */ + ierr=IOJpeg_Write2D (GH, index, varname); + + /* Register variable as having 2D output this iteration */ + myGH->out2D_last [index] = GH->cctk_iteration; + + return (ierr); +} + + +/**************************** local functions ******************************/ +static void CheckSteerableParameters (IOJpegGH *myGH) +{ + DECLARE_CCTK_PARAMETERS + int out2D_vars_current_nset; + static int out2D_vars_lastset = 0; + + + /* How often to output */ + myGH->out2D_every = out_every > 0 ? out_every : -1; + if (out2D_every > 0) + myGH->out2D_every = out2D_every; + + /* re-parse the 'out2D_vars' parameter if it was changed */ + out2D_vars_current_nset = CCTK_ParameterQueryTimesSet ("out2D_vars", + CCTK_THORNSTRING); + if (out2D_vars_current_nset != out2D_vars_lastset) + { + IOUtil_ParseVarsForOutput (out2D_vars, myGH->do_out2D); + + /* Save the last setting of 'out2D_vars' parameter */ + out2D_vars_lastset = out2D_vars_current_nset; + } +} diff --git a/src/ParseGeometry.c b/src/ParseGeometry.c new file mode 100644 index 0000000..b060708 --- /dev/null +++ b/src/ParseGeometry.c @@ -0,0 +1,142 @@ +#include +#include +#include + +#include "cctk.h" +#include "cctk_Arguments.h" +#include "cctk_Parameters.h" + +#include "util_String.h" +#include "IOJpeg.h" +#include "CactusBase/IOASCII/src/ioASCIIGH.h" + +void IOJpeg_DefaultGeo(cGH *GH, int sdim, IOJpegGeo_t *geo) { + DECLARE_CCTK_PARAMETERS + + asciiioGH *asGH; + int idim,ti; + const char *tmp_origin, *tmp_downs, *tmp_length; + const char *token; + + asGH = (asciiioGH *) GH->extensions + [CCTK_GHExtensionHandle ("IOASCII")]; + + geo->vdim = -1; + geo->sdim = -1; + + for (idim=0;idimdirection[idim] = idim; + geo->slab_start[idim]= 0; + geo->length[idim] =-1; + geo->actlen[idim] =-1; + geo->downs[idim] = 1; + } + + /* FIXME: we use spxyz, which is hardcoded to 3D */ + for (idim=0;idim<3;idim++) + geo->slab_start[idim]=asGH->spxyz[2][(idim+1)%3][idim]; + + /* Parse the parameter of the requested dimension */ + switch (sdim) { + case 2: + tmp_origin = origin2D; + tmp_downs = downsampling2D; + tmp_length = length2D; + break; + default: + tmp_origin = origin2D; + tmp_downs = downsampling2D; + tmp_length = length2D; + break; + } + + /* Origin, set from parameter only if parameter value .ne. -1 */ + idim=0; + while((token = Util_StrSep(&tmp_origin,","))) { + ti=atoi(token); + if (ti>-1) geo->slab_start[idim++] = ti; + } + ti = atoi(tmp_origin); + if (ti>-1) geo->slab_start[idim] = ti; + + /* Downsample */ + idim=0; + while((token = Util_StrSep(&tmp_downs,","))) { + geo->downs[idim++]=atoi(token); + } + geo->downs[idim] = atoi(tmp_downs); + + /* Length */ + idim=0; + while((token = Util_StrSep(&tmp_length,","))) { + geo->length[idim++]=atoi(token); + } + geo->length[idim] = atoi(tmp_length); +} + + +int IOJpeg_NumDirection(int sdim, int vdim) +{ + int numdir=-1; + if (vdim==3) { + switch (sdim) { + case 1: return(3); + case 2: return(3); + case 3: return(1); + } + } else if (vdim==2) { + switch (sdim) { + case 1: return(2); + case 2: return(1); + } + } + else if (vdim==1) { + switch (sdim) { + case 1: return(1); + } + } + else printf("Bad dimension: %d \n",vdim); + return(numdir); +} + +int IOJpeg_SetDirection(int vdim, int sdim, int ci, int *direction) +{ + int retval=0; + + if (sdim>vdim) { + printf("SetDirection: slabdim gt vdim"); + return(-1); + } + + if (vdim==3) { + if (sdim==2) { + switch (ci) { + case 0: direction[0]=0; direction[1]=1; break; + case 1: direction[0]=0; direction[1]=2; break; + case 2: direction[0]=1; direction[1]=2; break; + } + } + else if (sdim==1) { + switch (ci) { + case 0: direction[0]=0; break; + case 1: direction[0]=1; break; + case 2: direction[0]=2; break; + } + } + } + else if (vdim==2) { + if (sdim==2) { + direction[0]=0; direction[1]=1; + } else if (sdim==1) { + switch (ci) { + case 0: direction[0]=0; break; + case 1: direction[0]=1; break; + } + } + } else retval = -1; + return(retval); +} + + + + diff --git a/src/Startup.c b/src/Startup.c new file mode 100644 index 0000000..323ffd0 --- /dev/null +++ b/src/Startup.c @@ -0,0 +1,47 @@ +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioGH.h" + +int IOJpeg_Output2DGH(cGH *GH); +int IOJpeg_TriggerOutput2D(cGH *GH, int); +int IOJpeg_TimeFor2D(cGH *GH, int); +int IOJpeg_Output2DVarAs(cGH *GH, const char *var, const char *alias); + +void *IOJpeg_SetupGH (tFleshConfig *config, int convergence_level, cGH *GH); +int IOJpeg_InitGH (cGH *GH); + +void IOJpeg_Startup (void) +{ + DECLARE_CCTK_PARAMETERS + int IO_GHExtension; + int IOMethod; + + + if (CCTK_GHExtensionHandle ("IO") < 0) + { + CCTK_WARN (1, "Thorn IOUtil was not activated. " + "No IOJpeg IO methods will be enabled."); + return; + } + if (CCTK_GHExtensionHandle ("PUGH") < 0) + { + CCTK_WARN (1, "Thorn PUGH was not activated. " + "No IOJpeg IO methods will be enabled."); + return; + } + + IO_GHExtension = CCTK_RegisterGHExtension ("IOJpeg"); + CCTK_RegisterGHExtensionSetupGH (IO_GHExtension, IOJpeg_SetupGH); + CCTK_RegisterGHExtensionInitGH (IO_GHExtension, IOJpeg_InitGH); + + /* Register the 2D IOJpeg routines as output methods */ + + IOMethod = CCTK_RegisterIOMethod ("IOJpeg_2D"); + CCTK_RegisterIOMethodOutputGH (IOMethod, IOJpeg_Output2DGH); + CCTK_RegisterIOMethodOutputVarAs (IOMethod, IOJpeg_Output2DVarAs); + CCTK_RegisterIOMethodTimeToOutput (IOMethod, IOJpeg_TimeFor2D); + CCTK_RegisterIOMethodTriggerOutput (IOMethod, IOJpeg_TriggerOutput2D); + +} diff --git a/src/Write2D.c b/src/Write2D.c new file mode 100644 index 0000000..874ec76 --- /dev/null +++ b/src/Write2D.c @@ -0,0 +1,168 @@ + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "IOJpeg.h" + +#include +#include +#include + +/* local function prototypes */ +int IOJpeg_NumDirection(int sdim, int vdim); +int IOJpeg_SetDirection(int vdim, int sdim, int ci, int *direction); + +static int *advertised; + +int IOJpeg_Write2D (cGH *GH, int index, const char *alias) +{ + DECLARE_CCTK_PARAMETERS + int timelevel; + ioGH *ioUtilGH; + IOJpegGH *ssGH; + IOJpegGeo_t geo; + FILE **fdset_2D; /* array of output file pointers */ + int SDIM; + int si,max_slabs; + int ierr=0; + + /* Get the handle for IO extensions */ + ioUtilGH = (ioGH *) GH->extensions [CCTK_GHExtensionHandle ("IO")]; + ssGH = (IOJpegGH *) GH->extensions [CCTK_GHExtensionHandle ("IOJpeg")]; + + /* The dimension of the slab - HARDCODED */ + SDIM = 2; + + /* Get the slab geometry for 2D slabs */ + geo = ssGH->out_geo[index][SDIM]; + /* Set geo.sdim to announce 2D output */ + geo.sdim = SDIM; + /* get the dimension of the variable */ + geo.vdim = CCTK_GroupDimFromVarI(index); + + if (!CCTK_Equals(verbose,"no")) + CCTK_VInfo (CCTK_THORNSTRING, "IOJpeg %dD-output of variable '%s', " + "downsampling parameters (%d, %d, %d)", SDIM, alias, + geo.downs[0], geo.downs [1], geo.downs [2]); + + /* get the current timelevel */ + timelevel = CCTK_NumTimeLevelsFromVarI (index) - 1; + if (timelevel > 0) + timelevel--; + + /* Maximal number of slabs (dimension sdim) in + given volume (dimension vdim) */ + if ((max_slabs=IOJpeg_NumDirection(SDIM, geo.vdim))<0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Cannot get valid number of slabs (%d) for given volume (%d).\n", + SDIM, geo.vdim); + return(-1); + } + + /* see if output file for this alias name was already created */ + fdset_2D = (FILE **) GetNamedData (ssGH->fileList_2D, alias); + /* if (fdset_2D == NULL) */ + { + char *fname; + + fdset_2D = (FILE **) malloc (max_slabs * sizeof (FILE *)); + fname = (char *) malloc ((strlen (ssGH->outdir2D) + strlen (alias) + 20)*sizeof(char)); + + /* Set flags for remembering if files have been advertised */ + if (!advertised) + { + advertised = (int *)malloc(max_slabs*sizeof(int)); + for (si=0;sioutdir2D,alias, + extensions [si]); + } + else + { + sprintf (fname, "%s/%s_2d_%s.%d.jpeg", ssGH->outdir2D,alias, + extensions [si],GH->cctk_iteration); + } + + fdset_2D [si] = fopen (fname, "w"); + if (! fdset_2D [si]) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Cannot open 2D output file '%s'", fname); + return; + } + + /* advertise the file for downloading */ + if (CCTK_Equals(mode,"remove") && advertised[si] == 0) + { + advertised_file.slice = (char *) extensions [si]; + advertised_file.thorn = CCTK_THORNSTRING; + advertised_file.varname = CCTK_FullName (index); + advertised_file.description = "Jpegs of slices"; + advertised_file.mimetype = "image/jpeg"; + + IOUtil_AdvertiseFile (GH, fname, &advertised_file); + advertised[si] = 1; + free (advertised_file.varname); + } + } + + /* store file desriptors in database */ + StoreNamedData (&ssGH->fileList_2D, alias, fdset_2D); + + /* ********************************************** + The call to the actual data collection and + lowlevel output routine. + ********************************************** */ + + ierr = IOJpeg_DumpVar(GH, index, timelevel, &geo, fdset_2D[si]); + if (ierr<0) CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOJpeg_DumpVar failed for GF index: %d\n", + index); + + /* ********************************************** + File close procedures which are more complex, + like for HDF5 can go here. + ********************************************** */ + + /* Close the file */ + close (fdset_2D [si]); + + } + + free(fname); + + } + + return(ierr); +} diff --git a/src/make.code.defn b/src/make.code.defn new file mode 100644 index 0000000..096edce --- /dev/null +++ b/src/make.code.defn @@ -0,0 +1,9 @@ +# Main make.code.defn file for thorn IOSkeleton +# $Header$ + +# Source files in this directory +SRCS = DumpVar.c Output2D.c Write2D.c Startup.c ParseGeometry.c GHExtension.c JPEG.c + +# Subdirectories containing source files +SUBDIRS = + -- cgit v1.2.3