diff options
Diffstat (limited to 'src/Write3D.c')
-rw-r--r-- | src/Write3D.c | 292 |
1 files changed, 292 insertions, 0 deletions
diff --git a/src/Write3D.c b/src/Write3D.c new file mode 100644 index 0000000..f07ef55 --- /dev/null +++ b/src/Write3D.c @@ -0,0 +1,292 @@ +/*@@ + @file Write3D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Three-dimensional output of variables in SDF file format. + @enddesc + @version $Id$ + @@*/ + + +#include <stdlib.h> +#include <string.h> + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "util_Table.h" +#include "CactusBase/IOUtil/src/ioGH.h" +#include "CactusBase/IOUtil/src/ioutil_AdvertisedFiles.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Header$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Write3D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static char *OpenFile (const cGH *GH, const char *fullname, const char *alias); + +/*@@ + @routine IOSDF_Write3D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Writes the 3D volume of a variable into a gnuplot SDF file. + @enddesc + @calls Hyperslab_GlobalMappingByIndex + Hyperslab_FreeMapping + Hyperslab_GetList + OpenFile + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable to output + @vtype int + @vio in + @endvar + @var alias + @vdesc alias name of variable to output + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + 0 for success, or<BR> + -1 if variable has no storage assigned<BR> + -2 if output file couldn't be opened<BR> + -3 if hyperslab for coordinates and/or variable couldn't be + extracted + @endreturndesc +@@*/ +int IOSDF_Write3D (const cGH *GH, int vindex, const char *alias) +{ + int i, total_hsize; + int myproc, gindex, have_coords; + int num_requested_hslabs, num_returned_hslabs; + cGroup gdata; + CCTK_INT coord_system_handle, coord_handles[3]; + char *fullname, *groupname, *filename; + double *hdata[4]; + int extent_int[3]; + double offset[3]; + int mapping; + CCTK_INT vindices[4], extent[3], downsample[3], hsize[3]; + const double dtime = GH->cctk_time; + const CCTK_INT origin[] = {0, 0, 0}, + direction[] = {1, 0, 0, 0, 1, 0, 0, 0, 1}; + DECLARE_CCTK_PARAMETERS + + + /* get the variable group information */ + fullname = CCTK_FullName (vindex); + gindex = CCTK_GroupIndexFromVarI (vindex); + CCTK_GroupData (gindex, &gdata); + + /* check if variable has storage assigned */ + if (! CCTK_QueryGroupStorageI (GH, gindex)) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOSDF 3D output for '%s' (no storage)", fullname); + free (fullname); + return (-1); + } + + /* get the coordinate system associated with this grid variable */ + vindices[0] = vindex; + groupname = CCTK_GroupName (gindex); + coord_system_handle = Coord_GroupSystem (GH, groupname); + free (groupname); + + have_coords = coord_system_handle >= 0 && + Util_TableGetIntArray (coord_system_handle, 3, + coord_handles, "COORDINATES") >= 0; + if (have_coords) + { + /* get the coordinate functions and coordinate physical minimum */ + for (i = 1; i <= 3; i++) + { + vindices[i] = -1; + Util_TableGetInt (coord_handles[i-1], &vindices[i], "GAINDEX"); + have_coords &= vindices[i] >= 0; + } + } + num_requested_hslabs = have_coords ? 4 : 1; + + /* What processor are we on? */ + myproc = CCTK_MyProc (GH); + + /* Open the file on processor 0 */ + filename = myproc == 0 ? OpenFile (GH, fullname, alias) : NULL; + + /* get the total number of grid points to check for zero-sized variables */ + /* set the extent vector (copy from 'int' to 'CCTK_INT') */ + CCTK_GroupgshVI (GH, 3, extent_int, vindex); + for (i = 0, total_hsize = 1; i < 3; i++) + { + total_hsize *= extent_int[i]; + extent[i] = extent_int[i]; + } + if (total_hsize <= 0) + { + free (fullname); + return (0); + } + + downsample[0] = out_downsample_x; + downsample[1] = out_downsample_y; + downsample[2] = out_downsample_z; + + /* get the hyperslab mapping */ + mapping = Hyperslab_GlobalMappingByIndex (GH, vindex, 3, + direction, origin, extent, + downsample, + -1, /* table handle */ + NULL /* conversion fn */, + hsize); + if (mapping < 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write3D: Failed to define hyperslab mapping for " + "variable '%s'", fullname); + free (fullname); + return (-1); + } + for (i = 0, total_hsize = 1; i < 3; i++) + { + extent_int[i] = hsize[i]; + total_hsize *= hsize[i]; + } + if (total_hsize <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write3D: selected hyperslab has zero size for " + "variable '%s'", fullname); + Hyperslab_FreeMapping (mapping); + free (fullname); + return (-1); + } + + hdata[0] = hdata[1] = hdata[2] = hdata[3]; + if (myproc == 0) + { + /* allocate hyperslab buffers */ + hdata[0] = malloc (total_hsize * sizeof (double)); + hdata[1] = have_coords ? malloc (3 * total_hsize * sizeof (double)) : NULL; + hdata[2] = hdata[1] + 1*total_hsize; + hdata[3] = hdata[1] + 2*total_hsize; + } + + /* get the hyperslabs */ + num_returned_hslabs = Hyperslab_GetList (GH, mapping, num_requested_hslabs, + NULL, vindices, NULL, NULL, + (void **) hdata, NULL); + + /* And dump the data to file */ + if (myproc == 0) + { + if (num_returned_hslabs == num_requested_hslabs) + { + if (have_coords) + { + /* get the staggering offset for the coordinates */ + for (i = 0; i < 3; i++) + { + offset[i] = 0.5 * GH->cctk_delta_space[i] * + CCTK_StaggerDirIndex (i, gdata.stagtype); + } + for (i = 0; i < total_hsize; i++) + { + hdata[1][i] += offset[0]; + hdata[2][i] += offset[1]; + hdata[3][i] += offset[2]; + } + } + + i = have_coords ? gft_out_full (filename, dtime, extent_int, "x|y|z", 3, + hdata[1], hdata[0]) : + gft_out_brief (filename, dtime, extent_int, 3,hdata[0]); + if (i <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Error writing to 3D IOSDF output file '%s'", filename); + } + } + else + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write3D: Failed to extract hyperslab for " + "variable '%s'", fullname); + } + + /* clean up */ + free (hdata[0]); + free (hdata[1]); + } /* end of outputting the data by processor 0 */ + + free (fullname); + + return (0); +} + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +/*@@ + @routine OpenFile + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Opens an SDF file for a given alias name. + If this is the first time through, it will advertise it + to IOUtil. + @enddesc + + @returntype char * + @returndesc + the full filename of the SDF output file + @endreturndesc + @@*/ +static char *OpenFile (const cGH *GH, const char *fullname, const char *alias) +{ + char *filename; + ioSDFGH *myGH; + ioAdvertisedFileDesc advertised_file; + DECLARE_CCTK_PARAMETERS + + + /* get handle for IOSDF GH extensions */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* see if we are the first time through */ + filename = GetNamedData (myGH->fileList_3D, alias); + if (! filename) + { + filename = malloc (strlen (myGH->out3D_dir) + strlen (alias) + 9); + + /* open/create the file */ + sprintf (filename, "%s%s_3D.sdf", myGH->out3D_dir, alias); + + /* advertise the file for downloading and write file info */ + advertised_file.slice = ""; + advertised_file.thorn = CCTK_THORNSTRING; + advertised_file.varname = fullname; + advertised_file.description = "Full-dimensional variable contents"; + advertised_file.mimetype = "application/sdf"; + + IOUtil_AdvertiseFile (GH, filename, &advertised_file); + + /* store filename in database */ + StoreNamedData (&myGH->fileList_3D, alias, filename); + } + + return (filename); +} |