From ca0c7731de7c3d2bc45175af5b521c539bd66228 Mon Sep 17 00:00:00 2001 From: tradke Date: Mon, 14 Jun 2004 11:12:42 +0000 Subject: New I/O thorn for 1D/2D/3D output of datasets in SDF file format. git-svn-id: http://svn.cactuscode.org/arrangements/CactusIO/IOSDF/trunk@2 3af55ef0-e5e4-43b4-b020-ca5761ff09b2 --- COPYRIGHT | 352 ++++++++++++++++++++++++++++++++++++++++ ConfigureWithSDF.pl | 30 ++++ README | 31 ++++ configuration.ccl | 10 ++ doc/documentation.tex | 172 ++++++++++++++++++++ interface.ccl | 48 ++++++ param.ccl | 224 ++++++++++++++++++++++++++ schedule.ccl | 25 +++ src/ChooseOutput.c | 149 +++++++++++++++++ src/Output1D.c | 378 +++++++++++++++++++++++++++++++++++++++++++ src/Output2D.c | 382 +++++++++++++++++++++++++++++++++++++++++++ src/Output3D.c | 383 ++++++++++++++++++++++++++++++++++++++++++++ src/Startup.c | 251 +++++++++++++++++++++++++++++ src/Write1D.c | 436 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/Write2D.c | 371 ++++++++++++++++++++++++++++++++++++++++++ src/Write3D.c | 292 +++++++++++++++++++++++++++++++++ src/ioSDFGH.h | 87 ++++++++++ src/make.code.defn | 6 + 18 files changed, 3627 insertions(+) create mode 100644 COPYRIGHT create mode 100644 ConfigureWithSDF.pl create mode 100644 README create mode 100644 configuration.ccl create mode 100644 doc/documentation.tex create mode 100644 interface.ccl create mode 100644 param.ccl create mode 100644 schedule.ccl create mode 100644 src/ChooseOutput.c create mode 100644 src/Output1D.c create mode 100644 src/Output2D.c create mode 100644 src/Output3D.c create mode 100644 src/Startup.c create mode 100644 src/Write1D.c create mode 100644 src/Write2D.c create mode 100644 src/Write3D.c create mode 100644 src/ioSDFGH.h create mode 100644 src/make.code.defn diff --git a/COPYRIGHT b/COPYRIGHT new file mode 100644 index 0000000..57b2896 --- /dev/null +++ b/COPYRIGHT @@ -0,0 +1,352 @@ + + +This thorn is (c) Copyright the authors listed in the sources files. This +thorn is distributed under the GNU GPL with the specific exception that +the GNU GPL does not migrate to code linking to or using infrastructure +from this thorn. + +- The Cactus Team + +************************************************************************** + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 675 Mass Ave, Cambridge, MA 02139, USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + Appendix: How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. + + diff --git a/ConfigureWithSDF.pl b/ConfigureWithSDF.pl new file mode 100644 index 0000000..0c65c5d --- /dev/null +++ b/ConfigureWithSDF.pl @@ -0,0 +1,30 @@ +#! /usr/bin/perl -w +#/*@@ +# @file ConfigureWithSDF.pl +# @date Sat 12 Jube 2004 +# @author Thomas Radke +# @desc +# Configures IOSDF with external SDF installation +# @enddesc +# @version $Header$ +#@@*/ + +# SDF_DIR must be given be the user +my $bbhutil_dir = $ENV{'SDF_DIR'}; +if (! $bbhutil_dir) +{ + print "BEGIN ERROR\n"; + print "IOSDF requires an external SDF installation. Please specify " . + "SDF_DIR to point to this installation or remove thorn IOSDF " . + "from your ThornList !\n"; + print "END ERROR\n"; + exit (-1); +} + +print <\_\_.sdf} + \end{center} + and for diagonals: + \begin{center}{\tt \_3D\_diagonal.sdf} + \end{center} + These files can be processed directly by {\tt xvs} and {\tt DV}. + + \item {\tt IOSDF\_2D} + outputs two-dimensional slices of grid functions and arrays planes. + Again, slicing is done through the edge (in the octant case) or center + (in all origin centered cases).\\ + Data is written in SDF format and goes into files named +\begin{center} + {\tt \_\_
.sdf} +\end{center} + These files can be visualized by {\tt DV}. + + \item {\tt IOSDF\_3D} + outputs three-dimensional grid functions and arrays as a whole.\\ + Data is written in SDF format and goes into files named +\begin{center} + {\tt \_3D.sdf} +\end{center} + These files can be visualized by {\tt DV}. +\end{itemize} +% +% +\section{{\tt IOSDF} Parameters} +% +General parameters to control all {\tt IOSDF}'s I/O methods are: +\begin{itemize} + \item {\tt IOSDF::out[123]D\_every} (steerable)\\ + How often to do periodic {\tt IOSDF} output. If this parameter is set in the + parameter file, it will override the setting of the shared + {\tt IO::out\_every} parameter. The output frequency can also be set + for individual variables using the {\tt out\_every} option in an option string appended to the {\tt IOSDF::out[123]D\_vars} parameter. + \item {\tt IOSDF::out[123]D\_vars} (steerable)\\ + The list of variables to output using an {\tt IOSDF} I/O method. + The variables must be given by their fully qualified variable or group + name. The special keyword {\it all} requests {\tt IOSDF} output for + all variables. Multiple names must be separated by whitespaces.\\ + An option string can be appended in curly braces to the + group/variable name. The only option supported so far is {\tt out\_every} + which sets the output frequency for an individual variable (overriding + {\tt IOSDF::out[123]D\_every} and {\tt IO::out\_every}). + \item {\tt IOSDF::out[123]D\_dir}\\ + The directory in which to place the {\tt IOSDF} output files. + If the directory doesn't exist at startup it will be created.\\ + If this parameter is set to an empty string {\tt IOSDF} output will go + to the standard output directory as specified in {\tt IO::out\_dir}. +\end{itemize} +% +Additional parameters to control the {\tt IOSDF\_1D} I/O method are: +\begin{itemize} + \item {\tt IOSDF::out1D\_[xyzd]} (steerable)\\ + Chooses the directions to output in 1D {\tt IOSDF} format ({\tt d} + stands for diagonal direction). + \item {\tt IOSDF::out1D\_[xyz]line\_[xyz], IOSDF::out1D\_[xyz]line\_[xyz]i}\\ + Chooses the slice centers for 1D lines from {\tt IOSDF\_1D}. These + can be set either in physical or index coordinates. If they are set + these parameters will override the default slice center parameters + {\tt IO::out\_[xyz]line[xyz], IO::out\_[xyz]line[xyz]i}.\\ + Note that the slice center can only be set for grid functions so far. + For {\tt CCTK\_ARRAY} variables the slices will always start in the + origin, ie. (0, 0, 0) in C ordering. +\end{itemize} +% +Additional parameters to control the {\tt IOSDF\_2D} I/O method are: +\begin{itemize} + \item {\tt IOSDF::out2D\_[{xy}{xz}{yz}]plane\_[xyz], IOSDF::out2D\_[{xy}{xz}{yz}]plane\_[xyz]i}\\ + Chooses the slice centers for 2D planes from {\tt IOSDF\_2D}. These + can be set either in physical or index coordinates. If they are set + these parameters will override the default slice center parameters + {\tt IO::out\_[{xy}{xz}{yz}]plane[xyz], IO::out\_[{xy}{xz}{yz}]plane[xyz]i}. +\end{itemize} +% +Additional {\tt IOUtil} parameters to control the {\tt IOSDF\_[123]D} I/O methods are: +\begin{itemize} + \item {\tt IO::out\_downsample\_[xyz]}\\ + Chooses downsampling factors for individual dimensions (default is 1 + meaning no downsampling). +\end{itemize} +% +% +\section{Comments} +% +{\bf Getting Output from {\tt IOSDF}'s I/O Mehtods}\\ +% +You obtain output by an I/O method by either +% +\begin{itemize} + \item setting the appropriate I/O parameters + \item calling one the routines of the I/O function interface provided by the flesh +\end{itemize} +% +For a description of basic I/O parameters and the I/O function interface to +invoke I/O methods by application thorns please see the documentation of thorn +{\tt IOUtil} and the flesh.\\[3ex] +% +{\bf Building Cactus configurations with {\tt IOSDF}}\\ +% +In order to build thorn {\tt IOSDF} an external SDF installation (with includes +and libraries) is required. You must specify the location of this SDF +installation via the configure-time option\\ +\centerline{\tt SDF\_LOCATION=}. + +Since {\tt IOSDF} uses parameters from {\tt IOUtil} it also needs this I/O +helper thorn be compiled into Cactus and activated at runtime in the +{\tt ActiveThorns} parameter in your parameter file. +% +% +\begin{thebibliography}{9} + +\bibitem{DataVaultXVSutils_package} +\url{http://www.cactuscode.org/VizTools/DataVaultXVSutils.html} + +\bibitem{xvs_documentation} +\url{http://laplace.physics.ubc.ca/\~matt/410/Doc/xvs/} + +\bibitem{DV_tutorial} +\url{http://laplace.physics.ubc.ca/Doc/DV/} +\end{thebibliography} + + +% Do not delete next line +% END CACTUS THORNGUIDE + +\end{document} diff --git a/interface.ccl b/interface.ccl new file mode 100644 index 0000000..2c84453 --- /dev/null +++ b/interface.ccl @@ -0,0 +1,48 @@ +# Interface definition for thorn IOSDF +# $Header$ + +implements: IOSDF +inherits: IO + +CCTK_INT FUNCTION \ + Hyperslab_GetList (CCTK_POINTER_TO_CONST IN cctkGH, \ + CCTK_INT IN mapping_handle, \ + CCTK_INT IN num_arrays, \ + CCTK_INT ARRAY IN procs, \ + CCTK_INT ARRAY IN vindices, \ + CCTK_INT ARRAY IN timelevels, \ + CCTK_INT ARRAY IN hdatatypes, \ + CCTK_POINTER ARRAY IN hdata, \ + CCTK_INT ARRAY OUT retvals) + +CCTK_INT FUNCTION \ + Hyperslab_GlobalMappingByIndex (CCTK_POINTER_TO_CONST IN cctkGH, \ + CCTK_INT IN vindex, \ + CCTK_INT IN hdim, \ + CCTK_INT ARRAY IN direction, \ + CCTK_INT ARRAY IN origin, \ + CCTK_INT ARRAY IN extent, \ + CCTK_INT ARRAY IN downsample, \ + CCTK_INT IN table_handle, \ + CCTK_INT CCTK_FPOINTER IN \ + conversion_fn (CCTK_INT IN nelems, \ + CCTK_INT IN src_stride, \ + CCTK_INT IN dst_stride, \ + CCTK_INT IN src_type, \ + CCTK_INT IN dst_type, \ + CCTK_POINTER_TO_CONST IN from, \ + CCTK_POINTER IN to), \ + CCTK_INT ARRAY OUT hsize) + +CCTK_INT FUNCTION Hyperslab_FreeMapping (CCTK_INT IN mapping_handle) + + +REQUIRES FUNCTION Hyperslab_GetList +REQUIRES FUNCTION Hyperslab_GlobalMappingByIndex +REQUIRES FUNCTION Hyperslab_FreeMapping + +CCTK_INT FUNCTION Coord_GroupSystem \ + (CCTK_POINTER_TO_CONST IN GH, \ + CCTK_STRING IN groupname) + +REQUIRES FUNCTION Coord_GroupSystem diff --git a/param.ccl b/param.ccl new file mode 100644 index 0000000..7331e0b --- /dev/null +++ b/param.ccl @@ -0,0 +1,224 @@ +# Parameter definitions for thorn IOSDF +# $Header$ + + +############################################################################# +### declare IOSDF parameters +############################################################################# +private: + +########################## +# Directories to output to +########################## +STRING out1D_dir "Output directory for 1D IOSDF files, overrides IO::out_dir" STEERABLE = RECOVER +{ + ".+" :: "A valid directory name" + "^$" :: "An empty string to choose the default from IO::out_dir" +} "" +STRING out2D_dir "Output directory for 2D IOSDF files, overrides out_dir" STEERABLE = RECOVER +{ + ".+" :: "A valid directory name" + "^$" :: "An empty string to choose the default from IO::out_dir" +} "" +STRING out3D_dir "Output directory for 3D IOSDF files, overrides IO::out_dir" STEERABLE = RECOVER +{ + ".+" :: "A valid directory name" + "^$" :: "An empty string to choose the default from IO::out_dir" +} "" + + +########################## +# What variables to output +########################## +STRING out1D_vars "Variables to output in 1D IOSDF file format" STEERABLE = ALWAYS +{ + ".+" :: "Space-separated list of fully qualified variable/group names" + "^$" :: "An empty string to output nothing" +} "" +STRING out2D_vars "Variables to output in 2D IOSDF file format" STEERABLE = ALWAYS +{ + ".+" :: "Space-separated list of fully qualified variable/group names" + "^$" :: "An empty string to output nothing" +} "" +STRING out3D_vars "Variables to output in 3D IOSDF file format" STEERABLE = ALWAYS +{ + ".+" :: "Space-separated list of fully qualified variable/group names" + "^$" :: "An empty string to output nothing" +} "" + + +######################## +# How often to do output +######################## +INT out1D_every "How often to do 1D IOSDF output, overrides IO::out_every" STEERABLE = ALWAYS +{ + 1:* :: "Every so many iterations" + 0: :: "Disable 1D IOSDF output" + -1: :: "Default to IO::out_every" +} -1 +INT out2D_every "How often to do 2D IOSDF output, overrides IO::out_every" STEERABLE = ALWAYS +{ + 1:* :: "Every so many iterations" + 0: :: "Disable 2D IOSDF output" + -1: :: "Default to IO::out_every" +} -1 +INT out3D_every "How often to do 3D IOSDF output, overrides IO::out_every" STEERABLE = ALWAYS +{ + 1:* :: "Every so many iterations" + 0: :: "Disable 3D IOSDF output" + -1: :: "Default to IO::out_every" +} -1 + + +############################ +# Specific to 1D output +# Choosing what output to do +############################ +BOOLEAN out1D_x "Do 1D IOSDF output in the x-direction" STEERABLE = ALWAYS +{ +} "yes" +BOOLEAN out1D_y "Do 1D IOSDF output in the y-direction" STEERABLE = ALWAYS +{ +} "yes" +BOOLEAN out1D_z "Do 1D IOSDF output in the z-direction" STEERABLE = ALWAYS +{ +} "yes" +BOOLEAN out1D_d "Do 1D IOSDF output in the diagonal-direction" STEERABLE = ALWAYS +{ +} "yes" + +################################ +# Choosing what slices to output +################################ +REAL out1D_xline_y "y-coord for 1D lines in x-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [ymin, ymax]" + -424242: :: "Default to IO::out_xline_y" +} -424242 +REAL out1D_xline_z "z-coord for 1D lines in x-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [zmin, zmax]" + -424242: :: "Default to IO::out_xline_z" +} -424242 +REAL out1D_yline_x "x-coord for 1D lines in y-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [xmin, xmax]" + -424242: :: "Default to IO::out_yline_x" +} -424242 +REAL out1D_yline_z "z-coord for 1D lines in y-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [zmin, zmax]" + -424242: :: "Default to IO::out_yline_z" +} -424242 +REAL out1D_zline_x "x-coord for 1D lines in z-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [xmin, xmax]" + -424242: :: "Default to IO::out_zline_x" +} -424242 +REAL out1D_zline_y "y-coord for 1D lines in z-direction" STEERABLE = RECOVER +{ + *:* :: "A value between [ymin, ymax]" + -424242: :: "Default to IO::out_zline_y" +} -424242 + +INT out1D_xline_yi "y-index (from 0) for 1D lines in x-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, ny)" + -1: :: "Choose the default from IO::out_xline_yi" +} -1 +INT out1D_xline_zi "z-index (from 0) for 1D lines in x-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nz)" + -1: :: "Choose the default from IO::out_xline_zi" +} -1 + +INT out1D_yline_xi "x-index (from 0) for 1D lines in y-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nx)" + -1: :: "Choose the default from IO::out_yline_xi" +} -1 +INT out1D_yline_zi "z-index (from 0) for 1D lines in y-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nz)" + -1: :: "Choose the default from IO::out_yline_zi" +} -1 + +INT out1D_zline_xi "x-index (from 0) for 1D lines in z-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nx)" + -1: :: "Choose the default from IO::out_zline_xi" +} -1 +INT out1D_zline_yi "y-index (from 0) for 1D lines in z-direction" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, ny)" + -1: :: "Choose the default from IO::out_zline_yi" +} -1 + + +################################ +# Specific to 2D output +# Choosing what planes to output +################################ +REAL out2D_yzplane_x "x-coord for 2D planes in yz" STEERABLE = RECOVER +{ + *:* :: "A value between [xmin, xmax]" + -424242: :: "Default to IO::out_yzplane_x" +} -424242 +REAL out2D_xzplane_y "y-coord for 2D planes in xz" STEERABLE = RECOVER +{ + *:* :: "A value between [ymin, ymax]" + -424242: :: "Default to IO::out_xzplane_y" +} -424242 +REAL out2D_xyplane_z "z-coord for 2D planes in xy" STEERABLE = RECOVER +{ + *:* :: "A value between [zmin, zmax]" + -424242: :: "Default to IO::out_xyplane_z" +} -424242 + +INT out2D_yzplane_xi "x-index (from 0) for 2D planes in yz" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nx)" + -1: :: "Choose the default from IO::out_yzplane_xi" +} -1 +INT out2D_xzplane_yi "y-index (from 0) for 2D planes in xz" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, ny)" + -1: :: "Choose the default from IO::out_xzplane_yi" +} -1 +INT out2D_xyplane_zi "z-index (from 0) for 2D planes in xy" STEERABLE = RECOVER +{ + 0:* :: "An index between [0, nz)" + -1: :: "Choose the default from IO::out_xyplane_zi" +} -1 + + +############################################################################# +### import IOUtil parameters +############################################################################# +shares: IO + +USES STRING out_dir +USES INT out_every +USES REAL out_xline_y +USES REAL out_xline_z +USES REAL out_yline_x +USES REAL out_yline_z +USES REAL out_zline_x +USES REAL out_zline_y +USES INT out_xline_yi +USES INT out_xline_zi +USES INT out_yline_xi +USES INT out_yline_zi +USES INT out_zline_xi +USES INT out_zline_yi +USES REAL out_yzplane_x +USES REAL out_xzplane_y +USES REAL out_xyplane_z +USES INT out_yzplane_xi +USES INT out_xzplane_yi +USES INT out_xyplane_zi +USES INT out_downsample_x +USES INT out_downsample_y +USES INT out_downsample_z +USES KEYWORD verbose +USES BOOLEAN strict_io_parameter_check diff --git a/schedule.ccl b/schedule.ccl new file mode 100644 index 0000000..de179c8 --- /dev/null +++ b/schedule.ccl @@ -0,0 +1,25 @@ +# Schedule definitions for thorn IOSDF +# $Header$ + +######################################################################## +### register IOSDF routines +######################################################################## +schedule IOSDF_Startup at STARTUP after IOUtil_Startup +{ + LANG:C +} "Startup routine" + +schedule IOSDF_Choose1D at BASEGRID after SpatialCoordinates +{ + LANG:C +} "Choose 1D output lines" + +schedule IOSDF_Choose2D at BASEGRID after SpatialCoordinates +{ + LANG:C +} "Choose 2D output planes" + +schedule IOSDF_Terminate at TERMINATE +{ + LANG:C +} "Close all open SDF output files" diff --git a/src/ChooseOutput.c b/src/ChooseOutput.c new file mode 100644 index 0000000..00ae902 --- /dev/null +++ b/src/ChooseOutput.c @@ -0,0 +1,149 @@ +/*@@ + @file ChooseOutput.c + @author Thomas Radke + @date 12 June 2004 + @desc + Choose what 1D slices and 2D planes to output by IOSDF. + @enddesc + + @version $Id$ + @@*/ + +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Header$"; +CCTK_FILEVERSION(CactusIO_IOSDF_ChooseOutput_c) + + +/******************************************************************** + ******************** Macro Definitions ************************ + ********************************************************************/ +/* macro to choose origin according actual parameter settings: + 1. Indices from IOSDF + 2. Indices from IOUtil + 3. Coords from IOSDF + 4. Coords from IOUtil + */ +#define GET_SLICE(IOSDF_param, IOUtil_param, index, coord) \ + { \ + index = IOSDF_param##i >= 0 ? IOSDF_param##i : IOUtil_param##i; \ + coord = IOSDF_param != -424242 ? IOSDF_param : IOUtil_param; \ + } + + +/*@@ + @routine IOSDF_Choose1D + @author Thomas Radke + @date 12 June 2004 + @desc + Use parameters to choose the 1D slices through the output data. + @enddesc + + @calls IOUtil_1DLines + + @var GH + @vdesc pointer to CCTK grid hierarchy + @vtype const cGH * + @vio in + @endvar +@@*/ +void IOSDF_Choose1D (const cGH *GH) +{ + int i, j, maxdim; + ioSDFGH *myGH; + int *origin_index[3]; + CCTK_REAL *origin_phys[3]; + DECLARE_CCTK_PARAMETERS + + + /* allocate arrays for origins */ + origin_phys[0] = malloc (3 * 3 * sizeof (CCTK_REAL)); + origin_phys[1] = origin_phys[0] + 3; + origin_phys[2] = origin_phys[1] + 3; + origin_index[0] = malloc (3 * 3 * sizeof (int)); + origin_index[1] = origin_index[0] + 3; + origin_index[2] = origin_index[1] + 3; + + /* get slice points */ + GET_SLICE (out1D_xline_y, out_xline_y, origin_index[0][1], origin_phys[0][1]); + GET_SLICE (out1D_xline_z, out_xline_z, origin_index[0][2], origin_phys[0][2]); + GET_SLICE (out1D_yline_x, out_yline_x, origin_index[1][0], origin_phys[1][0]); + GET_SLICE (out1D_yline_z, out_yline_z, origin_index[1][2], origin_phys[1][2]); + GET_SLICE (out1D_zline_x, out_zline_x, origin_index[2][0], origin_phys[2][0]); + GET_SLICE (out1D_zline_y, out_zline_y, origin_index[2][1], origin_phys[2][1]); + + maxdim = CCTK_MaxDim (); + myGH = CCTK_GHExtension (GH, "IOSDF"); + myGH->spxyz = malloc (maxdim * sizeof (int **)); + + for (i = 0; i < maxdim; i++) + { + myGH->spxyz[i] = malloc ((i + 1) * sizeof (int *)); + + for (j = 0; j <= i; j++) + { + myGH->spxyz[i][j] = calloc (i + 1, sizeof (int)); + } + + if (i < 3) + { + IOUtil_1DLines (GH, i + 1, origin_index, origin_phys, myGH->spxyz[i]); + } + } + + /* free allocated resources */ + free (origin_phys[0]); + free (origin_index[0]); +} + + +/*@@ + @routine IOSDF_Choose2D + @author Thomas Radke + @date 12 June 2004 + @desc + Use parameters to choose the 2D slices through the output data. + @enddesc + + @calls IOUtil_2DPlanes + + @var GH + @vdesc Pointer to CCTK grid hierarchy + @vtype const cGH * + @vio in + @endvar + @@*/ +void IOSDF_Choose2D (const cGH *GH) +{ + int i, maxdim; + ioSDFGH *myGH; + int origin_index[3]; + CCTK_REAL origin_phys[3]; + DECLARE_CCTK_PARAMETERS + + + GET_SLICE (out2D_xyplane_z, out_xyplane_z, origin_index[0], origin_phys[0]); + GET_SLICE (out2D_xzplane_y, out_xzplane_y, origin_index[1], origin_phys[1]); + GET_SLICE (out2D_yzplane_x, out_yzplane_x, origin_index[2], origin_phys[2]); + + maxdim = CCTK_MaxDim (); + myGH = CCTK_GHExtension (GH, "IOSDF"); + myGH->sp2xyz = malloc (3 * sizeof (int *)); + + for (i = 0; i < maxdim; i++) + { + myGH->sp2xyz[i] = calloc (i + 1, sizeof (int)); + + if (i == 2) + { + IOUtil_2DPlanes (GH, i + 1, origin_index, origin_phys, myGH->sp2xyz[i]); + } + } +} diff --git a/src/Output1D.c b/src/Output1D.c new file mode 100644 index 0000000..1f572f9 --- /dev/null +++ b/src/Output1D.c @@ -0,0 +1,378 @@ + /*@@ + @file Output1D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Functions to deal with 1D SDF output of variables + @enddesc + @version $Id$ + @@*/ + +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "util_String.h" +#include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Id$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Output1D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static int CheckOutputVar (int vindex); +static void SetOutputFlag (int vindex, const char *optstring, void *arg); + + +/*@@ + @routine IOSDF_Output1DGH + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Loops over all variables and outputs them if necessary + @enddesc + @calls IOSDF_TimeFor1D + IOSDF_Write1D + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + + @returntype int + @returndesc + the number of variables which were output at this iteration + (or 0 if it wasn't time to output yet) + @endreturndesc +@@*/ +int IOSDF_Output1DGH (const cGH *GH) +{ + int vindex, retval; + const ioSDFGH *myGH; + + + retval = 0; + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* loop over all variables */ + for (vindex = CCTK_NumVars () - 1; vindex >= 0; vindex--) + { + if (IOSDF_TimeFor1D (GH, vindex) && + IOSDF_Write1D (GH, vindex, CCTK_VarName (vindex)) == 0) + { + /* register variable as having 1D output this iteration */ + myGH->out1D_last[vindex] = GH->cctk_iteration; + retval++; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_Output1DVarAs + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Unconditional output of a variable + using the IOSDF output method + @enddesc + @calls IOSDF_Write1D + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var fullname + @vdesc complete name of variable to output + @vtype const char * + @vio in + @endvar + @var alias + @vdesc alias name of variable to output + (used to generate output filename) + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write1D, or
+ -1 if variable cannot be output by IOSDF_1D + @endreturndesc +@@*/ +int IOSDF_Output1DVarAs (const cGH *GH, const char *fullname, const char *alias) +{ + int vindex, retval; + + + retval = -1; + vindex = CCTK_VarIndex (fullname); + if (vindex < 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "There is no such variable %s. Ignoring IOSDF 1D output.", + fullname); + } + else if (CheckOutputVar (vindex)) + { + retval = IOSDF_Write1D (GH, vindex, alias); + } + + return (retval); +} + + + /*@@ + @routine IOSDF_TimeFor1D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Decides if it is time to output a variable + using the IO 1D output method + @enddesc + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable + @vtype int + @vio in + @endvar + + @returntype int + @returndesc + 1 if output should take place at this iteration, or
+ 0 if not + @endreturndesc +@@*/ +int IOSDF_TimeFor1D (const cGH *GH, int vindex) +{ + int retval; + char *fullname; + ioSDFGH *myGH; + + + myGH = CCTK_GHExtension (GH, "IOSDF"); + IOSDF_CheckSteerableParameters1D (myGH); + + /* check if this variable should be output */ + retval = myGH->out1D_every[vindex] > 0 && + GH->cctk_iteration % myGH->out1D_every[vindex] == 0; + if (retval) + { + /* check if this variable wasn't already output this iteration */ + if (myGH->out1D_last[vindex] == GH->cctk_iteration) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, + "Already done IOSDF 1D output for '%s' in current " + "iteration (probably via triggers)", fullname); + free (fullname); + retval = 0; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_TriggerOutput1D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Triggers the output a variable + using the IOSDF output method method + @enddesc + @calls IOSDF_Write1D + + @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 + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write1D + @endreturndesc +@@*/ +int IOSDF_TriggerOutput1D (const cGH *GH, int vindex) +{ + int retval; + ioSDFGH *myGH; + + + retval = IOSDF_Write1D (GH, vindex, CCTK_VarName (vindex)); + if (retval == 0) + { + /* register variables as having 1D output this iteration */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + myGH->out1D_last[vindex] = GH->cctk_iteration; + } + + return (retval); +} + + +/*@@ + @routine IOSDF_CheckSteerableParameters1D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Check if steerable IOSDF 1D parameters have changed + @enddesc + @calls CCTK_TraverseString + + @var myGH + @vdesc Pointer to IOSDF GH + @vtype ioSDFGH * + @vio inout + @endvar +@@*/ +void IOSDF_CheckSteerableParameters1D (ioSDFGH *myGH) +{ + int i, num_vars; + char *fullname, *msg; + DECLARE_CCTK_PARAMETERS + + + /* how often to output */ + i = myGH->out1D_every_default; + myGH->out1D_every_default = out1D_every >= 0 ? out1D_every : out_every; + + /* report if frequency changed */ + if (myGH->out1D_every_default != i && ! CCTK_Equals (verbose, "none")) + { + if (myGH->out1D_every_default > 0) + { + CCTK_VInfo (CCTK_THORNSTRING, "Periodic 1D output every %d " + "iterations", myGH->out1D_every_default); + } + else + { + CCTK_INFO ("Periodic 1D output turned off"); + } + } + + /* re-parse the 'out1D_vars' parameter if it was changed */ + if (strcmp (out1D_vars, myGH->out1D_vars) || myGH->out1D_every_default != i) + { + num_vars = CCTK_NumVars (); + memset (myGH->out1D_every, 0, num_vars * sizeof (CCTK_INT)); + if (CCTK_TraverseString (out1D_vars, SetOutputFlag, myGH, + CCTK_GROUP_OR_VAR) < 0) + { + CCTK_WARN (myGH->stop_on_parse_errors ? 0 : 1, + "error while parsing parameter 'IOSDF::out1D_vars'"); + } + + if (myGH->out1D_every_default == i || ! CCTK_Equals (verbose, "none")) + { + msg = NULL; + for (i = 0; i < num_vars; i++) + { + if (myGH->out1D_every[i] > 0) + { + fullname = CCTK_FullName (i); + if (! msg) + { + Util_asprintf (&msg, "Periodic 1D output requested for " + "'%s'", fullname); + } + else + { + Util_asprintf (&msg, "%s, '%s'", msg, fullname); + } + free (fullname); + } + } + if (msg) + { + CCTK_INFO (msg); + free (msg); + } + } + + /* save the last setting of 'out1D_vars' parameter */ + free (myGH->out1D_vars); + myGH->out1D_vars = strdup (out1D_vars); + } +} + + +/**************************** local functions ******************************/ +/* check if this variable can be output (static conditions) */ +static int CheckOutputVar (int vindex) +{ + int groupindex; + cGroup groupinfo; + char *fullname; + const char *errormsg; + + + /* get the variable group information */ + groupindex = CCTK_GroupIndexFromVarI (vindex); + CCTK_GroupData (groupindex, &groupinfo); + + errormsg = NULL; + if (groupinfo.grouptype != CCTK_GF && groupinfo.grouptype != CCTK_ARRAY) + { + errormsg = "not a grid function or array"; + } + else if (strncmp (CCTK_VarTypeName (groupinfo.vartype), + "CCTK_VARIABLE_REAL", 18) || + CCTK_VarTypeSize (groupinfo.vartype) != sizeof (double)) + { + errormsg = "not a double-precision floating-point grid function or array"; + } + + if (errormsg) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOSDF 1D output for '%s': %s", fullname, errormsg); + free (fullname); + } + + return (errormsg == NULL); +} + + +/* callback for CCTK_TraverseString() to set the output flag + for the given variable */ +static void SetOutputFlag (int vindex, const char *optstring, void *arg) +{ + const ioSDFGH *myGH = arg; + + + if (CheckOutputVar (vindex)) + { + myGH->out1D_every[vindex] = myGH->out1D_every_default; + + if (optstring) + { + IOUtil_ParseOutputFrequency ("1D IOSDF", "IOSDF::out1D_vars", + myGH->stop_on_parse_errors, + vindex, optstring, + &myGH->out1D_every[vindex]); + } + } +} diff --git a/src/Output2D.c b/src/Output2D.c new file mode 100644 index 0000000..5eb5161 --- /dev/null +++ b/src/Output2D.c @@ -0,0 +1,382 @@ + /*@@ + @file Output2D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Functions to deal with 2D SDF output of variables + @enddesc + @version $Id$ + @@*/ + +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "util_String.h" +#include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Id$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Output2D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static int CheckOutputVar (int vindex); +static void SetOutputFlag (int vindex, const char *optstring, void *arg); + + +/*@@ + @routine IOSDF_Output2DGH + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Loops over all variables and outputs them if necessary + @enddesc + @calls IOSDF_TimeFor2D + IOSDF_Write2D + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + + @returntype int + @returndesc + the number of variables which were output at this iteration + (or 0 if it wasn't time to output yet) + @endreturndesc +@@*/ +int IOSDF_Output2DGH (const cGH *GH) +{ + int vindex, retval; + const ioSDFGH *myGH; + + + retval = 0; + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* loop over all variables */ + for (vindex = CCTK_NumVars () - 1; vindex >= 0; vindex--) + { + if (IOSDF_TimeFor2D (GH, vindex) && + IOSDF_Write2D (GH, vindex, CCTK_VarName (vindex)) == 0) + { + /* register variable as having 2D output this iteration */ + myGH->out2D_last[vindex] = GH->cctk_iteration; + retval++; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_Output2DVarAs + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Unconditional output of a variable + using the IOSDF 2D output method + @enddesc + @calls IOSDF_Write2D + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var fullname + @vdesc complete name of variable to output + @vtype const char * + @vio in + @endvar + @var alias + @vdesc alias name of variable to output + (used to generate output filename) + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write2D, or
+ -1 if variable cannot be output by IOSDF_2D + @endreturndesc +@@*/ +int IOSDF_Output2DVarAs (const cGH *GH, const char *fullname, const char *alias) +{ + int vindex, retval; + + + retval = -1; + vindex = CCTK_VarIndex (fullname); + if (vindex<0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "There is no such variable %s. Ignoring IOSDF 2D output.", + fullname); + } else if (CheckOutputVar (vindex) == 0) + { + retval = IOSDF_Write2D (GH, vindex, alias); + } + + return (retval); +} + + + /*@@ + @routine IOSDF_TimeFor2D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Decides if it is time to output a variable + using the IOSDF 2D output method + @enddesc + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable + @vtype int + @vio in + @endvar + + @returntype int + @returndesc + 1 if output should take place at this iteration, or
+ 0 if not + @endreturndesc +@@*/ +int IOSDF_TimeFor2D (const cGH *GH, int vindex) +{ + int retval; + char *fullname; + ioSDFGH *myGH; + + + myGH = CCTK_GHExtension (GH, "IOSDF"); + IOSDF_CheckSteerableParameters2D (myGH); + + /* check if this variable should be output */ + retval = myGH->out2D_every[vindex] > 0 && + GH->cctk_iteration % myGH->out2D_every[vindex] == 0; + if (retval) + { + /* check if variable wasn't already output this iteration */ + if (myGH->out2D_last[vindex] == GH->cctk_iteration) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, + "Already done IOSDF 2D output for '%s' in current " + "iteration (probably via triggers)", fullname); + free (fullname); + retval = 0; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_TriggerOutput2D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Triggers the output of a variable + using the IOSDF 2D output method + @enddesc + @calls IOSDF_Write2D + + @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 + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write2D + @endreturndesc +@@*/ +int IOSDF_TriggerOutput2D (const cGH *GH, int vindex) +{ + int retval; + ioSDFGH *myGH; + + + /* do the 2D output */ + retval = IOSDF_Write2D (GH, vindex, CCTK_VarName (vindex)); + if (retval == 0) + { + /* register variable as having 2D output this iteration */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + myGH->out2D_last[vindex] = GH->cctk_iteration; + } + + return (retval); +} + + +/*@@ + @routine IOSDF_CheckSteerableParameters2D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Check if steerable IOSDF 2D parameters have changed + @enddesc + @calls CCTK_TraverseString + + @var myGH + @vdesc Pointer to IOSDF GH + @vtype ioSDFGH * + @vio inout + @endvar +@@*/ +void IOSDF_CheckSteerableParameters2D (ioSDFGH *myGH) +{ + int i, num_vars; + char *fullname, *msg; + DECLARE_CCTK_PARAMETERS + + + /* how often to output */ + i = myGH->out2D_every_default; + myGH->out2D_every_default = out2D_every >= 0 ? out2D_every : out_every; + + /* report if frequency changed */ + if (myGH->out2D_every_default != i && ! CCTK_Equals (verbose, "none")) + { + if (myGH->out2D_every_default > 0) + { + CCTK_VInfo (CCTK_THORNSTRING, "Periodic 2D output every %d " + "iterations", myGH->out2D_every_default); + } + else + { + CCTK_INFO ("Periodic 2D output turned off"); + } + } + + /* re-parse the 'out2D_vars' parameter if it was changed */ + if (strcmp (out2D_vars, myGH->out2D_vars) || myGH->out2D_every_default != i) + { + num_vars = CCTK_NumVars (); + memset (myGH->out2D_every, 0, num_vars * sizeof (CCTK_INT)); + if (CCTK_TraverseString (out2D_vars, SetOutputFlag, myGH, + CCTK_GROUP_OR_VAR) < 0) + { + CCTK_WARN (myGH->stop_on_parse_errors ? 0 : 1, + "error while parsing parameter 'IOSDF::out2D_vars'"); + } + + if (myGH->out2D_every_default == i || ! CCTK_Equals (verbose, "none")) + { + msg = NULL; + for (i = 0; i < num_vars; i++) + { + if (myGH->out2D_every[i]) + { + fullname = CCTK_FullName (i); + if (! msg) + { + Util_asprintf (&msg, "Periodic 2D output requested for " + "'%s'", fullname); + } + else + { + Util_asprintf (&msg, "%s, '%s'", msg, fullname); + } + free (fullname); + } + } + if (msg) + { + CCTK_INFO (msg); + free (msg); + } + } + + /* save the last setting of 'out2D_vars' parameter */ + free (myGH->out2D_vars); + myGH->out2D_vars = strdup (out2D_vars); + } +} + + +/**************************** local functions ******************************/ +/* check if this variable can be output (static conditions) */ +static int CheckOutputVar (int vindex) +{ + int groupindex; + cGroup groupinfo; + char *fullname; + const char *errormsg; + + + /* get the variable group information */ + groupindex = CCTK_GroupIndexFromVarI (vindex); + CCTK_GroupData (groupindex, &groupinfo); + + errormsg = NULL; + if (groupinfo.dim < 2 || groupinfo.dim > 3) + { + errormsg = "dim != [2,3]"; + } + else if (groupinfo.grouptype != CCTK_GF && groupinfo.grouptype != CCTK_ARRAY) + { + errormsg = "not a grid function or array"; + } + else if (strncmp (CCTK_VarTypeName (groupinfo.vartype), + "CCTK_VARIABLE_REAL", 18) || + CCTK_VarTypeSize (groupinfo.vartype) != sizeof (double)) + { + errormsg = "not a double-precision floating-point grid function or array"; + } + + if (errormsg) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOSDF 2D output for '%s': %s", fullname, errormsg); + free (fullname); + } + + return (errormsg != NULL); +} + + +/* callback for CCTK_TraverseString() to set the output flag + for the given variable */ +static void SetOutputFlag (int vindex, const char *optstring, void *arg) +{ + const ioSDFGH *myGH = arg; + + + if (CheckOutputVar (vindex) == 0) + { + myGH->out2D_every[vindex] = myGH->out2D_every_default; + + if (optstring) + { + IOUtil_ParseOutputFrequency ("2D IOSDF", "IOSDF::out2D_vars", + myGH->stop_on_parse_errors, + vindex, optstring, + &myGH->out2D_every[vindex]); + } + } +} diff --git a/src/Output3D.c b/src/Output3D.c new file mode 100644 index 0000000..16e01a5 --- /dev/null +++ b/src/Output3D.c @@ -0,0 +1,383 @@ + /*@@ + @file Output3D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Functions to deal with 3D SDF output of variables + @enddesc + @version $Id$ + @@*/ + +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "util_String.h" +#include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Id$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Output3D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static int CheckOutputVar (int vindex); +static void SetOutputFlag (int vindex, const char *optstring, void *arg); + + +/*@@ + @routine IOSDF_Output3DGH + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Loops over all variables and outputs them if necessary + @enddesc + @calls IOSDF_TimeFor3D + IOSDF_Write3D + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + + @returntype int + @returndesc + the number of variables which were output at this iteration + (or 0 if it wasn't time to output yet) + @endreturndesc +@@*/ +int IOSDF_Output3DGH (const cGH *GH) +{ + int vindex, retval; + const ioSDFGH *myGH; + + + retval = 0; + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* loop over all variables */ + for (vindex = CCTK_NumVars () - 1; vindex >= 0; vindex--) + { + if (IOSDF_TimeFor3D (GH, vindex) && + IOSDF_Write3D (GH, vindex, CCTK_VarName (vindex)) == 0) + { + /* register variable as having 3D output this iteration */ + myGH->out3D_last[vindex] = GH->cctk_iteration; + retval++; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_Output3DVarAs + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Unconditional output of a variable + using the IOSDF 3D output method + @enddesc + @calls IOSDF_Write3D + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var fullname + @vdesc complete name of variable to output + @vtype const char * + @vio in + @endvar + @var alias + @vdesc alias name of variable to output + (used to generate output filename) + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write3D, or
+ -1 if variable cannot be output by IOSDF_3D + @endreturndesc +@@*/ +int IOSDF_Output3DVarAs (const cGH *GH, const char *fullname, const char *alias) +{ + int vindex, retval; + + + retval = -1; + vindex = CCTK_VarIndex (fullname); + if (vindex<0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "There is no such variable %s. Ignoring IOSDF 3D output.", + fullname); + } else if (CheckOutputVar (vindex) == 0) + { + retval = IOSDF_Write3D (GH, vindex, alias); + } + + return (retval); +} + + + /*@@ + @routine IOSDF_TimeFor3D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Decides if it is time to output a variable + using the IOSDF 3D output method + @enddesc + + @var GH + @vdesc pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc index of variable + @vtype int + @vio in + @endvar + + @returntype int + @returndesc + 1 if output should take place at this iteration, or
+ 0 if not + @endreturndesc +@@*/ +int IOSDF_TimeFor3D (const cGH *GH, int vindex) +{ + int retval; + char *fullname; + ioSDFGH *myGH; + + + myGH = CCTK_GHExtension (GH, "IOSDF"); + IOSDF_CheckSteerableParameters3D (myGH); + + /* check if this variable should be output */ + retval = myGH->out3D_every[vindex] > 0 && + GH->cctk_iteration % myGH->out3D_every[vindex] == 0; + if (retval) + { + /* check if variable wasn't already output this iteration */ + if (myGH->out3D_last[vindex] == GH->cctk_iteration) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (5, __LINE__, __FILE__, CCTK_THORNSTRING, + "Already done IOSDF 3D output for '%s' in current " + "iteration (probably via triggers)", fullname); + free (fullname); + retval = 0; + } + } + + return (retval); +} + + +/*@@ + @routine IOSDF_TriggerOutput3D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Triggers the output of a variable + using the IOSDF 3D output method + @enddesc + @calls IOSDF_Write3D + + @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 + + @returntype int + @returndesc + return code of @seeroutine IOSDF_Write3D + @endreturndesc +@@*/ +int IOSDF_TriggerOutput3D (const cGH *GH, int vindex) +{ + int retval; + ioSDFGH *myGH; + + + /* do the 3D output */ + retval = IOSDF_Write3D (GH, vindex, CCTK_VarName (vindex)); + if (retval == 0) + { + /* register variables as having 3D output this iteration */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + myGH->out3D_last[vindex] = GH->cctk_iteration; + } + + return (retval); +} + + +/*@@ + @routine IOSDF_CheckSteerableParameters3D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Check if steerable IOSDF 3D parameters have changed + @enddesc + @calls CCTK_TraverseString + + @var myGH + @vdesc Pointer to IOSDF GH + @vtype ioSDFGH * + @vio inout + @endvar +@@*/ +void IOSDF_CheckSteerableParameters3D (ioSDFGH *myGH) +{ + int i, num_vars; + char *fullname, *msg; + DECLARE_CCTK_PARAMETERS + + + /* how often to output */ + i = myGH->out3D_every_default; + myGH->out3D_every_default = out3D_every >= 0 ? out3D_every : out_every; + + /* report if frequency changed */ + if (myGH->out3D_every_default != i && ! CCTK_Equals (verbose, "none")) + { + if (myGH->out3D_every_default > 0) + { + CCTK_VInfo (CCTK_THORNSTRING, "Periodic 3D output every %d " + "iterations", myGH->out3D_every_default); + } + else + { + CCTK_INFO ("Periodic 3D output turned off"); + } + } + + /* re-parse the 'out3D_vars' parameter if it was changed */ + if (strcmp (out3D_vars, myGH->out3D_vars) || myGH->out3D_every_default != i) + { + num_vars = CCTK_NumVars (); + memset (myGH->out3D_every, 0, num_vars * sizeof (CCTK_INT)); + if (CCTK_TraverseString (out3D_vars, SetOutputFlag, myGH, + CCTK_GROUP_OR_VAR) < 0) + { + CCTK_WARN (myGH->stop_on_parse_errors ? 0 : 1, + "error while parsing parameter 'IOSDF::out3D_vars'"); + } + + if (myGH->out3D_every_default == i || ! CCTK_Equals (verbose, "none")) + { + msg = NULL; + for (i = 0; i < num_vars; i++) + { + if (myGH->out3D_every[i] > 0) + { + fullname = CCTK_FullName (i); + if (! msg) + { + Util_asprintf (&msg, "Periodic 3D output requested for " + "'%s'", fullname); + } + else + { + Util_asprintf (&msg, "%s, '%s'", msg, fullname); + } + free (fullname); + } + } + if (msg) + { + CCTK_INFO (msg); + free (msg); + } + } + + /* save the last setting of 'out3D_vars' parameter */ + free (myGH->out3D_vars); + myGH->out3D_vars = strdup (out3D_vars); + } +} + + +/**************************** local functions ******************************/ +/* check if this variable can be output (static conditions) */ +static int CheckOutputVar (int vindex) +{ + int groupindex; + cGroup groupinfo; + char *fullname; + const char *errormsg; + + + /* get the variable group information */ + groupindex = CCTK_GroupIndexFromVarI (vindex); + CCTK_GroupData (groupindex, &groupinfo); + + /* check if variable is grid array type with 3 dimensions */ + errormsg = NULL; + if (groupinfo.dim != 3) + { + errormsg = "dim != 3"; + } + else if (groupinfo.grouptype != CCTK_GF && groupinfo.grouptype != CCTK_ARRAY) + { + errormsg = "not a grid function or array"; + } + else if (strncmp (CCTK_VarTypeName (groupinfo.vartype), + "CCTK_VARIABLE_REAL", 18) || + CCTK_VarTypeSize (groupinfo.vartype) != sizeof (double)) + { + errormsg = "not a double-precision floating-point grid function or array"; + } + + if (errormsg) + { + fullname = CCTK_FullName (vindex); + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "No IOSDF 3D output for '%s': %s", fullname, errormsg); + free (fullname); + } + + return (errormsg != NULL); +} + + +/* callback for CCTK_TraverseString() to set the output flag + for the given variable */ +static void SetOutputFlag (int vindex, const char *optstring, void *arg) +{ + const ioSDFGH *myGH = arg; + + + if (CheckOutputVar (vindex) == 0) + { + myGH->out3D_every[vindex] = myGH->out3D_every_default; + + if (optstring) + { + IOUtil_ParseOutputFrequency ("3D IOSDF", "IOSDF::out3D_vars", + myGH->stop_on_parse_errors, + vindex, optstring, + &myGH->out3D_every[vindex]); + } + } +} diff --git a/src/Startup.c b/src/Startup.c new file mode 100644 index 0000000..fbb8b79 --- /dev/null +++ b/src/Startup.c @@ -0,0 +1,251 @@ + /*@@ + @file Startup.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Startup routines for IOSDF. + @enddesc + @version $Id$ + @@*/ + + +#include +#include + +#include "cctk.h" +#include "cctk_IOMethods.h" +#include "cctk_Parameters.h" +#include "CactusBase/IOUtil/src/ioutil_Utils.h" +#include "ioSDFGH.h" + +/* the rcs ID and its dummy function to use it */ +static const char *rcsid = "$Id$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Startup_c) + + +/******************************************************************** + ******************** Macro Definitions ************************ + ********************************************************************/ +#define CREATE_OUTDIR(dim, dir) \ + { \ + const char *_dir = dir; \ + \ + \ + /* check whether "dir" was set; if not default to "IO::out_dir" */ \ + if (*_dir == 0) \ + { \ + _dir = out_dir; \ + } \ + \ + /* omit the directory name if it's the current working dir */ \ + if (strcmp (_dir, ".") == 0) \ + { \ + myGH->dir = strdup (""); \ + } \ + else \ + { \ + myGH->dir = malloc (strlen (_dir) + 2); \ + sprintf (myGH->dir, "%s/", _dir); \ + } \ + \ + /* create the directory */ \ + i = IOUtil_CreateDirectory (GH, myGH->dir, 0, 0); \ + if (i < 0) \ + { \ + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, \ + "IOSDF_SetupGH: Problem creating directory '%s' " \ + "for %dD output", myGH->dir, dim); \ + } \ + else if (i >= 0 && CCTK_Equals (verbose, "full")) \ + { \ + CCTK_VInfo (CCTK_THORNSTRING, "%dD output to directory '%s'", \ + dim, myGH->dir); \ + } \ + } + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static void *IOSDF_SetupGH (tFleshConfig *config, int conv_level, cGH *GH); + + + /*@@ + @routine IOSDF_Startup + @date Sat 12 June 2004 + @author Thomas Radke + @desc + The startup registration routine for IOSDF. + Registers the GH extensions needed for IOSDF + along with its setup routine. + @enddesc + @calls CCTK_RegisterGHExtension + CCTK_RegisterGHExtensionSetupGH +@@*/ +void IOSDF_Startup (void) +{ + CCTK_RegisterGHExtensionSetupGH (CCTK_RegisterGHExtension ("IOSDF"), + IOSDF_SetupGH); +} + + + /*@@ + @routine IOSDF_Terminate + @date Sat 12 June 2004 + @author Thomas Radke + @desc + The termination routine for IOSDF. + Closes all open SDF output files. + @enddesc +@@*/ +void IOSDF_Terminate (void) +{ + gft_close_all (); +} + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ + /*@@ + @routine IOSDF_SetupGH + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Allocates and sets up IOSDF's GH extension structure + @enddesc + + @calls CCTK_RegisterIOMethod + CCTK_RegisterIOMethodOutputGH + CCTK_RegisterIOMethodOutputVarAs + CCTK_RegisterIOMethodTimeToOutput + CCTK_RegisterIOMethodTriggerOutput + + @var config + @vdesc the CCTK configuration as provided by the flesh + @vtype tFleshConfig * + @vio unused + @endvar + @var conv_level + @vdesc the convergence level + @vtype int + @vio unused + @endvar + @var GH + @vdesc Pointer to CCTK grid hierarchy + @vtype cGH * + @vio in + @endvar + + @returntype void * + @returndesc + pointer to the allocated GH extension structure + @endreturndesc +@@*/ +static void *IOSDF_SetupGH (tFleshConfig *config, int conv_level, cGH *GH) +{ + int i, maxdim, numvars; + ioSDFGH *myGH; + DECLARE_CCTK_PARAMETERS + + + /* suppress compiler warnings about unused variables */ + (void) (config + 0); + (void) (conv_level + 0); + (void) (GH + 0); + + /* allocate the GH extension and its components */ + myGH = malloc (sizeof (ioSDFGH)); + if (! myGH) + { + CCTK_WARN (0, "IOSDF_SetupGH: Unable to allocate memory for GH"); + } + + /* register the IOSDF routines as output methods */ + i = CCTK_RegisterIOMethod ("IOSDF_1D"); + CCTK_RegisterIOMethodOutputGH (i, IOSDF_Output1DGH); + CCTK_RegisterIOMethodOutputVarAs (i, IOSDF_Output1DVarAs); + CCTK_RegisterIOMethodTimeToOutput (i, IOSDF_TimeFor1D); + CCTK_RegisterIOMethodTriggerOutput (i, IOSDF_TriggerOutput1D); + + /* only register N-D IOSDF I/O methods + if at least N-dimensional grid variables are defined by thorns */ + maxdim = CCTK_MaxDim (); + if (maxdim >= 2) + { + i = CCTK_RegisterIOMethod ("IOSDF_2D"); + CCTK_RegisterIOMethodOutputGH (i, IOSDF_Output2DGH); + CCTK_RegisterIOMethodOutputVarAs (i, IOSDF_Output2DVarAs); + CCTK_RegisterIOMethodTimeToOutput (i, IOSDF_TimeFor2D); + CCTK_RegisterIOMethodTriggerOutput (i, IOSDF_TriggerOutput2D); + } + + if (maxdim >= 3) + { + i = CCTK_RegisterIOMethod ("IOSDF_3D"); + CCTK_RegisterIOMethodOutputGH (i, IOSDF_Output3DGH); + CCTK_RegisterIOMethodOutputVarAs (i, IOSDF_Output3DVarAs); + CCTK_RegisterIOMethodTimeToOutput (i, IOSDF_TimeFor3D); + CCTK_RegisterIOMethodTriggerOutput (i, IOSDF_TriggerOutput3D); + } + + numvars = CCTK_NumVars (); + myGH->out1D_every = malloc (numvars * sizeof (CCTK_INT)); + myGH->out2D_every = malloc (numvars * sizeof (CCTK_INT)); + myGH->out3D_every = malloc (numvars * sizeof (CCTK_INT)); + myGH->out1D_last = malloc (numvars * sizeof (int)); + myGH->out2D_last = malloc (numvars * sizeof (int)); + myGH->out3D_last = malloc (numvars * sizeof (int)); + + for (i = 0; i < numvars; i++) + { + myGH->out1D_last[i] = -1; + myGH->out2D_last[i] = -1; + myGH->out3D_last[i] = -1; + } + + myGH->out1D_vars = strdup (""); + myGH->out2D_vars = strdup (""); + myGH->out3D_vars = strdup (""); + myGH->out1D_every_default = out1D_every - 1; + myGH->out2D_every_default = out2D_every - 1; + myGH->out3D_every_default = out3D_every - 1; + + myGH->fileList_1D = NULL; + myGH->fileList_2D = NULL; + myGH->fileList_3D = NULL; + + myGH->stop_on_parse_errors = strict_io_parameter_check; + if (! CCTK_Equals (verbose, "none")) + { + CCTK_INFO ("I/O Method 'IOSDF_1D' registered: output of 1D lines of grid " + "functions/arrays to SDF files"); + } + IOSDF_CheckSteerableParameters1D (myGH); + if (maxdim >= 2) + { + if (! CCTK_Equals (verbose, "none")) + { + CCTK_INFO ("I/O Method 'IOSDF_2D' registered: output of 2D planes of " + "grid functions/arrays to SDF files"); + } + IOSDF_CheckSteerableParameters2D (myGH); + } + if (maxdim >= 3) + { + if (! CCTK_Equals (verbose, "none")) + { + CCTK_INFO ("I/O Method 'IOSDF_3D' registered: output of 3D grid " + "functions/arrays to SDF files"); + } + IOSDF_CheckSteerableParameters3D (myGH); + } + myGH->stop_on_parse_errors = 0; + + /* make sure all output directories exist */ + CREATE_OUTDIR (1, out1D_dir); + CREATE_OUTDIR (2, out2D_dir); + CREATE_OUTDIR (3, out3D_dir); + + return (myGH); +} diff --git a/src/Write1D.c b/src/Write1D.c new file mode 100644 index 0000000..debf166 --- /dev/null +++ b/src/Write1D.c @@ -0,0 +1,436 @@ +/*@@ + @file Write1D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Output one-dimensional lines in SDF file format. + @enddesc + @version $Id$ +@@*/ + +#include /* sqrt(3) */ +#include +#include + +#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_Write1D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static char *OpenFile (const cGH *GH, + const char *fullname, + const char *alias, + const cGroup *gdata, + int dir); + + +/*@@ + @routine IOSDF_Write1D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + This routine does 1D line output along the orthogonals + and the diagonal (in case of a cubed grid). +

+ It writes to SDF files suitable for gnuplot and xgraph. + A header telling the physical time prefixes the output data. + @enddesc + @calls Hyperslab_GlobalMappingByIndex + Hyperslab_FreeMapping + Hyperslab_GetList + OpenFile + WriteData + + @var GH + @vdesc Pointer to CCTK GH + @vtype const cGH * + @vio in + @endvar + @var vindex + @vdesc global index of variable to output + @vtype int + @vio in + @endvar + @var alias + @vdesc alias name (used for creating the output filename) + @vtype const char * + @vio in + @endvar + + @returntype int + @returndesc + 0 for success, or
+ -1 if variable has no storage assigned + @endreturndesc +@@*/ +int IOSDF_Write1D (const cGH *GH, int vindex, const char *alias) +{ + ioSDFGH *myGH; + int do_dir[4], coord_index[3]; + int i, dir, myproc, gindex, have_coords, mapping; + int num_requested_hslabs, num_returned_hslabs; + int *extent_int; + cGroup gdata; + char *fullname, *groupname, *filename; + CCTK_INT coord_system_handle, coord_handles[3]; + double offset; + CCTK_REAL coord_lower[3]; + CCTK_INT downsample[4]; + CCTK_INT *origin, *direction; + CCTK_INT hsize, extent; + CCTK_INT vindices[2]; + double *hdata[2]; + const double dtime = GH->cctk_time; + const char *coordnames[] = {"x", "y", "z", "d"}; + DECLARE_CCTK_PARAMETERS + + + /* get the variable's group index and its full name */ + gindex = CCTK_GroupIndexFromVarI (vindex); + fullname = CCTK_FullName (vindex); + + /* check if variable has storage assigned */ + if (! CCTK_QueryGroupStorageI (GH, gindex)) + { + CCTK_VWarn (2, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write1D: No IOSDF_1D output for '%s' (no storage)", + fullname); + free (fullname); + return (-1); + } + + /* get the handle for IOSDF extensions */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* get the variable's group information */ + CCTK_GroupData (gindex, &gdata); + + /* see what slices should be output */ + do_dir[0] = out1D_x && gdata.dim >= 1; + do_dir[1] = out1D_y && gdata.dim >= 2; + do_dir[2] = out1D_z && gdata.dim >= 3; + /* diagonal slice is done only if variable is non-staggered and 3D */ + do_dir[3] = out1D_d && gdata.dim == 3 && gdata.stagtype == 0; + if (out1D_d && ! do_dir[3] && myGH->out1D_last[vindex] < 0) + { + CCTK_VWarn (3, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write1D: No IOSDF_1D diagonal output for '%s' " + "(only implemented for non-staggered 3D variables)", + fullname); + } + + /* return if nothing to do */ + if (! (do_dir[0] || do_dir[1] || do_dir[2] || do_dir[3])) + { + free (fullname); + return (0); + } + + /* get the coordinate system associated with this grid variable */ + groupname = CCTK_GroupName (gindex); + coord_system_handle = Coord_GroupSystem (GH, groupname); + free (groupname); + + dir = gdata.dim < 3 ? gdata.dim : 3; + + have_coords = coord_system_handle >= 0 && + Util_TableGetIntArray (coord_system_handle, dir, + coord_handles, "COORDINATES") >= 0; + if (have_coords) + { + /* get the coordinate functions and coordinate physical minimum */ + for (i = 0; i < dir; i++) + { + coord_index[i] = -1; + coord_lower[i] = 0; + Util_TableGetInt (coord_handles[i], &coord_index[i], "GAINDEX"); + Util_TableGetReal (coord_handles[i], &coord_lower[i], "COMPMIN"); + have_coords &= coord_index[i] >= 0; + } + } + + myproc = CCTK_MyProc (GH); + + origin = calloc (2*gdata.dim, sizeof (CCTK_INT)); + direction = origin + gdata.dim; + extent_int = malloc ((gdata.dim + 1) * sizeof (int)); + + /* set downsampling vector from I/O parameters */ + downsample[0] = out_downsample_x; + downsample[1] = out_downsample_y; + downsample[2] = out_downsample_z; + downsample[3] = 1; + + /* get the variable's extents, compute the extent for 3D-diagonals as the + minimum of grid points in each direction */ + CCTK_GroupgshVI (GH, gdata.dim, extent_int, vindex); + if (gdata.dim == 3) + { + extent_int[3] = extent_int[0] < extent_int[1] ? + extent_int[0] : extent_int[1]; + if (extent_int[2] < extent_int[3]) + { + extent_int[3] = extent_int[2]; + } + } + /* get the total number of grid points to check for zero-sized variables */ + for (dir = 0, hsize = 1; dir < gdata.dim; dir++) + { + hsize *= extent_int[dir]; + } + + /* now do the actual I/O looping over all directions */ + for (dir = 0; dir < 4; dir++) + { + if (hsize <= 0) + { + continue; + } + + /* skip empty slices */ + if (! do_dir[dir]) + { + continue; + } + + /* processor 0 opens the files with the appropriate name */ + filename = NULL; + if (myproc == 0) + { + filename = OpenFile (GH, fullname, alias, &gdata, dir); + } + + /* get the number of hyperslabs to extract + (ie. whether to get a coordinate hyperslab too or not) */ + num_requested_hslabs = have_coords && dir < 3 ? 2 : 1; + + /* set the direction vector */ + for (i = 0; i < gdata.dim; i++) + { + direction[i] = (dir == i || dir == 3) ? 1 : 0; + } + + /* set the extent */ + extent = extent_int[dir]; + + /* set the origin of the line */ + if (gdata.grouptype == CCTK_GF && dir < 3) + { + for (i = 0; i < gdata.dim; i++) + { + origin[i] = myGH->spxyz[gdata.dim-1][dir][i]; + } + extent -= origin[dir]; + + /* correct extent in the case of staggered grids */ + if (CCTK_StaggerDirIndex(dir,gdata.stagtype)==1) + { + --extent; + } + } + else /* origin for CCTK_ARRAYS is always (0, 0, 0) */ + { + memset (origin, 0, gdata.dim * sizeof (CCTK_INT)); + } + + mapping = Hyperslab_GlobalMappingByIndex (GH, vindex, 1, + direction, origin, &extent, + &downsample[dir], + -1, /* table handle */ + NULL /* conversion fn */, + &hsize); + if (mapping < 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write1D: Failed to define hyperslab mapping for " + "variable '%s'", fullname); + continue; + } + if (hsize <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write1D: selected hyperslab has zero size for " + "variable '%s' direction %d", fullname, dir); + Hyperslab_FreeMapping (mapping); + continue; + } + + /* allocate hyperslab buffers on I/O processor */ + hdata[0] = hdata[1] = NULL; + if (myproc == 0) + { + hdata[0] = malloc (hsize * sizeof (double)); + hdata[1] = have_coords ? malloc (hsize * sizeof (double)) : NULL; + } + + /* get the hyperslabs */ + vindices[0] = vindex; + vindices[1] = coord_index[dir]; + num_returned_hslabs = Hyperslab_GetList (GH, mapping, num_requested_hslabs, + NULL, vindices, NULL, NULL, + (void **) hdata, NULL); + + /* release the mapping structure */ + Hyperslab_FreeMapping (mapping); + + /* And dump the data to file */ + if (num_returned_hslabs != num_requested_hslabs) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write1D: Failed to extract hyperslab for " + "variable '%s'", fullname); + } + else if (filename) + { + if (have_coords) + { + if (dir < 3) + { + /* get the staggering offset for the xyz coordinates */ + offset = 0.5 * GH->cctk_delta_space[dir] * + CCTK_StaggerDirIndex (dir, gdata.stagtype); + for (i = 0; i < hsize; i++) + { + hdata[1][i] += offset; + } + } + else + { + /* calculate the diagonal coordinates */ + offset = GH->cctk_delta_space[0] * sqrt (3); + for (i = 0; i < hsize; i++) + { + hdata[1][i] = coord_lower[0]*sqrt (3) + i*offset; + } + } + } + + extent_int[0] = hsize; + i = have_coords ? gft_out_full (filename, dtime, extent_int, + coordnames[dir], 1, hdata[1], hdata[0]): + gft_out_brief (filename, dtime, extent_int, + 1, hdata[0]); + if (i <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Error writing to 1D IOSDF output file '%s'", filename); + } + } + + /* clean up */ + free (hdata[0]); + free (hdata[1]); + } /* end of loop through all directions */ + + /* free allocated resources */ + free (origin); + free (fullname); + free (extent_int); + + return (0); +} + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +/*@@ + @routine OpenFile + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Opens a set of SDF files for a given alias name. + If this is the first time through, it will advertise them + to IOUtil. + @enddesc + @@*/ +static char *OpenFile (const cGH *GH, + const char *fullname, + const char *alias, + const cGroup *gdata, + int dir) +{ + ioSDFGH *myGH; + int upper, lower; + char *filename, *nameddata; + char slicename[40]; + ioAdvertisedFileDesc advertised_file; + DECLARE_CCTK_PARAMETERS + + + /* get handle for and IOSDF GH extensions */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + + nameddata = malloc (strlen (alias) + 3); + sprintf (nameddata, "%s_%d", alias, dir); + filename = GetNamedData (myGH->fileList_1D, nameddata); + if (filename) + { + free (nameddata); + return (filename); + } + + /* get the indices into spxyz[] */ + lower = (dir + 1) % 3; + upper = (dir + 2) % 3; + if (upper < lower) + { + upper = lower; + lower = 0; + } + + if (dir < 3) + { + if (gdata->dim == 1) + { + strcpy (slicename, "1D"); + } + else if (gdata->dim == 2) + { + /* give the slice origin as range [1 .. n] */ + sprintf (slicename, "%c_%d", 'x' + dir, + gdata->grouptype == CCTK_GF ? + myGH->spxyz[gdata->dim-1][dir][lower] : 0); + } + else + { + /* give the slice origin as range [1 .. n] */ + sprintf (slicename, "%c_%d_%d", 'x' + dir, + gdata->grouptype == CCTK_GF ? + myGH->spxyz[gdata->dim-1][dir][lower] : 0, + gdata->grouptype == CCTK_GF ? + myGH->spxyz[gdata->dim-1][dir][upper] : 0); + } + } + else + { + sprintf (slicename, "%dD_diagonal", gdata->dim); + } + + filename = malloc (strlen (myGH->out1D_dir) + strlen (alias) + + sizeof (slicename) + 6); + sprintf (filename, "%s%s_%s.sdf", myGH->out1D_dir, alias, slicename); + StoreNamedData (&myGH->fileList_1D, nameddata, filename); + free (nameddata); + + /* advertise the output file */ + advertised_file.slice = slicename; + advertised_file.thorn = CCTK_THORNSTRING; + advertised_file.varname = fullname; + advertised_file.description = "One-dimensional line plots"; + advertised_file.mimetype = "application/sdf"; + + IOUtil_AdvertiseFile (GH, filename, &advertised_file); + + return (filename); +} diff --git a/src/Write2D.c b/src/Write2D.c new file mode 100644 index 0000000..551e0c8 --- /dev/null +++ b/src/Write2D.c @@ -0,0 +1,371 @@ +/*@@ + @file Write2D.c + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Output two-dimensional slices in SDF file format. + @enddesc + @version $Id$ + @@*/ + + +#include +#include + +#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 = "$Id$"; +CCTK_FILEVERSION(CactusIO_IOSDF_Write2D_c) + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +static char **OpenFile (const cGH *GH, + const char *fullname, + const char *alias, + int dim, + int maxdir); + + +/*@@ + @routine IOSDF_Write2D + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Writes the 2D slices of a variable into separate SDF files. + @enddesc + @calls Hyperslab_GlobalMappingByIndex + Hyperslab_FreeMapping + Hyperslab_GetList + OpenFile + WriteData + + @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
+ -1 if variable has no storage assigned
+ -2 if output file couldn't be opened
+ -3 if hyperslab for coordinates and/or variable couldn't be + extracted + @endreturndesc +@@*/ +int IOSDF_Write2D (const cGH *GH, int vindex, const char *alias) +{ + ioSDFGH *myGH; + int i, total_hsize, num_requested_hslabs, num_returned_hslabs; + int dir, dir_i, dir_j, maxdir, myproc, gindex, have_coords; + int mapping; + cGroup gdata; + int coord_index[3]; + CCTK_INT coord_system_handle, coord_handles[3]; + char *fullname, *groupname; + int extent_int[3]; + double offset[2]; + CCTK_INT vindices[3], origin[3], extent[2], direction[6], downsample[2], + hsize[2]; + double *hdata[3]; + char **filenames; + const double dtime = GH->cctk_time; + const char *coordnames[] = {"x|y", "x|z", "y|z"}; + DECLARE_CCTK_PARAMETERS + + + /* get the variable name and 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 2D output for '%s' (no storage)", fullname); + free (fullname); + return (-1); + } + + /* get the handle for IOSDF extensions */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* get the number of slices to output */ + /* in general: maxdir = gdata.dim * (gdata.dim - 1) / 2; */ + maxdir = gdata.dim == 2 ? 1 : 3; + + /* get the coordinate system associated with this grid variable */ + groupname = CCTK_GroupName (gindex); + coord_system_handle = Coord_GroupSystem (GH, groupname); + free (groupname); + + dir = gdata.dim < 3 ? gdata.dim : 3; + + have_coords = coord_system_handle >= 0 && + Util_TableGetIntArray (coord_system_handle, dir, + coord_handles, "COORDINATES") >= 0; + if (have_coords) + { + /* get the coordinate functions and coordinate physical minimum */ + for (i = 0; i < dir; i++) + { + coord_index[i] = -1; + Util_TableGetInt (coord_handles[i], &coord_index[i], "GAINDEX"); + have_coords &= coord_index[i] >= 0; + } + } + num_requested_hslabs = have_coords ? 3 : 1; + + /* processor 0 opens the files on the first trip through */ + filenames = NULL; + myproc = CCTK_MyProc (GH); + if (myproc == 0) + { + filenames = OpenFile (GH, fullname, alias, gdata.dim, maxdir); + } + + /* get the extents of the variable */ + CCTK_GroupgshVI (GH, gdata.dim, extent_int, vindex); + + /* get the total number of grid points to check for zero-sized variables */ + for (dir = 0, hsize[0] = 1; dir < gdata.dim; dir++) + { + hsize[0] *= extent_int[dir]; + } + + /* now do the actual I/O looping over all directions */ + for (dir = 0; dir < maxdir; dir++) + { + if (hsize[0] <= 0) + { + continue; + } + + /* get the directions to span the hyperslab */ + if (dir == 0) + { + dir_i = 0; dir_j = 1; /* xy */ + downsample[0] = out_downsample_x; downsample[1] = out_downsample_y; + } + else if (dir == 1) + { + dir_i = 0; dir_j = 2; /* xz */ + downsample[0] = out_downsample_x; downsample[1] = out_downsample_z; + } + else + { + dir_i = 1; dir_j = 2; /* yz */ + downsample[0] = out_downsample_y; downsample[1] = out_downsample_z; + } + + /* set the extent vector */ + extent[0] = extent_int[dir_i]; + extent[1] = extent_int[dir_j]; + + /* set the origin using the slice center from IOUtil */ + memset (origin, 0, sizeof (origin)); + if (have_coords) + { + origin[maxdir-dir-1] = myGH->sp2xyz[gdata.dim-1][dir]; + } + + /* set the direction vector */ + memset (direction, 0, sizeof (direction)); + direction[dir_i] = direction[gdata.dim + dir_j] = 1; + + mapping = Hyperslab_GlobalMappingByIndex (GH, vindex, 2, + direction, origin, extent, + downsample, + -1, /* table handle */ + NULL /* conversion fn */, + hsize); + if (mapping < 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write2D: Failed to define hyperslab mapping for " + "variable '%s'", fullname); + continue; + } + total_hsize = hsize[0] * hsize[1]; + if (total_hsize <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write2D: selected hyperslab has zero size for " + "variable '%s' direction %d", fullname, dir); + Hyperslab_FreeMapping (mapping); + continue; + } + + hdata[0] = hdata[1] = hdata[2]; + if (myproc == 0) + { + /* allocate hyperslab buffers */ + hdata[0] = malloc (total_hsize * sizeof (double)); + hdata[1] = have_coords ? malloc (2 * total_hsize * sizeof(double)) : NULL; + hdata[2] = hdata[1] + total_hsize; + } + + /* get the hyperslabs */ + vindices[0] = vindex; + vindices[1] = coord_index[dir_i]; + vindices[2] = coord_index[dir_j]; + num_returned_hslabs = Hyperslab_GetList (GH, mapping, num_requested_hslabs, + NULL, vindices, NULL, NULL, + (void **) hdata, NULL); + + /* release the mapping structure */ + Hyperslab_FreeMapping (mapping); + + /* and dump the data to file */ + if (filenames) + { + if (num_returned_hslabs == num_requested_hslabs) + { + if (have_coords) + { + /* get the staggering offset for the coordinates */ + offset[0] = 0.5 * GH->cctk_delta_space[dir_i] * + CCTK_StaggerDirIndex (dir_i, gdata.stagtype); + offset[1] = 0.5 * GH->cctk_delta_space[dir_j] * + CCTK_StaggerDirIndex (dir_j, gdata.stagtype); + for (i = 0; i < total_hsize; i++) + { + hdata[1][i] += offset[0]; + hdata[2][i] += offset[1]; + } + } + + extent[0] = hsize[0]; + extent[1] = hsize[1]; + + i = have_coords ? gft_out_full (filenames[dir], dtime, extent_int, + coordnames[dir], 2, hdata[1], hdata[0]): + gft_out_brief (filenames[dir], dtime, extent_int, + 2, hdata[0]); + if (i <= 0) + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "Error writing to 2D IOSDF output file '%s'", + filenames[dir]); + } + } + else + { + CCTK_VWarn (1, __LINE__, __FILE__, CCTK_THORNSTRING, + "IOSDF_Write2D: Failed to extract hyperslab for " + "variable '%s'", fullname); + } + + /* clean up */ + free (hdata[0]); + free (hdata[1]); + + } /* end of outputting the data by processor 0 */ + + } /* end of looping through xyz directions */ + + free (fullname); + + return (0); +} + + +/******************************************************************** + ******************** Internal Routines ************************ + ********************************************************************/ +/*@@ + @routine OpenFile + @date Sat 12 June 2004 + @author Thomas Radke + @desc + Opens a set of SDF files for a given alias name. + If this is the first time through, it will advertise them + to IOUtil. + @enddesc + + @returntype char ** + @returndesc + the set of full filenames + @endreturndesc + @@*/ +static char **OpenFile (const cGH *GH, + const char *fullname, + const char *alias, + int dim, + int maxdir) +{ + int dir; + char **filenames; + ioSDFGH *myGH; + ioAdvertisedFileDesc advertised_file; + char slicename[30]; + const char *extensions[] = {"xy", "xz", "yz"}; + DECLARE_CCTK_PARAMETERS + + + /* get handle for IOSDF GH extensions */ + myGH = CCTK_GHExtension (GH, "IOSDF"); + + /* see if we are the first time through */ + filenames = GetNamedData (myGH->fileList_2D, alias); + if (filenames) + { + return (filenames); + } + + filenames = malloc (maxdir * sizeof (char **)); + + /* open/create files for each slice */ + for (dir = 0; dir < maxdir; dir++) + { + filenames[dir] = malloc (strlen (myGH->out2D_dir) + strlen (alias) + + sizeof (slicename) + 20); + + if (dim == 2) + { + strcpy (slicename, "2D"); + } + else + { + /* give the slice origin as range [1 .. n] */ + sprintf (slicename, "%s_%d", extensions[dir], + myGH->sp2xyz[dim-1][dir]); + } + + sprintf (filenames[dir], "%s%s_%s.sdf", myGH->out2D_dir, alias, slicename); + + /* advertise the file for downloading and write file info */ + advertised_file.slice = slicename; + advertised_file.thorn = CCTK_THORNSTRING; + advertised_file.varname = fullname; + advertised_file.description = "Two-dimensional slice plots"; + advertised_file.mimetype = "application/sdf"; + + IOUtil_AdvertiseFile (GH, filenames[dir], &advertised_file); + } + + /* store file desriptors in database */ + StoreNamedData (&myGH->fileList_2D, alias, filenames); + + return (filenames); +} 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 +#include + +#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
+ -1 if variable has no storage assigned
+ -2 if output file couldn't be opened
+ -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); +} diff --git a/src/ioSDFGH.h b/src/ioSDFGH.h new file mode 100644 index 0000000..e31867b --- /dev/null +++ b/src/ioSDFGH.h @@ -0,0 +1,87 @@ + /*@@ + @header ioSDFGH.h + @date Sat 12 June 2004 + @author Thomas Radke + @desc + The extensions to the GH structure from IOSDF. + @version $Header$ + @@*/ + +#ifndef _IOSDF_IOSDFGH_H_ +#define _IOSDF_IOSDFGH_H_ 1 + +#include "StoreNamedData.h" +#include "bbhutil.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct IOSDFGH +{ + /* default number of times to output */ + int out1D_every_default, out2D_every_default, out3D_every_default; + + /* number of times to output every variable */ + CCTK_INT *out1D_every, *out2D_every, *out3D_every; + + /* lists of variables to output */ + char *out1D_vars, *out2D_vars, *out3D_vars; + + /* directories in which to output */ + char *out1D_dir, *out2D_dir, *out3D_dir; + + /* the last iteration output for var [i] */ + int *out1D_last, *out2D_last, *out3D_last; + + /* database for names of output files that were already created */ + pNamedData *fileList_1D, *fileList_2D, *fileList_3D; + + /* for 1D lines, we define the index where to start the line: + spxyz[maxdim][XYZdirection][xyzstart_index] */ + int ***spxyz; + + /* for 2D planes, we define the index where to locate the plane + sp2xyz[maxdim][perpendicular direction] */ + int **sp2xyz; + + /* stop on I/O parameter parsing errors ? */ + int stop_on_parse_errors; + +} ioSDFGH; + + +/* prototypes of functions to be registered as I/O methods */ +int IOSDF_Output1DGH (const cGH *GH); +int IOSDF_TriggerOutput1D (const cGH *GH, int); +int IOSDF_TimeFor1D (const cGH *GH, int); +int IOSDF_Output1DVarAs (const cGH *GH, const char *var, const char *alias); +int IOSDF_Output2DGH (const cGH *GH); +int IOSDF_TriggerOutput2D (const cGH *GH, int); +int IOSDF_TimeFor2D (const cGH *GH, int); +int IOSDF_Output2DVarAs (const cGH *GH, const char *var, const char *alias); +int IOSDF_Output3DGH (const cGH *GH); +int IOSDF_TriggerOutput3D (const cGH *GH, int); +int IOSDF_TimeFor3D (const cGH *GH, int); +int IOSDF_Output3DVarAs (const cGH *GH, const char *var, const char *alias); + +/* other function prototypes */ +void IOSDF_Startup (void); + +int IOSDF_Write1D (const cGH *GH, int vindex, const char *alias); +int IOSDF_Write2D (const cGH *GH, int vindex, const char *alias); +int IOSDF_Write3D (const cGH *GH, int vindex, const char *alias); + +void IOSDF_Choose1D (const cGH *GH); +void IOSDF_Choose2D (const cGH *GH); + +void IOSDF_CheckSteerableParameters1D (ioSDFGH *myGH); +void IOSDF_CheckSteerableParameters2D (ioSDFGH *myGH); +void IOSDF_CheckSteerableParameters3D (ioSDFGH *myGH); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* _IOSDF_IOSDFGH_H_ */ diff --git a/src/make.code.defn b/src/make.code.defn new file mode 100644 index 0000000..8bf6eb1 --- /dev/null +++ b/src/make.code.defn @@ -0,0 +1,6 @@ +# Main make.code.defn file for thorn IOSDF +# $Header$ + +# Source files in this directory +SRCS = Startup.c ChooseOutput.c Output1D.c Write1D.c Output2D.c Write2D.c \ + Output3D.c Write3D.c -- cgit v1.2.3