aboutsummaryrefslogtreecommitdiff
path: root/src/Write3D.c
diff options
context:
space:
mode:
authortradke <tradke@ebee0441-1374-4afa-a3b5-247f3ba15b9a>1999-06-25 11:40:06 +0000
committertradke <tradke@ebee0441-1374-4afa-a3b5-247f3ba15b9a>1999-06-25 11:40:06 +0000
commitde89a5c6b08b5ad9eb7044dc8b2c04a965b19982 (patch)
tree339e8646892a1638fc0d9b81c38cfed38acb238c /src/Write3D.c
parentf9c5c1bc939250652e057dcd06f5ce9701b8a0bb (diff)
The hopefully final renaming of the FlexIO thorn.
git-svn-id: http://svn.cactuscode.org/arrangements/CactusPUGHIO/IOFlexIO/trunk@2 ebee0441-1374-4afa-a3b5-247f3ba15b9a
Diffstat (limited to 'src/Write3D.c')
-rw-r--r--src/Write3D.c462
1 files changed, 462 insertions, 0 deletions
diff --git a/src/Write3D.c b/src/Write3D.c
new file mode 100644
index 0000000..6d72a93
--- /dev/null
+++ b/src/Write3D.c
@@ -0,0 +1,462 @@
+/*@@
+ @file Write3D.c
+ @date Fri Feb 21 15:27:03 1997
+ @author
+ @desc
+ A horrible blocking write and not-quite-so-horrible
+ slicer for xgraph output. Basically MPI based IO
+ bites the big one, and this is MPI based IO written
+ quickly and in the obvious inefficient fashion.
+ <p>
+ Oh, not it also contains zero-d I/O and a closer also.
+ <p>
+ This routine can write DFSD style HDF (not the default)
+ or Johns IEEEIO 3D files (the default). For 0 and 1D
+ I/O it writes xgraph files.
+ @enddesc
+ @history
+ @hauthor Gabrielle Allen @hdate 26 Sep 1998
+ @hdesc Changed routine name (WriteGF->Write3D), Lots of tidying up and
+ renaming of parameters
+ @hauthor Gabrielle Allen @hdate 17 Oct 1998
+ @hdesc Implemented new parameters IO_verbose,IO_parameter,IO_structures,IO_scalars
+ @hauthor Gabrielle Allen @hdate 19 Oct 1998
+ @hdesc Changed names ready for thorn_IO
+ @hauthor Thomas Radke @hdate 16 Mar 1999
+ @hdesc Converted to Cactus 4.0
+ @hauthor Thomas Radke @hdate 17 Mar 1999
+ @hdesc Changed naming: IEEEIO -> IOFlexIO
+ @hendhistory
+ @version $Id$
+ @@*/
+
+static char *rcsid = "$Id$";
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "cctk.h"
+#include "flesh.h"
+#include "Comm.h"
+#include "Groups.h"
+#include "GHExtensions.h"
+#include "WarnLevel.h"
+#include "declare_parameters.h"
+#ifdef CACTUSBASE_PUGH
+#include "CactusBase/pugh/src/include/pugh.h"
+#endif
+#include "CactusBase/IOUtil/src/ioGH.h"
+#include "ioFlexGH.h"
+
+
+/* local function prototypes */
+void IOFlexIO_Write3D_filename (cGH *GH, char *filename, const char *name);
+void IOFlexIO_Write3D_openFile (cGH *GH, const char *filename, IOFile *iofile, int first);
+void IOFlexIO_Write3D_closeFile (cGH *GH, const char *filename, IOFile *iofile);
+/* external function prototypes */
+void IOFlexIO_DumpVar (cGH *GH, int index, int timelevel, IOFile iof);
+
+
+/*@@
+ @routine IOFlexIO_Write3D
+ @author Paul Walker
+ @date Feb 1997
+ @desc
+ This routine does 3D IO for a grid function which has been
+ distributed with MPI.
+ <p>
+ 3D MPI IO! Wow, you may say, that sounds pretty clever. Well it isn't
+ because <b><i>The method I use sucks rocks</i></b>. That is.
+ I spam the data from all processors onto processor 0. Luckily
+ it doesn't just put it all in one memory chunk, but recieves it
+ bit by bit and writes it out chunkwise, using IEEEIO. Alas,
+ while this happens the other processors <i>sit in a barrier
+ with their metaphoric thumbs up their asses</i>.
+ <p>
+ <b>Even Worse</b> it is a blocking send which must come in order
+ from the other processors.
+ <p>
+ This is inefficient to say the least. I/O costs can go up to 70-80%
+ using this technique on the T3E. So there are also a couple of ways to
+ get around it.
+ <p>
+ The easiest option is one-file-per-processor which is
+ good on some machines, (eg T3E) and bad on others (eg O2K, I think).
+ So you can activate this mode (or de-activate it on the T3E)
+ by setting the parameter onefileperproc to "yes" or "no".
+ This will create a bunch of files in their own subdirectory,
+ and they can be smooshed together using cactus/lib/etc/Recombiner.C
+ <p>
+ Also, you can downsample output. You can also output one file per
+ slice. Various combinations of these work or don't, depending.
+ <p>
+ Finally notice that @seeroutine main guarantees that this is never
+ called on a 1- or 2-D grid.
+ @enddesc
+ @calls CCTK_GetGHExtensionHandle
+ CCTK_GetMyProc
+ CCTK_GetnProcs
+ CCTK_WARN
+ @calledby IOFlexIO_Output3DVarAs
+ IOFlexIO_TriggerOutput3D
+ @history
+ @hdate Wed Sep 2 10:11:41 1998 @hauthor Tom Goodale
+ @hdesc Merged in Szu-Wen's Panda calls.
+ @hdate Sep 25 1998 1998 @hauthor Gabrielle Allen
+ @hdesc Split into subroutines
+ @endhistory
+ @var GH
+ @vdesc Pointer to CCTK GH
+ @vtype cGH
+ @vio in
+ @vcomment
+ @endvar
+ @var index
+ @vdesc index of variable to output
+ @vtype int
+ @vio in
+ @vcomment
+ @endvar
+ @var alias
+ @vdesc alias name of variable to output
+ @vtype const char *
+ @vio in
+ @vcomment
+ @endvar
+ @var first
+ @vdesc flag to indicate whether file should be opened in "w" or "a" mode
+ @vtype int (boolean)
+ @vio in
+ @vcomment
+ @endvar
+ @@*/
+
+
+void IOFlexIO_Write3D (cGH *GH, int index, const char *alias, int first)
+{
+ DECLARE_PARAMETERS
+ int myproc, nprocs;
+ int timelevel;
+ ioGH *ioUtilGH;
+ flexioGH *myGH;
+ IOFile *iofile;
+ char *filename;
+
+
+ /* Get the handle for IOUtil and IOFlexIO extensions */
+ ioUtilGH = (ioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IO")];
+ myGH = (flexioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IOFlexIO")];
+
+ /* Get filename and reference to file handle */
+ filename = myGH->IEEEfname_3D [index];
+ iofile = &myGH->IEEEfile_3D [index];
+
+ if (IO_verbose) {
+ printf ("-------------------------------------------------------\n");
+ printf ("3D I/O on Grid Function %s\n", alias);
+ printf (" downsample (x,y,z): (%d,%d,%d) ioproc : %d\n",
+ ioUtilGH->downsample_x, ioUtilGH->downsample_y,
+ ioUtilGH->downsample_z, ioUtilGH->ioproc);
+ fflush (stdout);
+ }
+
+ /* What processor are we on? */
+ myproc = CCTK_GetMyProc (GH);
+ nprocs = CCTK_GetnProcs (GH);
+
+
+ /* build the filename for output */
+ /* This code is semi-repeated in DumpGH.c */
+ /* The output directory is also created. */
+ if (first || onefileperslice)
+ IOFlexIO_Write3D_filename (GH, filename, alias);
+
+ /* Close the file if it is already open (if IEEEfile_3D is set).
+ * This shouldn't be needed, since we do it below,
+ * but better safe than sorry.
+ * Also I have some vague recollection of needing it in some
+ * very strange case ... So leave it here for now (PW 11.5.98)
+ */
+ if (*iofile && onefileperslice) {
+ if (IO_verbose)
+ printf ("Closing IEEEfile from previous iteration.\n");
+ CACTUS_IEEEIO_ERROR (IOclose (*iofile));
+ *iofile = NULL; /* prevent attempts to close it twice! */
+ }
+
+
+ /* open the output file (only if we are an output processor) */
+ if (myproc == ioUtilGH->ioproc)
+ IOFlexIO_Write3D_openFile (GH, filename, iofile, first);
+
+ /* get the current timelevel */
+ timelevel = CCTK_GetNumTimeLevels (index) - 1;
+ if (timelevel > 0)
+ timelevel--;
+
+ /* output the data */
+ IOFlexIO_DumpVar (GH, index, timelevel, *iofile);
+
+ /* output the scalars and parameters */
+ /* Don't do this if the output is being byte compared, as the
+ * thorn lists might be different.
+ */
+ if (myproc == ioUtilGH->ioproc) {
+ /* output parameters necessary for filereader datafiles */
+ if (first)
+ IOFlexIO_IEEEIOStructDump (GH, *iofile);
+#if 0
+ if (ioUtilGH->parameters)
+ IOFlexIO_IEEEIOparamDump (*iofile);
+#endif
+ /* close the file */
+ IOFlexIO_Write3D_closeFile (GH, filename, iofile);
+ }
+
+ if (IO_verbose)
+ printf ("-------------------\n");
+}
+
+
+/*@@
+ @routine IOFlexIO_Write3D_closeFile
+ @author Paul Walker
+ @date Feb 1997
+ @desc
+ Closes or pauses the IEEEIO output file.
+ @enddesc
+ @history
+ @hauthor Gabrielle Allen
+ @hdate Sep 1998
+ @hdesc Split into subroutine
+ @endhistory
+ @@*/
+
+
+void IOFlexIO_Write3D_closeFile (cGH *GH, const char *filename, IOFile *iofile)
+{
+ DECLARE_PARAMETERS
+ ioGH *ioUtilGH;
+ flexioGH *myGH;
+
+ ioUtilGH = (ioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IO")];
+ myGH = (flexioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IOFlexIO")];
+
+ if (*iofile == NULL)
+ return;
+
+ if (onefileperslice) {
+ if (IO_verbose)
+ printf ("Closing IEEEfile from this iteration\n");
+ CACTUS_IEEEIO_ERROR (IOclose (*iofile));
+ *iofile = NULL;
+ return;
+ }
+
+ if (myGH->reuse_fh) {
+ if (IO_verbose)
+ printf ("Pausing file %s\n", filename);
+ IEEEbufferOff (*iofile);
+ CACTUS_IEEEIO_ERROR (IOpause (*iofile));
+ } else {
+ if (IO_verbose)
+ printf ("Closing file %s\n", filename);
+ CACTUS_IEEEIO_ERROR (IOclose (*iofile));
+ *iofile = NULL;
+ }
+}
+
+
+/*@@
+ @routine IOFlexIO_Write3D_openFile
+ @author Paul Walker
+ @date Feb 1997
+ @desc
+ Opens or resumes the IEEEIO output file
+ @enddesc
+ @history
+ @hauthor Gabrielle Allen
+ @hdate Sep 1998
+ @hdesc Split into subroutine
+ @endhistory
+ @@*/
+
+void IOFlexIO_Write3D_openFile (cGH *GH, const char *filename, IOFile *iofile, int first)
+{
+ DECLARE_PARAMETERS
+ ioGH *ioUtilGH;
+ flexioGH *myGH;
+
+ ioUtilGH = (ioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IO")];
+ myGH = (flexioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IOFlexIO")];
+
+ /* If we are the first time through, or writing one file per slice, we need
+ to open a file in write mode. Or, if we are reusing file handles we will
+ need to resume the file */
+
+ if (first || onefileperslice) {
+
+ /* First time through or one file per slice; open anew */
+ if (IO_verbose)
+ printf ("Opening file %s\n", filename);
+
+ *iofile = IEEEopen (filename, "w");
+ if (! IOisValid (*iofile)) {
+ char *msg = (char *) malloc (strlen (filename) + 80);
+
+ sprintf (msg, "The file %s could not be opened for writing.", filename);
+ CCTK_WARN (1, msg);
+ free (msg);
+ }
+ }
+
+ else if (myGH->reuse_fh) {
+
+ /* resume the file (reopen descriptor)
+ This allows descriptor reuse without requiring expensive destruction
+ and reallocation of the associated datastructures */
+
+ if (*iofile) {
+
+ if (IO_verbose)
+ printf ("Resuming file %s\n", filename);
+
+ CACTUS_IEEEIO_ERROR (IOresume (*iofile));
+ }
+ } else {
+ /* File is closed, not onefileperslice and not first time.
+ Therefore we must be conserving file handles and failed
+ to use the pause()/resume methods(), So append.
+ */
+ if (IO_verbose)
+ printf ("Re-opening file %s in append mode\n", filename);
+
+ *iofile = IEEEopen (filename, "a");
+ if (! IOisValid (*iofile)) {
+ char *msg = (char *) malloc (strlen (filename) + 80);
+
+ sprintf (msg, "The file %s could not be opened for appending.\n",
+ filename);
+ CCTK_WARN (1, msg);
+ free (msg);
+ }
+ }
+
+ /* Turn on buffer cache (with default size chosen by IEEEIO lib) */
+ IEEEbufferOn (*iofile, 0);
+}
+
+
+/*@@
+ @routine IOFlexIO_Write3D_filename
+ @author Paul Walker
+ @date Feb 1997
+ @desc
+ Generates the filename for output
+ @enddesc
+ @history
+ @hauthor Gabrielle Allen
+ @hdate Sep 1998
+ @hdesc Split into subroutine
+ @endhistory
+ @@*/
+
+void IOFlexIO_Write3D_filename (cGH *GH, char *filename, const char *name)
+{
+ DECLARE_PARAMETERS
+ ioGH *ioUtilGH; /* handle for IOUtil extensions */
+ pGH *pughGH; /* handle for PUGH extensions */
+ int nprocs;
+ int myproc;
+ char extra [256]; /* Extra stuff in fname based on mode */
+ char extradir [256]; /* Extra stuff for an output dir */
+ char createdir [256]; /* Text for system call to create output directory */
+
+ ioUtilGH = (ioGH *) GH->extensions [CCTK_GetGHExtensionHandle ("IO")];
+ pughGH = (pGH *) GH->extensions [CCTK_GetGHExtensionHandle ("PUGH")];
+
+ extra [0] = '\0';
+ extradir [0] = '\0';
+
+ nprocs = CCTK_GetnProcs (GH);
+ myproc = CCTK_GetMyProc (GH);
+
+#if 0
+ /* Say if we have a chunked data in the output file(s) */
+ if (! ioUtilGH->unchunked && nprocs > 1)
+ sprintf (extra, "%s_chunked", extra);
+#endif
+
+ if (onefileperslice)
+ sprintf (extra, "%s.time_%7.3f", extra, GH->time);
+
+
+ /* OUTPUT ONE FILE FOR EACH N PROCESSORS
+ * -------------------------------------
+ *
+ * If only one output file, the single file for each GF is written
+ * in the normal output dir (that is extradir = ""). Otherwise
+ * a directory is created for each output GF to hold the multiple
+ * file
+ */
+
+ if (ioUtilGH->ioproc_every < nprocs) {
+
+ /* Add the output processor number to the extra string */
+ sprintf (extra, "%s.file_%d", extra, myproc / ioUtilGH->ioproc_every);
+
+ /* If necessary create the output directory */
+ if (myproc == 0) {
+
+ sprintf (createdir, "mkdir -p %s/%s_3d", ioUtilGH->outpfx_3D, name);
+
+ if (IO_verbose) {
+ printf ("Creating output directory with command\n %s\n", createdir);
+ fflush (stdout);
+ }
+
+ if (system (createdir) != 0)
+ printf ("Could not create directory\n");
+ }
+
+#ifdef MPI
+ /* Wait for all processors to catch up */
+ CACTUS_MPI_ERROR (MPI_Barrier (pughGH->PUGH_COMM_WORLD));
+#endif
+
+ /* extradir is the relative output directory */
+ sprintf (extradir, "%s_3d/", name);
+
+ }
+
+
+ /* CREATE THE COMPLETE OUTPUT FILENAME
+ ----------------------------------- */
+
+ sprintf (filename, "%s/%s%s_3d%s.ieee", ioUtilGH->outpfx_3D,
+ extradir, name, extra);
+
+ /* And be sure to replace any spaces in the filename with an _ */
+ do
+ if (*filename == ' ')
+ *filename = '_';
+ while (*++filename);
+
+}
+
+
+#if 0
+void FMODIFIER FORTRAN_NAME(io_write3d_,
+ IO_WRITE3D,
+ io_write3d)
+ (Double *x)
+{
+ pGF *GF;
+
+ GF = locateGFbyDataPtr(x);
+ IO_Write3D(GF->parentGH,GF);
+
+}
+
+#endif