ANFQ3BZCQVIJLNWXETGDK26W3QLGIXH6V5FHSB5DEXWJY35YTUKAC
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 <cactusmaint@cactuscode.org>
**************************************************************************
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.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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.
<signature of Ty Coon>, 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.
Cactus Code Thorn CartGrid3D
Author(s) : Gabrielle Allen
Gerd Lanfermann
Joan Masso
Maintainer(s): Cactus team
Licence : LGPL
--------------------------------------------------------------------------
1. Purpose
This thorn sets up a Cartesian grid, for a given domain. It also
provides a method for registering symmetries of Grid Functions
across the grid axes, and a call for applying symmetry boundary
conditions.
CartGrid3d also registers a coordinate system spher3d, under the old
API, but this is deprecated. Spherical coordinate systems will be
provided by another thorn in the future.
2. Additional information
This thorn currently only works in 3D, in that it creates 3D grid functions.
It registers Cartesian coordinate systems of 1, 2, and 3 dimensions.
# Configuration definitions for thorn CartGrid2D
# $Header$
# This will disappear once no-one calls anything from this thorn
PROVIDES CartGrid3D
{
SCRIPT
LANG
}
# This will disappear once the aliasing has a requires
REQUIRES CoordBase
\documentclass{article}
% Use the Cactus ThornGuide style file
% (Automatically used from Cactus distribution, if you have a
% thorn without the Cactus Flesh download this from the Cactus
% homepage at www.cactuscode.org)
\usepackage{../../../../doc/latex/cactus}
\begin{document}
\title{CartGrid3D}
\author{Gabrielle Allen \\ Gerd Lanfermann \\ Joan Masso \\ Jonathan Thornburg}
\date{$ $Date$ $}
\maketitle
% Do not delete next line
% START CACTUS THORNGUIDE
\begin{abstract}
{\tt CartGrid3D} allows you to set up coordinates on a 3D Cartesian
grid in a flexible manner. You can choose different grid domains
({\it eg} octant) to allow you to exploit any symmetry in your problem.
{\tt CartGrid3D} also provides routines for registering symmetries
of grid functions and applying symmetry conditions across the
coordinate axes.
\end{abstract}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Specifying the Grid Symmetry}
CartGrid3D allows you to specify the grid symmetry (or lack thereof) with the
\verb|grid::domain| parameter:
\begin{description}
\item[{\tt grid::domain = "full"}]\mbox{}\\
There are no symmetries.
\item[{\tt grid::domain = "bitant"}]\mbox{}\\
The grid includes only the $z \ge 0$ half-space
(plus symmetry zones); there is a reflection symmetry
across the $z=0$ plane.
\item[{\tt grid::domain = "quadrant"}]\mbox{}\\
The grid includes only the $\{x \ge 0, y \ge 0\}$ quadrant
(plus symmetry zones); there is a reflection symmetry
across both the $x=0$ plane and the $y=0$ plane.
\item[{\tt grid::domain = "octant"}]\mbox{}\\
The grid includes only the $\{x \ge 0, y \ge 0, z \ge 0\}$
octant (plus symmetry zones); there is a reflection symmetry
across each of the $x=0$ plane, the $y=0$ plane, and the $z=0$
plane.
\end{description}
Note that the implementation of symmetries in CartGrid3D is
deprecated, and the SymBase infrastructure should be used instead.
The above symmetries can be implemented using SymBase and the
ReflectionSymmetry thorn. Additionally, there are rotational
symmetries provided by the RotatingSymmetry180 and RotatingSymmetry90
thorns.
In each case except \verb|grid::domain = "full"|, symmetry zones are
introduced just on the ``other side'' of each symmetry grid boundary.
Each symmetry zone has a width (perpendicular to the boundary) of
\verb|driver::ghost_size| extra grid points. For centered 2nd~order
finite differencing, a width of \verb|driver::ghost_size = 1| should be
sufficient, but for (centered) 4th~order finite differencing, or for
upwinded 2nd~order, a width of \verb|driver::ghost_size = 2| is needed.
Making \verb|driver::ghost_size|
too large is fairly harmless (it just slightly reduces performance),
but making it too small will almost certainly result in horribly wrong
finite differencing near the symmetry boundaries, and may also result
in core dumps from out-of-range array accessing.
Note that the symmetry zones must be explicitly included in
\verb|driver::global_nx|, \verb|driver::global_ny|, and
\verb|driver::global_nz|, but should {\em not\/} be included in any
of the \verb|grid::type = "byrange"| parameters \verb|grid::xmin|,
\verb|grid::xmax|, \verb|grid::ymin|, \verb|grid::ymax|, \verb|grid::zmin|,
\verb|grid::zmax|, \verb|grid::xyzmin|, and/or \verb|grid::xyzmax|
described in the next section.
Note also that \verb|driver::global_nx|, \verb|driver::global_ny|,
and \verb|driver::global_nz| do {\em not\/} include any ghost zones
introduced for multiprocessor synchronization. (For more information
on ghost zones, see the section ``Ghost Size'' in the ``Cactus Variables''
chapter of the Cactus Users' Guide.)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Specifying the Grid Size, Range, and Spacing}
\verb|CartGrid3D| provides several different methods for setting
up the integer {\em grid size\/} ({\it eg} 128), floating-point
{\em grid spacing\/} ({\it eg} 0.1), and floating-point {\em grid range\/}
({\it eg} 12.8).%%%
\footnote{%%%
If you're AMR-ing, this all refers to the
coarsest or base grid.%%%
}%%%
{} You specify which method to use, with the \verb|grid::type| parameter:
\begin{description}
\item[{\tt grid::type = "byrange"}]\mbox{}\\
You specify the $x$, $y$, and $z$ grid ranges, either with
separate \verb|grid::xmin|, \verb|grid::xmax|, \verb|grid::ymin|,
\verb|grid::ymax|, \verb|grid::zmin|, and \verb|grid::zmax|
parameters, or with the \verb|grid::xyzmin| and
\verb|grid::xyzmax| parameters. The grid spacings are then
determined automagically from this information and the
\verb|driver::global_nx|, \verb|driver::global_ny|, and
\verb|driver::global_nz| grid-size parameters. You should
also choose the \verb|grid::domain| parameter consistent with
all these other parameters. (It's not clear whether or not
the code ever explicitly checks this.)
\item[{\tt grid::type = "box"}]\mbox{}\\
This is a special case of \verb|grid::type = "byrange"|
with the grid ranges hard-wired to
\verb|grid::xyzmin = -0.5| and \verb|grid::xyzmax = +0.5|.
\item[{\tt grid::type = "byspacing"}]\mbox{}\\
You specify the $x$, $y$, and $z$ grid spacings, either with
separate \verb|grid::dx|, \verb|grid::dy|, and \verb|grid::dz|
parameters, or with the \verb|grid::dxyz| parameter. You also
specify the grid symmetry with the \verb|grid::domain| parameter.
The $x$, $y$, and $z$ grid ranges are then determined automagically
from this information and the \verb|driver::global_nx|,
\verb|driver::global_ny|, and \verb|driver::global_nz|
grid-size parameters: Each coordinate's range is chosen
to be either symmetric about zero, or to extend from 0 up
to a maximum value.
\end{description}
There are also a number of optional parameters which can be used
to specify whether or not it's ok to have a grid point with an $x$,
$y$, and/or $z$ coordinate exactly equal to 0:
\begin{description}
\item[{\tt grid::no\_originx}, {\tt grid::no\_originy}, {\tt
grid::no\_originz}, {\tt grid::no\_origin}]\mbox{}\\
These parameters are all deprecated --- don't use them!
\item[{\tt grid::avoid\_originx}]\mbox{}\\
This is a Boolean parameter; if set to true
(\verb|grid::avoid_originx = "true"| or
\verb|grid::avoid_originx = "yes"| or
\verb|grid::avoid_originx = 1|) then the grid will be
``half-centered'' across $x=0$, {\it ie} there will be
grid points at
\dots,
$x = - \frac{3}{2} \Delta x$,
$x = - \frac{1}{2} \Delta x$,
$x = + \frac{1}{2} \Delta x$,
$x = + \frac{3}{2} \Delta x$,
\dots,
but not at $x=0$.
\item[{\tt grid::avoid\_originy}]\mbox{}\\
Same thing for $y$.
\item[{\tt grid::avoid\_originz}]\mbox{}\\
Same thing for $z$.
\item[{\tt grid::avoid\_origin}]\mbox{}\\
Same thing for all 3 axes $x$ and $y$ and $z$, {\it ie}
no grid point will have $x=0$ or $y=0$ or $z=0$.
\end{description}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{An Example}
Here is an example of setting up a grid using the {\tt PUGH} unigrid
driver. The relevant parts of the parameter file are as follows:
\begin{verbatim}
# PUGH
driver::ghost_size = 2
driver::global_nx = 61
driver::global_ny = 61
driver::global_nz = 33
# CartGrid3D
grid::avoid_origin = "no"
grid::domain = "bitant"
grid::type = "byrange"
grid::xmin = -3.0
grid::xmax = +3.0
grid::ymin = -3.0
grid::ymax = +3.0
grid::zmin = 0.0
grid::zmax = +3.0
\end{verbatim}
The resulting Cactus output (describing the grid) is as follows:
\begin{verbatim}
INFO (CartGrid3D): Grid Spacings:
INFO (CartGrid3D): dx=>1.0000000e-01 dy=>1.0000000e-01 dz=>1.0000000e-01
INFO (CartGrid3D): Computational Coordinates:
INFO (CartGrid3D): x=>[-3.000, 3.000] y=>[-3.000, 3.000] z=>[-0.200, 3.000]
INFO (CartGrid3D): Indices of Physical Coordinates:
INFO (CartGrid3D): x=>[0,60] y=>[0,60] z=>[2,32]
INFO (PUGH): Single processor evolution
INFO (PUGH): 3-dimensional grid functions
INFO (PUGH): Size: 61 61 33
\end{verbatim}
Since there's no symmetry in the $x$ and $y$ directions, the grid
is set up just as specified, with floating-point coordinates running
from $-3.0$ to $3.0$ inclusive, and 61~grid points with integer grid
indices $[0,60]$ (C) or $[1,61]$ (Fortran).
However, in the $z$ direction there's a reflection symmetry across the
$z=0$ plane, so the specified range of the grid, $z \in [0.0,3.0]$,
is automagically widened to include the symmetry zone of
\verb|driver::ghost_size = 2| grid points. The grid thus actually
includes the range of floating-point coordinates $z \in [-0.2,3.0]$.
The original specification of 33~grid points is left alone, however,
so the grid points have integer array indices $[0,32]$ (C) or
$[1,33]$ (Fortran).
The ``physical'' ({\it ie} non-symmetry-zone) part of the grid is
precisely the originally-specified range, $z \in [0.0,3.0]$, and
has the integer array indices $[2,32]$ (C) or $[3,33]$ (Fortran).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Coordinates}
\verb|CartGrid3D| defines (registers) four coordinate systems:
\verb|cart3d|, \verb|cart2d|, \verb|cart1d|, and \verb|spher3d|.
The Cartesian coordinates supplied by this thorn are grid functions
with the standard names \verb|x|, \verb|y|, and \verb|z|. To use
these coordinates you need to inherit from \verb|grid|, {\it ie} you
need to have an
\begin{verbatim}
inherits: grid
\end{verbatim}
line in your \verb|interface.ccl| file.
In addition a grid function \verb|r| is provided, containing the
radial coordinate from the origin where
$$
r = \sqrt{x^2+y^2+z^2}
$$
\verb|CartGrid3D| registers the lower and upper range of each coordinate
with the flesh.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Symmetries for Grid Functions}
If your problem and initial data allow it, \verb|CartGrid3D|
allows you to enforce even or odd parity for any grid function%%%
{} at (across) each coordinate axis. For a function $\phi(x,y,z)$,
even parity symmetry on the $x$-axis means
$$
\phi(-x,y,z) = \phi(x,y,z)
$$
while odd parity symmetry means
$$
\phi(-x,y,z) = -\phi(x,y,z)
$$
Note that the symmetries will only be enforced if a symmetry domain
is chosen (that is, if \verb|grid::domain| is set to something other than
\verb|grid::domain = "full"|.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Registering Symmetry Behaviour}
Each grid function can register how it behaves under a coordinate
change using function calls in {\tt CartGrid3D}. These symmetry
properties can then be used by other thorns, for example
{\tt CactusBase/Boundary} uses them to enforce symmetry boundary
conditions across coordinate axes. Symmetries should obviously be
registered before they are used, but since they can be different
for different grids, they must be registered {\it after} the
{\tt CCTK\_STARTUP} timebin. The usual place to register symmetries
is in the {\tt CCTK\_BASEGRID} timebin.
For example, to register the symmetries of the {\it xy} component of the
metric tensor from C, you first need to get access to the include file
by putting the line
\begin{verbatim}
uses include: Symmetry.h
\end{verbatim}
in your \verb|interface.ccl| file. Then in your thorn you can write (C)
\begin{verbatim}
#include "Symmetry.h"
static int one=1;
int sym[3];
sym[0] = -one;
sym[1] = -one;
sym[2] = one;
SetCartSymVN(cctkGH, sym,"ADMBase::gxy");
\end{verbatim}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\subsection{Calling Symmetry Boundary Conditions}
\verb|CartGrid3D| provides the following two routines to apply symmetry
boundary conditions to a variable group:
\begin{verbatim}
CartSymGI(cGH *GH, int *gi)
CartSymGN(cGH *GH, const char *gn)
\end{verbatim}
and for a specific variable it provides:
\begin{verbatim}
CartSymVI(cGH *GH, int *vi)
CartSymVN(cGH *GH, const char *gn)
\end{verbatim}
A group or variable can
be specified by its index value or name (use the 'I' or 'N' version
respectively). The Fortran versions of these functions take an
additional first argument, which is an integer which will hold the
return value.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Do not delete next line
% END CACTUS THORNGUIDE
\end{document}
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_bbh.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Thu Jun 6 19:51:10 2002
%%For: dp@nbdell15 (Denis Pollney,,,)
%%BoundingBox: 0 0 203 204
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 204 moveto 0 0 lineto 203 0 lineto 203 204 lineto closepath clip newpath
-78.6 264.4 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/DrawEllipse {
/endangle exch def
/startangle exch def
/yrad exch def
/xrad exch def
/y exch def
/x exch def
/savematrix mtrx currentmatrix def
x y tr xrad yrad sc 0 0 1 startangle endangle arc
closepath
savematrix setmatrix
} def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0 slj 0 slc
0.06299 0.06299 sc
%
% Fig objects follow
%
% Polyline
7.500 slw
n 2700 1350 m 4050 1350 l 4050 4050 l 2700 4050 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Ellipse
n 3375 2250 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr
% Ellipse
n 2025 3375 64 64 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr
% Polyline
n 1350 1350 m 4050 1350 l 4050 4050 l 1350 4050 l
cp gs col0 s gr
% Polyline
gs clippath
2421 3767 m 2460 3721 l 2346 3623 l 2418 3724 l 2307 3668 l cp
eoclip
n 2115 3465 m
2430 3735 l gs col0 s gr gr
% arrowhead
n 2307 3668 m 2418 3724 l 2346 3623 l 2307 3668 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
2978 1857 m 2939 1903 l 3053 2001 l 2982 1901 l 3092 1956 l cp
eoclip
n 3285 2160 m
2970 1890 l gs col0 s gr gr
% arrowhead
n 3092 1956 m 2982 1901 l 3053 2001 l 3092 1956 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
4290 2730 m 4290 2670 l 4139 2670 l 4259 2700 l 4139 2730 l cp
eoclip
n 1260 2700 m
4275 2700 l gs col0 s gr gr
% arrowhead
n 4139 2730 m 4259 2700 l 4139 2670 l 4139 2730 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
2730 1110 m 2670 1110 l 2670 1261 l 2700 1141 l 2730 1261 l cp
eoclip
n 2700 4185 m
2700 1125 l gs col0 s gr gr
% arrowhead
n 2730 1261 m 2700 1141 l 2670 1261 l 2730 1261 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
2655 1080 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
4365 2745 m
gs 1 -1 sc (x) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
1 3 0 1 0 0 50 0 20 0.000 1 0.0000 3375 2250 64 64 3375 2250 3439 2250
1 3 0 1 0 0 50 0 20 0.000 1 0.0000 2025 3375 64 64 2025 3375 2089 3375
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
1350 1350 4050 1350 4050 4050 1350 4050 1350 1350
2 2 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
2700 1350 4050 1350 4050 4050 2700 4050 2700 1350
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2115 3465 2430 3735
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
3285 2160 2970 1890
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1260 2700 4275 2700
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2700 4185 2700 1125
4 0 0 50 0 16 12 0.0000 4 150 105 2655 1080 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 4365 2745 x\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_bitant.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sun Jun 9 11:06:24 2002
%%For: pollney@xeon20.aei-potsdam.mpg.de (Denis Pollney,0.21,1.21,none)
%%BoundingBox: 0 0 165 202
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 202 moveto 0 0 lineto 165 0 lineto 165 202 lineto closepath clip newpath
-56.7 261.5 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0.06299 0.06299 sc
%
% Fig objects follow
%
% Arc
7.500 slw
gs clippath
1765 3181 m 1774 3122 l 1624 3100 l 1739 3148 l 1615 3159 l cp
1774 2277 m 1765 2218 l 1615 2240 l 1739 2252 l 1624 2299 l cp
eoclip
n 1755.0 2700.0 450.0 -90.0 90.0 arcn
gs col0 s gr
gr
% arrowhead
n 1615 3159 m 1739 3148 l 1624 3100 l 1615 3159 l cp gs 0.00 setgray ef gr col0 s
% arrowhead
n 1624 2299 m 1739 2252 l 1615 2240 l 1624 2299 l cp gs 0.00 setgray ef gr col0 s
% Polyline
n 1800 1350 m 3150 1350 l 3150 4050 l 1800 4050 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
gs clippath
3390 2730 m 3390 2670 l 3239 2670 l 3359 2700 l 3239 2730 l cp
eoclip
n 1710 2700 m
3375 2700 l gs col0 s gr gr
% arrowhead
n 3239 2730 m 3359 2700 l 3239 2670 l 3239 2730 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
1830 1110 m 1770 1110 l 1770 1261 l 1800 1141 l 1830 1261 l cp
eoclip
n 1800 4140 m
1800 1125 l gs col0 s gr gr
% arrowhead
n 1830 1261 m 1800 1141 l 1770 1261 l 1830 1261 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
1755 1080 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
3420 2790 m
gs 1 -1 sc (x) col0 sh gr
/Symbol ff 180.00 scf sf
900 2745 m
gs 1 -1 sc (q=p) col0 sh gr
/Helvetica ff 180.00 scf sf
1575 2025 m
gs 1 -1 sc (A) col0 sh gr
/Helvetica ff 180.00 scf sf
1575 3600 m
gs 1 -1 sc (B) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
5 1 0 1 0 7 50 0 -1 0.000 0 1 1 1 1755.000 2700.000 1755 2250 1305 2700 1755 3150
1 1 1.00 60.00 120.00
1 1 1.00 60.00 120.00
2 2 0 1 0 6 50 0 20 0.000 0 0 -1 0 0 5
1800 1350 3150 1350 3150 4050 1800 4050 1800 1350
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1710 2700 3375 2700
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1800 4140 1800 1125
4 0 0 50 0 16 12 0.0000 4 150 105 1755 1080 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 3420 2790 x\001
4 0 0 50 0 32 12 0.0000 4 135 315 900 2745 q=p\001
4 0 0 50 0 16 12 0.0000 4 135 135 1575 2025 A\001
4 0 0 50 0 16 12 0.0000 4 135 120 1575 3600 B\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_bitant_example.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sat Jun 8 19:19:08 2002
%%For: dp@nbdell15 (Denis Pollney,,,)
%%BoundingBox: 0 0 302 269
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 269 moveto 0 0 lineto 302 0 lineto 302 269 lineto closepath clip newpath
-65.2 315.4 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/DrawEllipse {
/endangle exch def
/startangle exch def
/yrad exch def
/xrad exch def
/y exch def
/x exch def
/savematrix mtrx currentmatrix def
x y tr xrad yrad sc 0 0 1 startangle endangle arc
closepath
savematrix setmatrix
} def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0 slj 0 slc
0.06299 0.06299 sc
%
% Fig objects follow
%
% Polyline
7.500 slw
n 1800 2250 m 3375 2250 l 3375 4725 l 1800 4725 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
n 3375 1350 m 1800 2250 l 3375 2250 l 4950 1350 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
n 3375 2250 m 4950 1350 l 4950 3825 l 3375 4725 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Ellipse
n 2700 1350 315 135 0 360 DrawEllipse gs col0 s gr
% Polyline
gs clippath
1142 3806 m 1171 3858 l 1303 3783 l 1184 3817 l 1273 3731 l cp
eoclip
n 1800 3465 m
1170 3825 l gs col0 s gr gr
% arrowhead
n 1273 3731 m 1184 3817 l 1303 3783 l 1273 3731 l cp gs 0.00 setgray ef gr col0 s
% Polyline
[60] 0 sd
n 3375 1350 m
3375 3825 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 3375 3825 m
4950 3825 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 3375 3825 m
1800 4725 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 2700 1755 m
2700 4725 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 1805 3474 m
4145 2124 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 4140 2970 m
1575 2970 l gs col0 s gr [] 0 sd
% Polyline
gs clippath
5685 3000 m 5685 2940 l 5534 2940 l 5654 2970 l 5534 3000 l cp
eoclip
n 4140 2970 m
5670 2970 l gs col0 s gr gr
% arrowhead
n 5534 3000 m 5654 2970 l 5534 2940 l 5534 3000 l cp gs 0.00 setgray ef gr col0 s
% Polyline
n 2700 4725 m
2700 4995 l gs col0 s gr
% Polyline
[60] 0 sd
n 1800 2970 m
1575 2970 l gs col0 s gr [] 0 sd
% Polyline
gs clippath
2730 885 m 2670 885 l 2670 1036 l 2700 916 l 2730 1036 l cp
eoclip
n 2700 1710 m
2700 900 l gs col0 s gr gr
% arrowhead
n 2730 1036 m 2700 916 l 2670 1036 l 2730 1036 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
1035 3960 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
2655 855 m
gs 1 -1 sc (z) col0 sh gr
/Helvetica ff 180.00 scf sf
5715 3015 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
1710 1305 m
gs 1 -1 sc (rotation) col0 sh gr
/Helvetica ff 180.00 scf sf
1845 1485 m
gs 1 -1 sc (axis) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
1 1 0 1 0 7 50 0 -1 0.000 1 0.0000 2700 1350 315 135 2700 1350 3015 1350
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1800 3465 1170 3825
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
3375 1350 3375 3825
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
3375 3825 4950 3825
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
3375 3825 1800 4725
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
2700 1755 2700 4725
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
1805 3474 4145 2124
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
4140 2970 1575 2970
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4140 2970 5670 2970
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2700 4725 2700 4995
2 2 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
1800 2250 3375 2250 3375 4725 1800 4725 1800 2250
2 3 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
3375 1350 1800 2250 3375 2250 4950 1350 3375 1350
2 3 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
3375 2250 4950 1350 4950 3825 3375 4725 3375 2250
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
1800 2970 1575 2970
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2700 1710 2700 900
4 0 0 50 0 16 12 0.0000 4 105 90 1035 3960 x\001
4 0 0 50 0 16 12 0.0000 4 105 90 2655 855 z\001
4 0 0 50 0 16 12 0.0000 4 150 105 5715 3015 y\001
4 0 0 50 0 16 12 0.0000 4 135 615 1710 1305 rotation\001
4 0 0 50 0 16 12 0.0000 4 135 330 1845 1485 axis\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_general.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sun Jun 9 11:03:43 2002
%%For: pollney@xeon20.aei-potsdam.mpg.de (Denis Pollney,0.21,1.21,none)
%%BoundingBox: 0 0 154 158
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 158 moveto 0 0 lineto 154 0 lineto 154 158 lineto closepath clip newpath
-73.7 241.7 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/DrawEllipse {
/endangle exch def
/startangle exch def
/yrad exch def
/xrad exch def
/y exch def
/x exch def
/savematrix mtrx currentmatrix def
x y tr xrad yrad sc 0 0 1 startangle endangle arc
closepath
savematrix setmatrix
} def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0.06299 0.06299 sc
%
% Fig objects follow
%
% Arc
7.500 slw
gs clippath
2053 2808 m 2022 2756 l 1892 2833 l 2011 2798 l 1923 2885 l cp
2022 2193 m 2053 2141 l 1923 2064 l 2011 2152 l 1892 2116 l cp
eoclip
n 1761.0 2475.0 411.0 -50.0 50.0 arcn
gs col0 s gr
gr
% arrowhead
n 1923 2885 m 2011 2798 l 1892 2833 l 1923 2885 l cp gs 0.00 setgray ef gr col0 s
% arrowhead
n 1892 2116 m 2011 2152 l 1923 2064 l 1892 2116 l cp gs 0.00 setgray ef gr col0 s
% Ellipse
n 1800 2475 45 45 0 360 DrawEllipse gs 0.00 setgray ef gr gs col0 s gr
% Polyline
n 1800 2475 m 3600 1350 l 3600 3825 l
1800 2475 l cp gs col6 1.00 shd ef gr gs col0 s gr
/Symbol ff 180.00 scf sf
1170 2475 m
gs 1 -1 sc (q) col0 sh gr
/Helvetica ff 180.00 scf sf
2340 1980 m
gs 1 -1 sc (A) col0 sh gr
/Helvetica ff 180.00 scf sf
2340 3240 m
gs 1 -1 sc (B) col0 sh gr
/Helvetica ff 180.00 scf sf
2925 2610 m
gs 1 -1 sc (Grid) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
5 1 0 1 0 7 50 0 -1 0.000 0 1 1 1 1761.000 2475.000 2025 2160 1350 2475 2025 2790
1 1 1.00 60.00 120.00
1 1 1.00 60.00 120.00
1 3 0 1 0 0 50 0 20 0.000 1 0.0000 1800 2475 45 45 1800 2475 1845 2475
2 1 0 1 0 6 50 0 20 0.000 0 0 -1 0 0 4
1800 2475 3600 1350 3600 3825 1800 2475
4 0 0 50 0 32 12 0.0000 4 135 105 1170 2475 q\001
4 0 0 50 0 16 12 0.0000 4 135 135 2340 1980 A\001
4 0 0 50 0 16 12 0.0000 4 135 120 2340 3240 B\001
4 0 0 50 0 16 12 0.0000 4 135 345 2925 2610 Grid\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_grid.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sat Jun 8 18:10:26 2002
%%For: dp@nbdell15 (Denis Pollney,,,)
%%BoundingBox: 0 0 290 261
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 261 moveto 0 0 lineto 290 0 lineto 290 261 lineto closepath clip newpath
-59.5 346.6 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0 slj 0 slc
0.06299 0.06299 sc
%
% Fig objects follow
%
% Polyline
7.500 slw
n 1800 1800 m 5175 1800 l 5175 5400 l 1800 5400 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
n 2070 1800 m
2070 2565 l gs col0 s gr
% Polyline
n 2430 2070 m
1800 2070 l gs col0 s gr
% Polyline
n 2430 2295 m
1800 2295 l gs col0 s gr
% Polyline
n 1530 4635 m
1530 5400 l gs col0 s gr
% Polyline
n 1800 5400 m 1260 5400 l 1260 1800 l 1800 1800 l
cp gs col0 s gr
% Polyline
n 2430 2520 m
1800 2520 l gs col0 s gr
% Polyline
n 2340 1800 m
2340 2565 l gs col0 s gr
% Polyline
n 1260 5175 m
1800 5175 l gs col0 s gr
% Polyline
n 1260 4950 m
1800 4950 l gs col0 s gr
% Polyline
n 1260 4725 m
1800 4725 l gs col0 s gr
% Polyline
gs clippath
1830 1560 m 1770 1560 l 1770 1711 l 1800 1591 l 1830 1711 l cp
eoclip
n 1800 5490 m
1800 1575 l gs col0 s gr gr
% arrowhead
n 1830 1711 m 1800 1591 l 1770 1711 l 1830 1711 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
5415 3630 m 5415 3570 l 5264 3570 l 5384 3600 l 5264 3630 l cp
eoclip
n 1125 3600 m
5400 3600 l gs col0 s gr gr
% arrowhead
n 5264 3630 m 5384 3600 l 5264 3570 l 5264 3630 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
1845 2025 m
gs 1 -1 sc (00 01) col0 sh gr
/Helvetica ff 180.00 scf sf
1845 2250 m
gs 1 -1 sc (10 11) col0 sh gr
/Helvetica ff 180.00 scf sf
1845 2475 m
gs 1 -1 sc (20 21) col0 sh gr
/Helvetica ff 180.00 scf sf
1305 5130 m
gs 1 -1 sc (11 10) col0 sh gr
/Helvetica ff 180.00 scf sf
1305 5355 m
gs 1 -1 sc (01 00) col0 sh gr
/Helvetica ff 180.00 scf sf
1305 4905 m
gs 1 -1 sc (21 20) col0 sh gr
/Helvetica ff 180.00 scf sf
3105 2880 m
gs 1 -1 sc (physical grid) col0 sh gr
/Helvetica ff 180.00 scf sf
1575 4095 m
gs 1 -1 sc 90.0 rot (ghost zones) col0 sh gr
/Helvetica ff 180.00 scf sf
1800 1485 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
5445 3690 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
1935 1755 m
gs 1 -1 sc (0) col0 sh gr
/Helvetica ff 180.00 scf sf
2160 1755 m
gs 1 -1 sc (1) col0 sh gr
/Helvetica ff 180.00 scf sf
4995 1755 m
gs 1 -1 sc (n) col0 sh gr
/Helvetica ff 180.00 scf sf
945 1980 m
gs 1 -1 sc (0) col0 sh gr
/Helvetica ff 180.00 scf sf
945 2205 m
gs 1 -1 sc (1) col0 sh gr
/Helvetica ff 180.00 scf sf
945 5400 m
gs 1 -1 sc (m) col0 sh gr
/Times-Roman ff 180.00 scf sf
945 2430 m
gs 1 -1 sc (2) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
2 2 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
1800 1800 5175 1800 5175 5400 1800 5400 1800 1800
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2070 1800 2070 2565
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2430 2070 1800 2070
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2430 2295 1800 2295
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
1530 4635 1530 5400
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
1800 5400 1260 5400 1260 1800 1800 1800 1800 5400
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2430 2520 1800 2520
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
2340 1800 2340 2565
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
1260 5175 1800 5175
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
1260 4950 1800 4950
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 2
1260 4725 1800 4725
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1800 5490 1800 1575
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1125 3600 5400 3600
4 0 0 50 0 16 12 0.0000 4 135 480 1845 2025 00 01\001
4 0 0 50 0 16 12 0.0000 4 135 480 1845 2250 10 11\001
4 0 0 50 0 16 12 0.0000 4 135 480 1845 2475 20 21\001
4 0 0 50 0 16 12 0.0000 4 135 480 1305 5130 11 10\001
4 0 0 50 0 16 12 0.0000 4 135 480 1305 5355 01 00\001
4 0 0 50 0 16 12 0.0000 4 135 480 1305 4905 21 20\001
4 0 0 50 0 16 12 0.0000 4 180 1080 3105 2880 physical grid\001
4 0 0 50 0 16 12 1.5708 4 180 1005 1575 4095 ghost zones\001
4 0 0 50 0 16 12 0.0000 4 150 105 1800 1485 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 5445 3690 x\001
4 0 0 50 0 16 12 0.0000 4 135 105 1935 1755 0\001
4 0 0 50 0 16 12 0.0000 4 135 105 2160 1755 1\001
4 0 0 50 0 16 12 0.0000 4 105 105 4995 1755 n\001
4 0 0 50 0 16 12 0.0000 4 135 105 945 1980 0\001
4 0 0 50 0 16 12 0.0000 4 135 105 945 2205 1\001
4 0 0 50 0 16 12 0.0000 4 105 135 945 5400 m\001
4 0 0 50 0 0 12 0.0000 4 135 90 945 2430 2\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_octant.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sun Jun 9 11:05:54 2002
%%For: pollney@xeon20.aei-potsdam.mpg.de (Denis Pollney,0.21,1.21,none)
%%BoundingBox: 0 0 148 130
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 130 moveto 0 0 lineto 148 0 lineto 148 130 lineto closepath clip newpath
-31.2 218.0 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0.06299 0.06299 sc
%
% Fig objects follow
%
% Arc
7.500 slw
gs clippath
1833 3011 m 1777 2990 l 1724 3132 l 1794 3030 l 1780 3152 l cp
1327 2499 m 1311 2442 l 1165 2482 l 1289 2479 l 1181 2539 l cp
eoclip
n 1357.6 2923.7 451.8 -96.7 11.7 arcn
gs col0 s gr
gr
% arrowhead
n 1780 3152 m 1794 3030 l 1724 3132 l 1780 3152 l cp gs 0.00 setgray ef gr col0 s
% arrowhead
n 1181 2539 m 1289 2479 l 1165 2482 l 1181 2539 l cp gs 0.00 setgray ef gr col0 s
% Polyline
n 1350 1800 m 2475 1800 l 2475 2925 l 1350 2925 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
gs clippath
2715 2955 m 2715 2895 l 2564 2895 l 2684 2925 l 2564 2955 l cp
eoclip
n 1260 2925 m
2700 2925 l gs col0 s gr gr
% arrowhead
n 2564 2955 m 2684 2925 l 2564 2895 l 2564 2955 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
1380 1560 m 1320 1560 l 1320 1711 l 1350 1591 l 1380 1711 l cp
eoclip
n 1350 3015 m
1350 1575 l gs col0 s gr gr
% arrowhead
n 1380 1711 m 1350 1591 l 1320 1711 l 1380 1711 l cp gs 0.00 setgray ef gr col0 s
/Symbol ff 180.00 scf sf
495 3420 m
gs 1 -1 sc (q=3p/2) col0 sh gr
/Helvetica ff 180.00 scf sf
1305 1530 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
2745 3015 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
1125 2250 m
gs 1 -1 sc (A) col0 sh gr
/Helvetica ff 180.00 scf sf
1935 3150 m
gs 1 -1 sc (B) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
5 1 0 1 0 7 50 0 -1 0.000 0 1 1 1 1357.558 2923.697 1305 2475 1035 3240 1800 3015
1 1 1.00 60.00 120.00
1 1 1.00 60.00 120.00
2 2 0 1 0 6 50 0 20 0.000 0 0 -1 0 0 5
1350 1800 2475 1800 2475 2925 1350 2925 1350 1800
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1260 2925 2700 2925
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1350 3015 1350 1575
4 0 0 50 0 32 12 0.0000 4 135 540 495 3420 q=3p/2\001
4 0 0 50 0 16 12 0.0000 4 150 105 1305 1530 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 2745 3015 x\001
4 0 0 50 0 16 12 0.0000 4 135 135 1125 2250 A\001
4 0 0 50 0 16 12 0.0000 4 135 120 1935 3150 B\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_quadrant_example.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sat Jun 8 19:04:20 2002
%%For: dp@nbdell15 (Denis Pollney,,,)
%%BoundingBox: 0 0 302 203
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 203 moveto 0 0 lineto 302 0 lineto 302 203 lineto closepath clip newpath
-65.2 249.4 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/DrawEllipse {
/endangle exch def
/startangle exch def
/yrad exch def
/xrad exch def
/y exch def
/x exch def
/savematrix mtrx currentmatrix def
x y tr xrad yrad sc 0 0 1 startangle endangle arc
closepath
savematrix setmatrix
} def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0 slj 0 slc
0.06299 0.06299 sc
%
% Fig objects follow
%
% Polyline
7.500 slw
n 3375 1350 m 1800 2250 l 3375 2250 l 4950 1350 l 3375 1350 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
n 1800 2250 m 3375 2250 l 3375 3465 l 1800 3465 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Polyline
n 3375 2250 m 3375 3465 l 4950 2520 l 4950 1350 l 3375 2250 l
cp gs col6 1.00 shd ef gr gs col0 s gr
% Ellipse
n 2700 1350 315 135 0 360 DrawEllipse gs col0 s gr
% Polyline
gs clippath
1142 3806 m 1171 3858 l 1303 3783 l 1184 3817 l 1273 3731 l cp
eoclip
n 1800 3465 m
1170 3825 l gs col0 s gr gr
% arrowhead
n 1273 3731 m 1184 3817 l 1303 3783 l 1273 3731 l cp gs 0.00 setgray ef gr col0 s
% Polyline
[60] 0 sd
n 1805 3474 m
4145 2124 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 4140 2970 m
1575 2970 l gs col0 s gr [] 0 sd
% Polyline
gs clippath
5685 3000 m 5685 2940 l 5534 2940 l 5654 2970 l 5534 3000 l cp
eoclip
n 4140 2970 m
5670 2970 l gs col0 s gr gr
% arrowhead
n 5534 3000 m 5654 2970 l 5534 2940 l 5534 3000 l cp gs 0.00 setgray ef gr col0 s
% Polyline
[60] 0 sd
n 1800 2970 m
1575 2970 l gs col0 s gr [] 0 sd
% Polyline
gs clippath
2730 885 m 2670 885 l 2670 1036 l 2700 916 l 2730 1036 l cp
eoclip
n 2700 1710 m
2700 900 l gs col0 s gr gr
% arrowhead
n 2730 1036 m 2700 916 l 2670 1036 l 2730 1036 l cp gs 0.00 setgray ef gr col0 s
% Polyline
[60] 0 sd
n 3375 1350 m
3375 2250 l gs col0 s gr [] 0 sd
% Polyline
[60] 0 sd
n 2700 1755 m
2700 3465 l gs col0 s gr [] 0 sd
% Polyline
n 2700 3465 m
2700 3825 l gs col0 s gr
% Polyline
gs clippath
3075 3660 m 3135 3660 l 3135 3509 l 3105 3629 l 3075 3509 l cp
3135 3225 m 3075 3225 l 3075 3376 l 3105 3256 l 3135 3376 l cp
eoclip
n 3105 3240 m
3105 3645 l gs col0 s gr gr
% arrowhead
n 3135 3376 m 3105 3256 l 3075 3376 l 3135 3376 l cp gs 0.00 setgray ef gr col0 s
% arrowhead
n 3075 3509 m 3105 3629 l 3135 3509 l 3075 3509 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
1035 3960 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
2655 855 m
gs 1 -1 sc (z) col0 sh gr
/Helvetica ff 180.00 scf sf
5715 3015 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
3240 3690 m
gs 1 -1 sc (reflection plane) col0 sh gr
/Helvetica ff 180.00 scf sf
1755 1395 m
gs 1 -1 sc (rotation) col0 sh gr
/Helvetica ff 180.00 scf sf
1890 1575 m
gs 1 -1 sc (axis) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
1 1 0 1 0 7 50 0 -1 0.000 1 0.0000 2700 1350 315 135 2700 1350 3015 1350
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1800 3465 1170 3825
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
1805 3474 4145 2124
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
4140 2970 1575 2970
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4140 2970 5670 2970
2 3 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 6
3375 1350 1800 2250 3375 2250 4950 1350 3375 1350 3375 1350
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
1800 2970 1575 2970
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2700 1710 2700 900
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
3375 1350 3375 2250
2 2 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 5
1800 2250 3375 2250 3375 3465 1800 3465 1800 2250
2 3 0 1 0 6 60 0 20 0.000 0 0 -1 0 0 6
3375 2250 3375 3465 4950 2520 4950 1350 3375 2250 3375 2250
2 1 1 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
2700 1755 2700 3465
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2
2700 3465 2700 3825
2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 1 2
1 1 1.00 60.00 120.00
1 1 1.00 60.00 120.00
3105 3240 3105 3645
4 0 0 50 0 16 12 0.0000 4 105 90 1035 3960 x\001
4 0 0 50 0 16 12 0.0000 4 105 90 2655 855 z\001
4 0 0 50 0 16 12 0.0000 4 150 105 5715 3015 y\001
4 0 0 50 0 16 12 0.0000 4 180 1290 3240 3690 reflection plane\001
4 0 0 50 0 16 12 0.0000 4 135 615 1755 1395 rotation\001
4 0 0 50 0 16 12 0.0000 4 135 330 1890 1575 axis\001
%!PS-Adobe-2.0 EPSF-2.0
%%Title: rotate_reflect.eps
%%Creator: fig2dev Version 3.2 Patchlevel 3d
%%CreationDate: Sat Jun 8 18:20:30 2002
%%For: dp@nbdell15 (Denis Pollney,,,)
%%BoundingBox: 0 0 524 277
%%Magnification: 1.0000
%%EndComments
/$F2psDict 200 dict def
$F2psDict begin
$F2psDict /mtrx matrix put
/col-1 {0 setgray} bind def
/col0 {0.000 0.000 0.000 srgb} bind def
/col1 {0.000 0.000 1.000 srgb} bind def
/col2 {0.000 1.000 0.000 srgb} bind def
/col3 {0.000 1.000 1.000 srgb} bind def
/col4 {1.000 0.000 0.000 srgb} bind def
/col5 {1.000 0.000 1.000 srgb} bind def
/col6 {1.000 1.000 0.000 srgb} bind def
/col7 {1.000 1.000 1.000 srgb} bind def
/col8 {0.000 0.000 0.560 srgb} bind def
/col9 {0.000 0.000 0.690 srgb} bind def
/col10 {0.000 0.000 0.820 srgb} bind def
/col11 {0.530 0.810 1.000 srgb} bind def
/col12 {0.000 0.560 0.000 srgb} bind def
/col13 {0.000 0.690 0.000 srgb} bind def
/col14 {0.000 0.820 0.000 srgb} bind def
/col15 {0.000 0.560 0.560 srgb} bind def
/col16 {0.000 0.690 0.690 srgb} bind def
/col17 {0.000 0.820 0.820 srgb} bind def
/col18 {0.560 0.000 0.000 srgb} bind def
/col19 {0.690 0.000 0.000 srgb} bind def
/col20 {0.820 0.000 0.000 srgb} bind def
/col21 {0.560 0.000 0.560 srgb} bind def
/col22 {0.690 0.000 0.690 srgb} bind def
/col23 {0.820 0.000 0.820 srgb} bind def
/col24 {0.500 0.190 0.000 srgb} bind def
/col25 {0.630 0.250 0.000 srgb} bind def
/col26 {0.750 0.380 0.000 srgb} bind def
/col27 {1.000 0.500 0.500 srgb} bind def
/col28 {1.000 0.630 0.630 srgb} bind def
/col29 {1.000 0.750 0.750 srgb} bind def
/col30 {1.000 0.880 0.880 srgb} bind def
/col31 {1.000 0.840 0.000 srgb} bind def
end
save
newpath 0 277 moveto 0 0 lineto 524 0 lineto 524 277 lineto closepath clip newpath
-10.6 340.9 translate
1 -1 scale
/cp {closepath} bind def
/ef {eofill} bind def
/gr {grestore} bind def
/gs {gsave} bind def
/sa {save} bind def
/rs {restore} bind def
/l {lineto} bind def
/m {moveto} bind def
/rm {rmoveto} bind def
/n {newpath} bind def
/s {stroke} bind def
/sh {show} bind def
/slc {setlinecap} bind def
/slj {setlinejoin} bind def
/slw {setlinewidth} bind def
/srgb {setrgbcolor} bind def
/rot {rotate} bind def
/sc {scale} bind def
/sd {setdash} bind def
/ff {findfont} bind def
/sf {setfont} bind def
/scf {scalefont} bind def
/sw {stringwidth} bind def
/tr {translate} bind def
/tnt {dup dup currentrgbcolor
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add
4 -2 roll dup 1 exch sub 3 -1 roll mul add srgb}
bind def
/shd {dup dup currentrgbcolor 4 -2 roll mul 4 -2 roll mul
4 -2 roll mul srgb} bind def
/$F2psBegin {$F2psDict begin /$F2psEnteredState save def} def
/$F2psEnd {$F2psEnteredState restore end} def
$F2psBegin
10 setmiterlimit
0 slj 0 slc
0.06299 0.06299 sc
%
% Fig objects follow
%
% Polyline
435.000 slw
gs clippath
3300 2580 m 3300 1830 l 3161 1830 l 3281 2205 l 3161 2580 l cp
eoclip
n 2385 2205 m
3285 2205 l gs col6 s gr gr
% arrowhead
7.500 slw
n 3161 2580 m 3281 2205 l 3161 1830 l 3161 2580 l cp gs col6 1.00 shd ef gr col6 s
% Polyline
435.000 slw
gs clippath
6225 2580 m 6225 1830 l 6086 1830 l 6206 2205 l 6086 2580 l cp
eoclip
n 5310 2205 m
6210 2205 l gs col6 s gr gr
% arrowhead
7.500 slw
n 6086 2580 m 6206 2205 l 6086 1830 l 6086 2580 l cp gs col6 1.00 shd ef gr col6 s
% Polyline
435.000 slw
gs clippath
4965 4830 m 4965 4080 l 4826 4080 l 4946 4455 l 4826 4830 l cp
eoclip
n 3800 4455 m
4950 4455 l gs col7 1.00 shd ef gr gs col6 s gr gr
% arrowhead
7.500 slw
n 4826 4830 m 4946 4455 l 4826 4080 l 4826 4830 l cp gs col6 1.00 shd ef gr col6 s
% Polyline
gs clippath
1815 2280 m 1815 2220 l 1664 2220 l 1784 2250 l 1664 2280 l cp
eoclip
n 1125 2250 m
1800 2250 l gs col0 s gr gr
% arrowhead
n 1664 2280 m 1784 2250 l 1664 2220 l 1664 2280 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
643 2689 m 685 2731 l 792 2625 l 686 2689 l 749 2582 l cp
eoclip
n 1125 2250 m
675 2700 l gs col0 s gr gr
% arrowhead
n 749 2582 m 686 2689 l 792 2625 l 749 2582 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
1155 1560 m 1095 1560 l 1095 1711 l 1125 1591 l 1155 1711 l cp
eoclip
n 1125 2250 m
1125 1575 l gs col0 s gr gr
% arrowhead
n 1155 1711 m 1125 1591 l 1095 1711 l 1155 1711 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
630 2835 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
1845 2340 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
1080 1530 m
gs 1 -1 sc (z) col0 sh gr
% Polyline
gs clippath
7365 1560 m 7305 1560 l 7305 1711 l 7335 1591 l 7365 1711 l cp
eoclip
n 7335 2250 m
7335 1575 l gs col0 s gr gr
% arrowhead
n 7365 1711 m 7335 1591 l 7305 1711 l 7365 1711 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
6645 2220 m 6645 2280 l 6796 2280 l 6676 2250 l 6796 2220 l cp
eoclip
n 7335 2250 m
6660 2250 l gs col0 s gr gr
% arrowhead
n 6796 2220 m 6676 2250 l 6796 2280 l 6796 2220 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
7816 1810 m 7774 1768 l 7667 1874 l 7774 1811 l 7710 1917 l cp
eoclip
n 7335 2250 m
7785 1800 l gs col0 s gr gr
% arrowhead
n 7710 1917 m 7774 1811 l 7667 1874 l 7710 1917 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
7290 1530 m
gs 1 -1 sc (z) col0 sh gr
/Helvetica ff 180.00 scf sf
6525 2295 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
7785 1800 m
gs 1 -1 sc (x) col0 sh gr
% Polyline
gs clippath
4620 1560 m 4560 1560 l 4560 1711 l 4590 1591 l 4620 1711 l cp
eoclip
n 4590 2250 m
4590 1575 l gs col0 s gr gr
% arrowhead
n 4620 1711 m 4590 1591 l 4560 1711 l 4620 1711 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
4108 2689 m 4150 2731 l 4257 2625 l 4151 2689 l 4214 2582 l cp
eoclip
n 4590 2250 m
4140 2700 l gs col0 s gr gr
% arrowhead
n 4214 2582 m 4151 2689 l 4257 2625 l 4214 2582 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
3855 2220 m 3855 2280 l 4006 2280 l 3886 2250 l 4006 2220 l cp
eoclip
n 4545 2250 m
3870 2250 l gs col0 s gr gr
% arrowhead
n 4006 2220 m 3886 2250 l 4006 2280 l 4006 2220 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
3900 2220 m 3900 2280 l 4051 2280 l 3931 2250 l 4051 2220 l cp
eoclip
n 4590 2250 m
3915 2250 l gs col0 s gr gr
% arrowhead
n 4051 2220 m 3931 2250 l 4051 2280 l 4051 2220 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
4050 2835 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
3780 2295 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
4545 1530 m
gs 1 -1 sc (z) col0 sh gr
% Polyline
gs clippath
6240 3810 m 6180 3810 l 6180 3961 l 6210 3841 l 6240 3961 l cp
eoclip
n 6210 4500 m
6210 3825 l gs col0 s gr gr
% arrowhead
n 6240 3961 m 6210 3841 l 6180 3961 l 6240 3961 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
5520 4470 m 5520 4530 l 5671 4530 l 5551 4500 l 5671 4470 l cp
eoclip
n 6210 4500 m
5535 4500 l gs col0 s gr gr
% arrowhead
n 5671 4470 m 5551 4500 l 5671 4530 l 5671 4470 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
6691 4060 m 6649 4018 l 6542 4124 l 6649 4061 l 6585 4167 l cp
eoclip
n 6210 4500 m
6660 4050 l gs col0 s gr gr
% arrowhead
n 6585 4167 m 6649 4061 l 6542 4124 l 6585 4167 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
6165 3780 m
gs 1 -1 sc (z) col0 sh gr
/Helvetica ff 180.00 scf sf
5400 4545 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
6660 4050 m
gs 1 -1 sc (x) col0 sh gr
% Polyline
gs clippath
3255 4530 m 3255 4470 l 3104 4470 l 3224 4500 l 3104 4530 l cp
eoclip
n 2565 4500 m
3240 4500 l gs col0 s gr gr
% arrowhead
n 3104 4530 m 3224 4500 l 3104 4470 l 3104 4530 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
2083 4939 m 2125 4981 l 2232 4875 l 2126 4939 l 2189 4832 l cp
eoclip
n 2565 4500 m
2115 4950 l gs col0 s gr gr
% arrowhead
n 2189 4832 m 2126 4939 l 2232 4875 l 2189 4832 l cp gs 0.00 setgray ef gr col0 s
% Polyline
gs clippath
2595 3810 m 2535 3810 l 2535 3961 l 2565 3841 l 2595 3961 l cp
eoclip
n 2565 4500 m
2565 3825 l gs col0 s gr gr
% arrowhead
n 2595 3961 m 2565 3841 l 2535 3961 l 2595 3961 l cp gs 0.00 setgray ef gr col0 s
/Helvetica ff 180.00 scf sf
2070 5085 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
3285 4590 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
2520 3780 m
gs 1 -1 sc (z) col0 sh gr
% Polyline
n 180 1035 m 8460 1035 l 8460 3150 l 180 3150 l
cp gs col0 s gr
% Polyline
n 180 3285 m 8460 3285 l 8460 5400 l 180 5400 l
cp gs col0 s gr
/Helvetica ff 180.00 scf sf
2745 2340 m
gs 1 -1 sc (y) col0 sh gr
/Helvetica ff 180.00 scf sf
2565 2160 m
gs 1 -1 sc (reflect) col0 sh gr
/Helvetica ff 180.00 scf sf
3825 4410 m
gs 1 -1 sc (rotate about) col0 sh gr
/Helvetica ff 180.00 scf sf
5490 2205 m
gs 1 -1 sc (reflect) col0 sh gr
/Helvetica ff 180.00 scf sf
5670 2385 m
gs 1 -1 sc (x) col0 sh gr
/Helvetica ff 180.00 scf sf
4230 4590 m
gs 1 -1 sc (z) col0 sh gr
$F2psEnd
rs
#FIG 3.2
Landscape
Center
Metric
A4
100.00
Single
-2
1200 2
6 630 1395 1980 2835
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1125 2250 1800 2250
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1125 2250 675 2700
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
1125 2250 1125 1575
4 0 0 50 0 16 12 0.0000 4 105 90 630 2835 x\001
4 0 0 50 0 16 12 0.0000 4 150 105 1845 2340 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 1080 1530 z\001
-6
6 6525 1395 7875 2340
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
7335 2250 7335 1575
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
7335 2250 6660 2250
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
7335 2250 7785 1800
4 0 0 50 0 16 12 0.0000 4 105 90 7290 1530 z\001
4 0 0 50 0 16 12 0.0000 4 150 105 6525 2295 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 7785 1800 x\001
-6
6 3780 1395 4635 2835
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4590 2250 4590 1575
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4590 2250 4140 2700
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4545 2250 3870 2250
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
4590 2250 3915 2250
4 0 0 50 0 16 12 0.0000 4 105 90 4050 2835 x\001
4 0 0 50 0 16 12 0.0000 4 150 105 3780 2295 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 4545 1530 z\001
-6
6 5400 3645 6750 4590
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6210 4500 6210 3825
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6210 4500 5535 4500
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
6210 4500 6660 4050
4 0 0 50 0 16 12 0.0000 4 105 90 6165 3780 z\001
4 0 0 50 0 16 12 0.0000 4 150 105 5400 4545 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 6660 4050 x\001
-6
6 2070 3645 3420 5085
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2565 4500 3240 4500
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2565 4500 2115 4950
2 1 0 1 0 7 50 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 60.00 120.00
2565 4500 2565 3825
4 0 0 50 0 16 12 0.0000 4 105 90 2070 5085 x\001
4 0 0 50 0 16 12 0.0000 4 150 105 3285 4590 y\001
4 0 0 50 0 16 12 0.0000 4 105 90 2520 3780 z\001
-6
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
180 1035 8460 1035 8460 3150 180 3150 180 1035
2 2 0 1 0 7 50 0 -1 0.000 0 0 -1 0 0 5
180 3285 8460 3285 8460 5400 180 5400 180 3285
2 1 0 30 6 7 60 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 750.00 120.00
2385 2205 3285 2205
2 1 0 30 6 7 60 0 -1 0.000 0 0 -1 1 0 2
1 1 1.00 750.00 120.00
5310 2205 6210 2205
2 1 0 30 6 7 60 0 20 0.000 0 0 -1 1 0 2
1 1 1.00 750.00 120.00
3800 4455 4950 4455
4 0 0 50 0 16 12 0.0000 4 150 105 2745 2340 y\001
4 0 0 50 0 16 12 0.0000 4 135 510 2565 2160 reflect\001
4 0 0 50 0 16 12 0.0000 4 135 990 3825 4410 rotate about\001
4 0 0 50 0 16 12 0.0000 4 135 510 5490 2205 reflect\001
4 0 0 50 0 16 12 0.0000 4 105 90 5670 2385 x\001
4 0 0 50 0 16 12 0.0000 4 105 90 4230 4590 z\001
% /*@@
% @file rotating_sym.tex
% @date 6 June 2002
% @author Denis Pollney
% @desc
% Description of the implementation of `rotating'
% symmetry conditions in CartGrid3D.
% @enddesc
% @version $Header$
% @@*/
\documentclass{article}
\newif\ifpdf
\ifx\pdfoutput\undefined
\pdffalse % we are not running PDFLaTeX
\else
\pdfoutput=1 % we are running PDFLaTeX
\pdftrue
\fi
\ifpdf
\usepackage[pdftex]{graphicx}
\else
\usepackage{graphicx}
\fi
\parskip = 0 pt
\parindent = 0pt
\oddsidemargin = 0 cm
\textwidth = 16 cm
\topmargin = -1 cm
\textheight = 24 cm
\begin{document}
\title{Rotating symmetry conditions}
\author{Denis Pollney}
\date{June 2002}
\maketitle
\begin{abstract}
These notes describe the implentation of rotating symmetry conditions
for \emph{bitant} and \emph{quadrant} domains in \texttt{CartGrid3D}.
For these particular domain types, the condition that fields on the
grid have a rotational symmetry in a plane along one of the
coordinate axes can be simply implemented with minor extensions to the
already existing symmetry mechanism, which copies the components of
a given field to the required ghost-zones with a possible plus-minus
inversion.
\end{abstract}
%------------------------------------------------------------------------------
\section{Introduction}
\label{sec:rs_intro}
%------------------------------------------------------------------------------
A number of useful physical models involve situations where a
rotational symmetry is present in all of the relevant fields. By
`rotational symmetry' we mean that there exists a pair of half-planes
extending from one of the coordinate axes and separated by an angle
$\theta$ which have the property that on $A$ and near to $A$ can be
mapped onto $B$ and corresponding points near to $B$ (see Figure
\ref{fig:rs_rotation_examples}).
%
\begin{figure}
\centering
\begin{tabular}{ccc}
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_general.eps}
\fi
&
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_bitant.eps}
\fi
&
\ifpdf
\else
\includegraphics[height=25mm]{fig/rotate_octant.eps}
\fi
\\
(a) & (b) & (c)
\end{tabular}
\caption{Rotational symmetries, looking down the $z$-axis. In the
general case (a), the half-planes $A$ and $B$ are separated by an
angle $\theta$. Data at $A$ can be mapped on to points of $B$ via a
rotation through $\theta$. Particular cases of importance are the
rotation through $\theta=\pi$, so that data on the positive $y$-axis
is mapped onto the negative $y$, and vice versa; and the rotation
through $\theta=3\pi/2$ so that data need be specified only in a
single quarter-plane.}
\label{fig:rs_rotation_examples}
\end{figure}
%
In particular, situations for which such conditions can be useful
include
\begin{itemize}
\item rotating axisymmetric bodies -- satisfies the rotational
symmetry for arbitrary $\theta$.
\item pairs of massive bodies separated by distances $\pm
\mathbf{d}$ from the origin and with identical oppositely directed
momenta $\pm \mathbf{p}$ (Figure \ref{fig:rs_bbh}) -- satisfies
the half-plane rotational symmetry ($\theta=\pi$) or, if
$\mathbf{p}=0$ then also the quarter plane symmetry
($\theta=3\pi/2$).
\end{itemize}
\begin{figure}
\centering
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_bbh.eps}
\fi
\caption{A physical system consisting of a pair of identical bodies
separated equal distance along a line through the origin, and moving
with equal but opposite momenta, can be modelled using only the
positive half-plane if the rotating symmetry condition is applied to
the $x=0$ plane.}
\label{fig:rs_bbh}
\end{figure}
In order to apply the boundary condition exactly on a numerical grid,
it is necessary that grid points to each side of the mapping planes
$A$ and $B$ can be mapped onto each other exactly. In particular, this
means that the rotating symmetry conditions can be applied exactly if
the half-planes are each aligned with one of the coordinate axes. For
general planes $A$ and $B$, however, interpolation would be required
to put data in the neighbourhood of $A$ onto grid points near
$B$. Only the particular cases described by Figures
\ref{fig:rs_rotation_examples} (b) and (c) will be
considered here.
%------------------------------------------------------------------------------
\section{Symmetry conditions}
\label{sec:rs_application}
%------------------------------------------------------------------------------
For a given field, the boundary condition is applied as follows. For
each ghost-zone point along the symmetry plane, the corresponding
point on the physical grid (under the rotational $\theta$) is
determined. To determine the value of the ghost-zone point, the
value on the physical grid is simply transformed under the given
rotation.\\
The first of these issues is not difficult to resolve. As an example,
consider the half-plane rotational symmetry about the $z$-axis applied
in the $x=0$ plane, as depicted in Figure \ref{fig:rs_grid}. The
Figure has
$j=0\ldots m$ in the $y$ direction, an arbitrary number of points in the
$x$ and $z$ directions, and some ghostzones whose $j$ coordinates are
labelled $j=-1,-2,\ldots$. Then for the ghost-zone point $(n-i, -j,
k)$, the corresponding physical point under rotation is (1) $(i,j-1,k)$
if the $x=0$ plane is on the grid, or (2) $(i,j,k)$ if the $x=0$ plane
is staggered between a grid point and the first ghost-zone
point. There is an implicit assumption here that the grid extends
exactly the same distance to each side of the rotation axis. \\
\begin{figure}
\centering
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_grid.eps}
\fi
\caption{The mapping of physical points onto ghost-zone points for a
half-plane rotation about the $z$-axis, where the $x=0$ plane is
staggered between gridpoints, and two ghost zones have been
allocated.}
\label{fig:rs_grid}
\end{figure}
The remaining issue is to determine how the fields at a point
$(i,j,k)$ are modified under a rotation of a given angle. A set of
basis vectors $(\mathbf{\hat{x}},\mathbf{\hat{y}},\mathbf{\hat{z}})$
can be rotated to an arbitrary direction by applying the rotation
matrix
\begin{equation}
\mathbf{P} =
\left[
\begin{array}{ccc}
\eta_1(\cos\theta_1\cos\theta_3 - \sin\theta_1\cos\theta_2\sin\theta_3) &
\sin\theta_1\cos\theta_3 + \cos\theta_1\cos\theta_2\sin\theta_3 &
\sin\theta_2\sin\theta_3 \\
-(\cos\theta_1\sin\theta_3 + \sin\theta_1\cos\theta_2\cos\theta3) &
\eta_2(\sin\theta_1\sin\theta_3 + \cos\theta_1\cos\theta_2\cos\theta_3) &
\sin\theta_2\cos\theta_3 \\
\sin\theta_1\sin\theta_2 &
-\cos\theta_1\sin\theta_2 &
\eta_3\cos\theta_2
\end{array}
\right],
\end{equation}
which preserves the orthogonality of the basis. The matrix
$\mathbf{P}$ has been written in terms of the Euler angles
$0\leq\theta_1<2\pi$, $0\leq\theta_2<2\pi$, and $0\leq\theta_3<\pi$,
and the factors $\eta_1=\pm 1$, $\eta_2=\pm 1$, $\eta_3=\pm 1$ are
introduced to allow for reflections of individual axes (ie. changes of
handedness of the basis).
The basis is transformed under $\mathbf{P}$ via the matrix multiplication
\begin{equation}
\left[
\begin{array}{c}
\mathbf{\hat{x}^\prime} \\
\mathbf{\hat{y}^\prime} \\
\mathbf{\hat{z}^\prime}
\end{array}
\right]
=
\mathbf{P}
\left[
\begin{array}{c}
\mathbf{\hat{x}} \\
\mathbf{\hat{y}} \\
\mathbf{\hat{z}}
\end{array}
\right].
\end{equation}
Vectors and tensor components are transformed under the given rotation
by applying the $\mathbf{P}$ matrix:
\begin{eqnarray}
\mathbf{v} & \rightarrow & \mathbf{P}^T \mathbf{v}, \\
\mathbf{G} & \rightarrow & \mathbf{P}^T \mathbf{G} \mathbf{P},
\end{eqnarray}
where $\mathbf{v}$ is a 3-vector,
\begin{equation}
\mathbf{v} = [v_x, v_y, v_z]^T,
\end{equation}
and $\mathbf{G}$ is a two-index tensor treated as a matrix,
\begin{equation}
\mathbf{G} =
\left[
\begin{array}{ccc}
g_{xx} & g_{xy} & g_{xz} \\
g_{yx} & g_{yy} & g_{yz} \\
g_{zx} & g_{zy} & g_{zz}
\end{array}
\right].
\end{equation}
\emph{Example 1.} The special case of a reflection in the $x=0$ plane
corresponds to an inversion of the $x$-axis, so that
$\theta_1=\theta_2=\theta_3=0$ and $\eta_1=-1$,
\begin{equation}
\mathbf{P}_{x-\mathrm{reflect}} = \left[
\begin{array}{ccc}
-1 & 0 & 0 \\
0 & 1 & 0 \\
0 & 0 & 1
\end{array}
\right].
\end{equation}
\emph{Example 2.} For a rotation about the $z$ axis by an angle of
$\theta=\pi$ (corresponding to Figure \ref{fig:rs_grid}), the only
non-zero rotation angle is $\theta_1=\pi$, so that
\begin{equation}
\mathbf{P}_{z-\mathrm{rotate}} = \left[
\begin{array}{ccc}
-1 & 0 & 0 \\
0 & -1 & 0 \\
0 & 0 & 1
\end{array}
\right].
\end{equation}
\emph{Example 3.} A quarter-plane grid with positive $y$-axis values
mapped onto the positive $x$-axis (as in Figure\nobreak~
\ref{fig:rs_rotation_examples}) corresponds non-zero angle
$\theta_1=3\pi/2$, with the resulting rotation matrix
\begin{equation}
\mathbf{P}_{z-\mathrm{rotate(3/2)}} = \left[
\begin{array}{ccc}
0 & -1 & 0 \\
1 & 0 & 0 \\
0 & 0 & 1
\end{array}
\right].
\end{equation}
%------------------------------------------------------------------------------
\section{Implementation}
\label{sec:rs_implementation}
%------------------------------------------------------------------------------
In order to implement the bitant, quadrant and octant
\emph{reflection} symmetries which already exist in
\texttt{CartGrid3D}, it was necessary to attach to each grid function
information corresponding to how the field transforms under
reflections in each of the $x$, $y$, and $z$ axes. These are
specified as an array of three integers, each taking the value $+1$ or
$-1$, which is passed to the symmetry registration function. For
example,
\begin{verbatim}
static int one=1;
int sym[3];
sym[0] = -one;
sym[1] = -one;
sym[2] = one;
SetCartSymVN(cctkGH, sym,"einstein::gxy");
\end{verbatim}
specifies that the grid function \texttt{einstein::gxy} should be
negated under reflections in $x=0$ and $y=0$, but keeps the same value
under reflections in the $z=0$ plane.\\
This is the only information required for the reflection symmetry
since the value of the field at the new (reflected) point does not
require information from any other fields. For example, for a vector
$v = (v_x, v_y, v_z)^T$ reflected in $x=0$, we have
\begin{equation}
v_x \rightarrow -v_x, \qquad v_y \rightarrow v_y, \qquad
v_z \rightarrow v_z.
\end{equation}
That is, the transformation of $v_x$ only needs to know the values of
$v_x$, and does not need to know anything about the values of $v_y$ or
$v_z$. On the other hand, for the $3\pi/2$-rotation corresponding to
Example 3, above, the vector would transform as:
\begin{equation}
v_x \rightarrow -v_y, \qquad v_y \rightarrow v_x, \qquad
v_z \rightarrow v_z.
\end{equation}
In this case, to determine the rotated $v_x$ component it is necessary
to know the value of $v_y$. However, there is no concept of vector or
tensor within Cactus, so that given a grid function corresponding to
$v_x$, it is not generally possible to know which grid function
corresponds to $v_y$ which should be used to determine the rotated
values.\\
As a result, the only symmetries which can easily be implemented
within the current mechanism are those which require only the grid
function itself in order to determine the ghost zone points. This
includes the $\pi$-rotation symmetries (`half-plane', Figure
\ref{fig:rs_rotation_examples} (b)) but not the $3\pi/2$-rotation
symmetries (`quarter-plane', Figure \ref{fig:rs_rotation_examples}
(c)).\\
Table \ref{tbl:rs_xform} lists the transformations of the components
of an arbitrary scalar, vector and two-index tensor under reflections
in each plane, and rotations about each axis.
\begin{table}
\centering
\begin{tabular}{r|rrr|rrr}\hline\hline
& \multicolumn{3}{c|}{reflection in}
& \multicolumn{3}{c}{rotation about} \\
& $x$ & $y$ & $z$ & $x$ & $y$ & $z$ \\ \hline
$\phi$ & 1 & 1 & 1 & 1 & 1 & 1 \\ \hline
$v_x$ & -1 & 1 & 1 & 1 & -1 & -1 \\
$v_y$ & 1 & -1 & 1 & -1 & 1 & -1 \\
$v_z$ & 1 & 1 & -1 & -1 & -1 & 1 \\ \hline
$g_{xx}$ & 1 & 1 & 1 & 1 & 1 & 1 \\
$g_{xy}$ & -1 & -1 & 1 & -1 & -1 & 1 \\
$g_{xz}$ & -1 & 1 & -1 & -1 & 1 & -1 \\
$g_{yy}$ & 1 & 1 & 1 & 1 & 1 & 1 \\
$g_{yz}$ & 1 & -1 & -1 & 1 & -1 & -1 \\
$g_{zz}$ & 1 & 1 & 1 & 1 & 1 & 1 \\ \hline\hline
\end{tabular}
\caption{Transformation factors for reflection and half-plane rotation
symmetries.}
\label{tbl:rs_xform}
\end{table}
We note the following useful fact: The transformation factor $s_i$ for
a rotation about the axis $i$ is given by $s_j \times s_k$ where
$i\neq j\neq k$. For example, for a rotation about the $z$-axis, the
transformation factor is given by
\begin{equation}
s_x \times s_y = -1 \times -1 = 1.
\end{equation}
Intuitively, this is clear since the rotation of the axes by $\pi$
radians about $z$ is equivalent to a reflection in $y$ followed by
a reflection in $x$ (Figure \ref{fig:rs_rotate_reflect}).\\
\begin{figure}
\centering
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_reflect.eps}
\fi
\caption{A rotation by $\pi$ radians about the $z$-axis is equivalent
to successive reflections about the $y$- and $x$-axes.}
\label{fig:rs_rotate_reflect}
\end{figure}
Since the transformation values for reflection symmetries are
already specified for each Cactus grid function, we can use this
information to unambiguously determine the $\pi$-rotation
transformation coefficients, without requiring that any new
information be added if the reflection symmetries have already
been defined (as is the case for any Cactus GFs which are able to
use the current \texttt{bitant}, \texttt{quadrant} and \texttt{octant}
domains).
%------------------------------------------------------------------------------
\section{\texttt{CartGrid3D} Notes}
\label{sec:rs_cartgrid3d}
%------------------------------------------------------------------------------
Two types of rotating symmetry conditions have been implemented in
\texttt{CartGrid3D} as extensions to the \texttt{grid::domain}
parameter.\\
The first, \texttt{bitant\_rotate}, defines a grid which is half-sized
along one axis, and assumes a field that is rotating about a
perpendicular axis. The half-axis is chosen using the
\texttt{bitant\_plane} parameter, which specifies the plane at which
the grid is to be cut as either ``\texttt{xy}'', ``\texttt{xz}'' or
``\texttt{yz}''. The rotation axis is chosen using the
\texttt{rotation\_axis} parameter, which takes values of
``\texttt{x}'', ``\texttt{y}'' or ``\texttt{z}''. For example, to
specify a bitant domain along the positive $y$-axis, on which fields
are rotating about the $z$-axis, the following parameters would do the
job:
\begin{verbatim}
grid::domain = "bitant_rotate"
grid::bitant_plane = "xz"
grid::rotation_axis = "z"
\end{verbatim}
This setup is illustrated in Figure \ref{fig:rs_bitant_example} (a).\\
\begin{figure}
\centering
\begin{tabular}{cc}
\ifpdf
\else
\includegraphics[height=40mm]{fig/rotate_bitant_example.eps}
\fi
&
\ifpdf
\else
\includegraphics[height=30mm]{fig/rotate_quadrant_example.eps}
\fi
\\
(a) & (b)
\end{tabular}
\caption{Active grids for the \texttt{bitant\_rotate} and
\texttt{quadrant\_reflect\_rotate} domains for the examples given in
the text. (a) The given \texttt{bitant\_rotate} domain corresponds
to the $y>0$ half-grid, with fields rotating about the $z$-axis. (b)
The \texttt{quadrant\_reflect\_rotate} example is similar, except
the active grid is only along the positive $z$-axis and a reflection
symmetry is assumed in the $z=0$ plane.}
\label{fig:rs_bitant_example}
\end{figure}
The \texttt{quadrant\_reflect\_rotate} symmetry cuts two of the axes
in half so that only a quadrant of the full domain is active. A
standard reflection symmetry is applied to one of the half-planes,
while the physical fields are assumed to rotate in the other plane. To
set up such a grid which rotates about the $z$-axis and which is
reflection symmetric in the $z=0$ plane, the following parameters
would be used:
\begin{verbatim}
grid::domain = "quadrant_reflect_rotate"
grid::quadrant_direction = "x"
grid::rotation_axis = "z"
\end{verbatim}
Note that the \texttt{quadrant\_direction} parameter follows the
current \texttt{CartGrid3D} standard, which defines the domain on the
\emph{positive} quadrant with the long edge aligned with the specified
axis. It is currently not possible to choose the negative quadrant.\\
Octant rotation symmetries, or the alternate quadrant symmetry (for
which the data on one half-plane is rotated onto the other), are more
difficult to implement without some generalisation of the existing
\texttt{CartGrid3D} specification of symmetry boundaries for the
reasons mentioned in the previous section.
%------------------------------------------------------------------------------
\end{document}
# Interface definition for thorn CartGrid3D
# $Header$
implements: grid
inherits: coordbase
INCLUDE HEADER: Symmetry.h in Symmetry.h
uses include header: CoordBase.h
# The overall size of the domain
CCTK_INT FUNCTION GetDomainSpecification \
(CCTK_INT IN size, \
CCTK_REAL OUT ARRAY physical_min, \
CCTK_REAL OUT ARRAY physical_max, \
CCTK_REAL OUT ARRAY interior_min, \
CCTK_REAL OUT ARRAY interior_max, \
CCTK_REAL OUT ARRAY exterior_min, \
CCTK_REAL OUT ARRAY exterior_max, \
CCTK_REAL OUT ARRAY spacing)
USES FUNCTION GetDomainSpecification
CCTK_INT FUNCTION ConvertFromPhysicalBoundary \
(CCTK_INT IN size, \
CCTK_REAL IN ARRAY physical_min, \
CCTK_REAL IN ARRAY physical_max, \
CCTK_REAL OUT ARRAY interior_min, \
CCTK_REAL OUT ARRAY interior_max, \
CCTK_REAL OUT ARRAY exterior_min, \
CCTK_REAL OUT ARRAY exterior_max, \
CCTK_REAL IN ARRAY spacing)
USES FUNCTION ConvertFromPhysicalBoundary
CCTK_INT FUNCTION \
MultiPatch_GetMap \
(CCTK_POINTER_TO_CONST IN cctkGH)
USES FUNCTION MultiPatch_GetMap
CCTK_INT FUNCTION \
MultiPatch_GetDomainSpecification \
(CCTK_INT IN map, \
CCTK_INT IN size, \
CCTK_REAL OUT ARRAY physical_min, \
CCTK_REAL OUT ARRAY physical_max, \
CCTK_REAL OUT ARRAY interior_min, \
CCTK_REAL OUT ARRAY interior_max, \
CCTK_REAL OUT ARRAY exterior_min, \
CCTK_REAL OUT ARRAY exterior_max, \
CCTK_REAL OUT ARRAY spacing)
USES FUNCTION MultiPatch_GetDomainSpecification
CCTK_INT FUNCTION \
MultiPatch_ConvertFromPhysicalBoundary \
(CCTK_INT IN map, \
CCTK_INT IN size, \
CCTK_REAL IN ARRAY physical_min, \
CCTK_REAL IN ARRAY physical_max, \
CCTK_REAL OUT ARRAY interior_min, \
CCTK_REAL OUT ARRAY interior_max, \
CCTK_REAL OUT ARRAY exterior_min, \
CCTK_REAL OUT ARRAY exterior_max, \
CCTK_REAL IN ARRAY spacing)
USES FUNCTION MultiPatch_ConvertFromPhysicalBoundary
# Register the symmetry boundaries
CCTK_INT FUNCTION SymmetryRegister (CCTK_STRING IN sym_name)
USES FUNCTION SymmetryRegister
CCTK_INT FUNCTION \
SymmetryRegisterGrid \
(CCTK_POINTER IN cctkGH, \
CCTK_INT IN sym_handle, \
CCTK_INT IN ARRAY which_faces, \
CCTK_INT IN ARRAY symmetry_zone_width)
USES FUNCTION SymmetryRegisterGrid
# Apply the symmetry boundary conditions
CCTK_INT FUNCTION Boundary_SelectedGVs \
(CCTK_POINTER_TO_CONST IN GH, \
CCTK_INT IN array_size, \
CCTK_INT ARRAY OUT var_indicies, \
CCTK_INT ARRAY OUT faces, \
CCTK_INT ARRAY OUT boundary_widths, \
CCTK_INT ARRAY OUT table_handles, \
CCTK_STRING IN bc_name)
USES FUNCTION Boundary_SelectedGVs
public:
REAL gridspacings type=SCALAR tags='Checkpoint="no"'
{
coarse_dx, coarse_dy, coarse_dz
} "3D Cartesian grid spacings"
REAL coordinates type=GF tags='Prolongation="None" Checkpoint="no"'
{
x, y, z, r
# will become:
# coord_x, coord_y, coord_z
} "3D Cartesian grid coordinates"
!DESC "Create coordinates by range on a full grid"
ActiveThorns = "pugh pughslab CartGrid3D CoordBase SymBase ioutil ioascii"
driver::global_nsize = 10
grid::type = "byrange"
grid::domain = "full"
grid::xyzmin = -10
grid::xyzmax = 10
IO::out_dir = byrange_full
IOASCII::out1D_vars = "grid::x grid::y grid::z"
IOASCII::out1D_every = 1
# Parameter definitions for thorn CartGrid3D
# $Header$
shares: driver
USES BOOLEAN periodic
USES BOOLEAN periodic_x
USES BOOLEAN periodic_y
USES BOOLEAN periodic_z
private:
BOOLEAN no_origin "DEPRECATED: Don't place grid points on the coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN no_originx "DEPRECATED: Don't place grid points on the x-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN no_originy "DEPRECATED: Don't place grid points on the y-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN no_originz "DEPRECATED: Don't place grid points on the z-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN avoid_originx "Don't place grid points on the x-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN avoid_originy "Don't place grid points on the y-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN avoid_originz "Don't place grid points on the z-coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN avoid_origin "Don't place grid points on the coordinate origin/axes"
{
: :: ""
} "yes"
BOOLEAN register_default_coordinate_systems "register cartnd as the default coordinate systems"
{
} "yes"
restricted:
REAL dx "Coarse grid spacing in x-direction"
{
0:* :: "Positive"
} 0.3
REAL dy "Coarse grid spacing in y-direction"
{
0:* :: "Positive"
} 0.3
REAL dz "Coarse grid spacing in z-direction"
{
0:* :: "Positive"
} 0.3
REAL dxyz "Coarse grid spacing in x,y,z-directions"
{
0:* :: "Positive"
} 0.0
REAL xmin "Coordinate minimum in x-direction"
{
: :: "Anything"
} -1.0
REAL ymin "Coordinate minimum in y-direction"
{
: :: "Anything"
} -1.0
REAL zmin "Coordinate minimum in z-direction"
{
: :: "Anything"
} -1.0
REAL xyzmin "Coordinate minimum in x,y,z-directions"
{
: :: "Anything"
} -424242
REAL xmax "Coordinate maximum in x-direction"
{
: :: "Anything"
} 1.0
REAL ymax "Coordinate maximum in y-direction"
{
: :: "Anything"
} 1.0
REAL zmax "Coordinate maximum in z-direction"
{
: :: "Anything"
} 1.0
REAL xyzmax "Coordinate maximum in xyz-directions"
{
: :: "Anything"
} -424242
KEYWORD type "Grid type"
{
"box" :: "Box grid from -0.5 to 0.5"
"byrange" :: "Specify min and max values"
"byspacing" :: "Specify grid spacings"
"coordbase" :: "Get specification from CoordBase"
"multipatch" :: "Get specification from MultiPatch"
} "box"
KEYWORD domain "Domain type"
{
"octant" :: "Use an octant about the origin"
"quadrant" :: "Use a quadrant in x-y plane"
"quadrant_reflect_rotate" :: "Use a quadrant with rotation symmetry about an axis"
"bitant" :: "Use a bitant about the x-y plane"
"bitant_rotate" :: "Use a bitant with rotation symmetry about an axis"
"full" :: "Use the full domain"
} "full"
KEYWORD bitant_plane "Plane defining bitant domain"
{
"xy" :: "xy-plane"
"xz" :: "xz-plane"
"yz" :: "yz-plane"
} "xy"
KEYWORD quadrant_direction "Direction defining quadrant domain"
{
"x" :: "x-direction"
"y" :: "y-direction"
"z" :: "z-direction"
} "z"
KEYWORD rotation_axis "Axis about which the rotation symmetry is to be applied"
{
"x" :: "x-axis"
"y" :: "y-axis"
"z" :: "z-axis"
} "z"
BOOLEAN symmetry_xmin "Symmetry boundary condition on lower x boundary"
{
: :: "Logical"
} "no"
BOOLEAN symmetry_ymin "Symmetry boundary condition on lower y boundary"
{
: :: "Logical"
} "no"
BOOLEAN symmetry_zmin "Symmetry boundary condition on lower z boundary"
{
: :: "Logical"
} "no"
BOOLEAN symmetry_xmax "Symmetry boundary condition on upper x boundary"
{
: :: "Logical"
} "no"
BOOLEAN symmetry_ymax "Symmetry boundary condition on upper y boundary"
{
: :: "Logical"
} "no"
BOOLEAN symmetry_zmax "Symmetry boundary condition on upper z boundary"
{
: :: "Logical"
} "no"
private:
KEYWORD set_coordinate_ranges_on "On which grids to set the coordinate ranges"
{
"all grids" :: "set ranges in local mode, on the coarsest level"
"all maps" :: "set ranges in singlemap mode, on the coarsest level"
"first level" :: "set ranges in level mode, on the first level"
} "all grids"
# Schedule definitions for thorn CartGrid3D
# $Header$
STORAGE: coordinates gridspacings
schedule SymmetryStartup at CCTK_STARTUP
{
LANG: C
} "Register GH Extension for GridSymmetry"
schedule RegisterCartGrid3DCoords at CCTK_WRAGH
{
LANG:C
OPTIONS: meta
} "Register coordinates for the Cartesian grid"
schedule RegisterSymmetryBoundaries in SymmetryRegister
{
LANG:C
OPTIONS: meta
} "Register symmetry boundaries"
schedule ParamCheck_CartGrid3D at CCTK_PARAMCHECK
{
LANG:C
} "Check coordinates for CartGrid3D"
if (CCTK_EQUALS (set_coordinate_ranges_on, "all grids"))
{
schedule CartGrid3D_SetRanges at CCTK_BASEGRID as SpatialSpacings before SpatialCoordinates
{
LANG:C
} "Set up ranges for spatial 3D Cartesian coordinates (on all grids)"
}
else if (CCTK_EQUALS (set_coordinate_ranges_on, "all maps"))
{
schedule CartGrid3D_SetRanges at CCTK_BASEGRID as SpatialSpacings before SpatialCoordinates
{
LANG:C
OPTIONS: singlemap
} "Set up ranges for spatial 3D Cartesian coordinates (on all maps)"
}
else if (CCTK_EQUALS (set_coordinate_ranges_on, "first level"))
{
schedule CartGrid3D_SetRanges at CCTK_BASEGRID as SpatialSpacings before SpatialCoordinates
{
LANG:C
OPTIONS: level
} "Set up ranges for spatial 3D Cartesian coordinates (on first level)"
}
schedule CartGrid3D_SetCoordinates as SpatialCoordinates at CCTK_BASEGRID
{
LANG:C
WRITES: grid::coordinates(Everywhere)
} "Set up spatial 3D Cartesian coordinates on the GH"
schedule CartGrid3D_SetCoordinates as SpatialCoordinates at CCTK_POSTREGRIDINITIAL
{
LANG: C
WRITES: grid::coordinates(Everywhere)
} "Set Coordinates after regridding"
schedule CartGrid3D_SetCoordinates as SpatialCoordinates at CCTK_POSTREGRID
{
LANG: C
WRITES: grid::coordinates(Everywhere)
} "Set Coordinates after regridding"
schedule CartGrid3D_ApplyBC in BoundaryConditions
{
LANG: C
} "Apply symmetry boundary conditions"
/*@@
@file CartGrid3D.c
@date Thu Oct 7 13:20:06 1999
@author Tom Goodale
@desc
Set up coordinates for a 3D Cartesian grid.
C Conversion of Fortran routine written by Gab.
@version $Id$
@enddesc
@@*/
#include <stdio.h>
#include <math.h>
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
#include "util_Table.h"
#include "Symmetry.h"
#include "CoordBase.h"
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_CartGrid3D_c);
/********************************************************************
********************* Macro Definitions **************************
********************************************************************/
#define max(a, b) ((a) > (b) ? (a) : (b))
#define SQR(a) ((a) * (a))
/********************************************************************
********************* Scheduled Routine Prototypes ***************
********************************************************************/
void CartGrid3D_SetRanges(CCTK_ARGUMENTS);
void CartGrid3D_SetCoordinates(CCTK_ARGUMENTS);
/********************************************************************
********************* External Routine Prototypes ****************
********************************************************************/
void DecodeSymParameters3D(int sym[6]);
/********************************************************************
********************* Local Routine Prototypes *******************
********************************************************************/
/********************************************************************
********************* Scheduled Routines *************************
********************************************************************/
/*@@
@routine CartGrid3D_SetRanges
@date Oct 1999?
@author Tom Goodale? Gabrielle Allen? Thomas Radke
@date Mon 3 Jan 2005
@author Thomas Radke
@desc
Sets up ranges for Cartesian coordinates.
@enddesc
@calls DecodeSymParameters3D, CCTK_Equals, CCTK_WARN,
CCTK_CoordRegisterRange, CCTK_CoordRegisterRangePhysIndex,
CCTK_INFO, Coord_CoordHandle, Util_TableSetReal,
Util_TableSetString, Util_TableSetInt
@var CCTK_ARGUMENTS
@vdesc Cactus argument list
@vtype
@vio in/out
@endvar
@@*/
void CartGrid3D_SetRanges(CCTK_ARGUMENTS) {
int i;
int coord_handle, ierr;
CCTK_REAL this_delta[3], origin[3], min1[3], max1[3];
CCTK_REAL *coarse_delta[3];
double lower[3], upper[3];
int domainsym[6], cntstag[3], loweri[3], upperi[3], do_periodic[3];
char coord_name[16];
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
if (CCTK_EQUALS(set_coordinate_ranges_on, "first level")) {
/* Ranges must be set up only once, and this must happen on the
coarse grid. However, the coarse grid itself may not actually
exist; in this case, use the coarsest existing grid. We assume
that this is the first grid for which this routine is
called. */
static int is_coarsest_refinement_level = 1;
if (!is_coarsest_refinement_level) {
return;
}
is_coarsest_refinement_level = 0;
} else {
/* Ranges need to be set up only once (or once per map), on the
coarsest refinement level */
int const is_coarsest_refinement_level =
cctk_levfac[0] == 1 && cctk_levfac[1] == 1 && cctk_levfac[2] == 1;
if (!is_coarsest_refinement_level) {
return;
}
}
coarse_delta[0] = coarse_dx;
coarse_delta[1] = coarse_dy;
coarse_delta[2] = coarse_dz;
/* Calculate the coordinate ranges only for the coarsest level */
/* Avoid origin? Default is yes */
cntstag[0] = no_origin && no_originx && avoid_origin && avoid_originx;
cntstag[1] = no_origin && no_originy && avoid_origin && avoid_originy;
cntstag[2] = no_origin && no_originz && avoid_origin && avoid_originz;
/* Determine symmetries of domain */
DecodeSymParameters3D(domainsym);
do_periodic[0] = periodic && periodic_x;
do_periodic[1] = periodic && periodic_y;
do_periodic[2] = periodic && periodic_z;
/* Calculate physical indices, using symmetries and periodicity */
for (i = 0; i < 3; i++) {
loweri[i] = 0;
upperi[i] = cctk_gsh[i] - 1;
if (domainsym[2 * i + 0] || do_periodic[i]) {
loweri[i] += cctk_nghostzones[i];
}
if (domainsym[2 * i + 1] || do_periodic[i]) {
upperi[i] -= cctk_nghostzones[i];
}
}
/****************************************************************
*
* BYRANGE
*
* User gives: minimum and maximum values of coordinates and
* the number of gridpoints on the coarse grid
*
***************************************************************/
/**************************************************************
*
* BOX (-0.5 to 0.5)
*
* User gives: number of gridpoints on the coarse grid
*
**************************************************************/
if (CCTK_Equals(type, "byrange") || CCTK_Equals(type, "box")) {
if (CCTK_Equals(type, "box")) {
/* Coordinates are all -0.5 to 0.5 */
min1[0] = min1[1] = min1[2] = -0.5;
max1[0] = max1[1] = max1[2] = 0.5;
} else {
if (xyzmin != -424242) {
min1[0] = min1[1] = min1[2] = xyzmin;
} else {
min1[0] = xmin;
min1[1] = ymin;
min1[2] = zmin;
}
if (xyzmax != -424242) {
max1[0] = max1[1] = max1[2] = xyzmax;
} else {
max1[0] = xmax;
max1[1] = ymax;
max1[2] = zmax;
}
}
/* Grid spacing on coarsest grid */
for (i = 0; i < 3; i++) {
if (domainsym[2 * i + 0]) {
if (cntstag[i]) {
*coarse_delta[i] =
max1[i] / (cctk_gsh[i] - cctk_nghostzones[i] - 0.5);
origin[i] = -(cctk_nghostzones[i] - 0.5) * *coarse_delta[i];
} else {
*coarse_delta[i] = max1[i] / (cctk_gsh[i] - cctk_nghostzones[i] - 1);
origin[i] = -cctk_nghostzones[i] * *coarse_delta[i];
}
} else if (domainsym[2 * i + 1]) {
if (cntstag[i]) {
*coarse_delta[i] =
fabs(min1[i]) / (cctk_gsh[i] - cctk_nghostzones[i] - 0.5);
} else {
*coarse_delta[i] =
fabs(min1[i]) / (cctk_gsh[i] - cctk_nghostzones[i] - 1);
}
origin[i] = min1[i];
} else {
if (cntstag[i]) {
CCTK_VWarn(4, __LINE__, __FILE__, CCTK_THORNSTRING,
"Ignoring request to avoid origin in %c-direction, "
"it is not relevant for this grid type",
'x' + i);
}
*coarse_delta[i] = (max1[i] - min1[i]) / max(cctk_gsh[i] - 1, 1);
origin[i] = min1[i];
}
this_delta[i] = *coarse_delta[i];
}
}
/**************************************************************
* BYSPACING
*
* User gives: grid spacing on the coarsest GH and
* the number of gridpoints on the coarsest GH
*
**************************************************************/
else if (CCTK_Equals(type, "byspacing")) {
/* Dx, Dy, Dx on the coarsest grid */
if (dxyz > 0) {
*coarse_delta[0] = *coarse_delta[1] = *coarse_delta[2] = dxyz;
} else {
*coarse_delta[0] = dx;
*coarse_delta[1] = dy;
*coarse_delta[2] = dz;
}
for (i = 0; i < 3; i++) {
this_delta[i] = *coarse_delta[i];
/* Set minimum values of coordinates */
if (domainsym[2 * i + 0]) {
origin[i] = -(cctk_nghostzones[i] - cntstag[i] * 0.5);
} else if (domainsym[2 * i + 1]) {
origin[i] = -(cctk_gsh[i] - 1 - cctk_nghostzones[i] + cntstag[i] * 0.5);
} else {
origin[i] = -0.5 * (cctk_gsh[i] - 1 - cntstag[i] * cctk_gsh[i] % 2);
}
origin[i] *= this_delta[i];
}
}
/**************************************************************
* COORDBASE
*
* CoordBase gives: grid spacing on the coarsest GH and
* minimum and maximum values of coordinates and
* the number of gridpoints on the coarsest GH
*
**************************************************************/
else if (CCTK_Equals(type, "coordbase")) {
CCTK_REAL physical_min[3];
CCTK_REAL physical_max[3];
CCTK_REAL interior_min[3];
CCTK_REAL interior_max[3];
CCTK_REAL exterior_min[3];
CCTK_REAL exterior_max[3];
CCTK_REAL spacing[3];
int d;
ierr = GetDomainSpecification(3, physical_min, physical_max, interior_min,
interior_max, exterior_min, exterior_max,
spacing);
if (ierr)
CCTK_WARN(0, "error returned from function GetDomainSpecification");
/* Adapt to convergence level */
for (d = 0; d < 3; ++d) {
spacing[d] *= pow(cctkGH->cctk_convfac, cctkGH->cctk_convlevel);
}
ierr = ConvertFromPhysicalBoundary(3, physical_min, physical_max,
interior_min, interior_max, exterior_min,
exterior_max, spacing);
if (ierr)
CCTK_WARN(0, "error returned from function ConvertFromPhysicalBoundary");
for (d = 0; d < 3; ++d) {
origin[d] = exterior_min[d];
this_delta[d] = spacing[d];
*coarse_delta[d] = this_delta[d];
}
}
/**************************************************************
* MULTIPATCH
*
* MultiPatch gives: grid spacing on the coarsest GH and
* minimum and maximum values of coordinates and
* the number of gridpoints on the coarsest GH
*
**************************************************************/
else if (CCTK_Equals(type, "multipatch")) {
CCTK_REAL physical_min[3];
CCTK_REAL physical_max[3];
CCTK_REAL interior_min[3];
CCTK_REAL interior_max[3];
CCTK_REAL exterior_min[3];
CCTK_REAL exterior_max[3];
CCTK_REAL spacing[3];
CCTK_INT map;
int d;
map = MultiPatch_GetMap(cctkGH);
if (map < 0)
CCTK_WARN(0, "error returned from function MultiPatch_GetMap");
ierr = MultiPatch_GetDomainSpecification(
map, 3, physical_min, physical_max, interior_min, interior_max,
exterior_min, exterior_max, spacing);
if (ierr)
CCTK_WARN(
0, "error returned from function MultiPatch_GetDomainSpecification");
/* Adapt to convergence level */
for (d = 0; d < 3; ++d) {
spacing[d] *= pow(cctkGH->cctk_convfac, cctkGH->cctk_convlevel);
}
if (CCTK_IsFunctionAliased("MultiPatch_ConvertFromPhysicalBoundary")) {
ierr = MultiPatch_ConvertFromPhysicalBoundary(
map, 3, physical_min, physical_max, interior_min, interior_max,
exterior_min, exterior_max, spacing);
if (ierr)
CCTK_WARN(0, "error returned from function "
"MultiPatch_ConvertFromPhysicalBoundary");
} else {
ierr = ConvertFromPhysicalBoundary(3, physical_min, physical_max,
interior_min, interior_max,
exterior_min, exterior_max, spacing);
if (ierr)
CCTK_WARN(0,
"error returned from function ConvertFromPhysicalBoundary");
}
for (d = 0; d < 3; ++d) {
origin[d] = exterior_min[d];
this_delta[d] = spacing[d];
*coarse_delta[d] = this_delta[d];
}
}
else {
if (0)
CCTK_WARN(0, "type is out of bounds");
}
/* Register the coordinate ranges */
for (i = 0; i < 3; i++) {
cctkGH->cctk_delta_space[i] = this_delta[i];
cctkGH->cctk_origin_space[i] = origin[i];
lower[i] = origin[i];
upper[i] = origin[i] + this_delta[i] * (cctk_gsh[i] - 1);
if (CCTK_CoordRegisterRange(cctkGH, lower[i], upper[i], i + 1, NULL,
"cart3d") < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Failed to register %c-coordinate computational range",
'x' + i);
}
if (CCTK_CoordRegisterRangePhysIndex(cctkGH, loweri[i], upperi[i], i + 1,
NULL, "cart3d") < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Failed to register %c-coordinate physical range", 'x' + i);
}
}
CCTK_INFO("Grid Spacings:");
CCTK_VInfo(CCTK_THORNSTRING, "dx=>%12.7e dy=>%12.7e dz=>%12.7e",
(double)cctk_delta_space[0], (double)cctk_delta_space[1],
(double)cctk_delta_space[2]);
CCTK_INFO("Computational Coordinates:");
CCTK_VInfo(CCTK_THORNSTRING,
"x=>[%6.3f,%6.3f] y=>[%6.3f,%6.3f] z=>[%6.3f,%6.3f]", lower[0],
upper[0], lower[1], upper[1], lower[2], upper[2]);
CCTK_INFO("Indices of Physical Coordinates:");
CCTK_VInfo(CCTK_THORNSTRING, "x=>[%d,%d] y=>[%d,%d] z=>[%d,%d]", loweri[0],
upperi[0], loweri[1], upperi[1], loweri[2], upperi[2]);
if ((domainsym[0] == GFSYM_ROTATION_Y || domainsym[2] == GFSYM_ROTATION_X) &&
(lower[2] + upper[2] > 1e-12)) {
CCTK_WARN(0, "minimum z must equal maximum z for rotation symmetry");
}
if ((domainsym[0] == GFSYM_ROTATION_Z || domainsym[4] == GFSYM_ROTATION_X) &&
(lower[1] + upper[1] > 1e-12)) {
CCTK_WARN(0, "minimum y must equal maximum y for rotation symmetry");
}
if ((domainsym[2] == GFSYM_ROTATION_Z || domainsym[4] == GFSYM_ROTATION_Y) &&
(lower[0] - upper[0] > 1e-12)) {
CCTK_WARN(0, "minimum x must equal maximum x for rotation symmetry");
}
/* cart3d */
for (i = 0; i < 3; i++) {
sprintf(coord_name, "%c", 'x' + i);
coord_handle = Coord_CoordHandle(cctkGH, coord_name, "cart3d");
if (coord_handle < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Error retreiving coordinate handle for '%s' of cart3d",
coord_name);
}
sprintf(coord_name, "grid::%c", 'x' + i);
ierr = Util_TableSetInt(coord_handle, loweri[i], "PHYSICALMIN");
ierr += Util_TableSetReal(coord_handle, lower[i], "COMPMIN");
ierr += Util_TableSetInt(coord_handle, upperi[i], "PHYSICALMAX");
ierr += Util_TableSetReal(coord_handle, upper[i], "COMPMAX");
ierr += Util_TableSetString(coord_handle, "uniform", "TYPE");
ierr += Util_TableSetString(coord_handle, "no", "TIMEDEPENDENT");
ierr += Util_TableSetString(coord_handle, "CCTK_REAL", "DATATYPE");
ierr +=
Util_TableSetInt(coord_handle, CCTK_VarIndex(coord_name), "GAINDEX");
ierr += Util_TableSetReal(coord_handle, cctk_delta_space[i], "DELTA");
}
/* cart2d */
for (i = 0; i < 2; i++) {
sprintf(coord_name, "%c", 'x' + i);
coord_handle = Coord_CoordHandle(cctkGH, coord_name, "cart2d");
if (coord_handle < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Error retreiving coordinate handle for '%s' of cart2d",
coord_name);
}
sprintf(coord_name, "grid::%c", 'x' + i);
ierr = Util_TableSetReal(coord_handle, lower[i], "PHYSICALMIN"); /*??*/
ierr += Util_TableSetReal(coord_handle, lower[i], "COMPMIN");
ierr += Util_TableSetReal(coord_handle, upper[i], "PHYSICALMAX"); /*??*/
ierr += Util_TableSetReal(coord_handle, upper[i], "COMPMAX");
ierr += Util_TableSetString(coord_handle, "uniform", "TYPE");
ierr += Util_TableSetString(coord_handle, "no", "TIMEDEPENDENT");
ierr += Util_TableSetString(coord_handle, "CCTK_REAL", "DATATYPE");
ierr +=
Util_TableSetInt(coord_handle, CCTK_VarIndex(coord_name), "GAINDEX");
ierr += Util_TableSetReal(coord_handle, cctk_delta_space[i], "DELTA");
}
/* cart1d */
coord_handle = Coord_CoordHandle(cctkGH, "x", "cart1d");
if (coord_handle < 0) {
CCTK_WARN(0, "Error retreiving coordinate handle for x of cart1d");
}
ierr = Util_TableSetReal(coord_handle, lower[0], "PHYSICALMIN"); /*??*/
ierr += Util_TableSetReal(coord_handle, lower[0], "COMPMIN");
ierr += Util_TableSetReal(coord_handle, upper[0], "PHYSICALMAX"); /*??*/
ierr += Util_TableSetReal(coord_handle, upper[0], "COMPMAX");
ierr += Util_TableSetString(coord_handle, "uniform", "TYPE");
ierr += Util_TableSetString(coord_handle, "no", "TIMEDEPENDENT");
ierr += Util_TableSetString(coord_handle, "CCTK_REAL", "DATATYPE");
ierr += Util_TableSetInt(coord_handle, CCTK_VarIndex("grid::x"), "GAINDEX");
ierr += Util_TableSetReal(coord_handle, cctk_delta_space[0], "DELTA");
/* Set up coordinate tables */
/* Should this be done in a function?
WriteCoordinateTable(cctkGH, "cart3d"); */
}
/*@@
@routine CartGrid3D_SetCoordinates
@date 2004-06-17
@author Christian Ott
@desc
Sets up Cartesian coordinates.
@enddesc
@var CCTK_ARGUMENTS
@vdesc Cactus argument list
@vtype
@vio in/out
@endvar
@@*/
void CartGrid3D_SetCoordinates(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS;
/* CCTK_VInfo(CCTK_THORNSTRING,"Resetting coordinates after regridding."); */
for (int k = 0; k < cctk_lsh[2]; k++) {
for (int j = 0; j < cctk_lsh[1]; j++) {
for (int i = 0; i < cctk_lsh[0]; i++) {
int idx = CCTK_GFINDEX3D(cctkGH, i, j, k);
x[idx] =
CCTK_DELTA_SPACE(0) * (i + cctk_lbnd[0]) + CCTK_ORIGIN_SPACE(0);
y[idx] =
CCTK_DELTA_SPACE(1) * (j + cctk_lbnd[1]) + CCTK_ORIGIN_SPACE(1);
z[idx] =
CCTK_DELTA_SPACE(2) * (k + cctk_lbnd[2]) + CCTK_ORIGIN_SPACE(2);
r[idx] = sqrt(SQR(x[idx]) + SQR(y[idx]) + SQR(z[idx]));
}
}
}
}
/*@@
@file DecodeSymParameters.c
@date Wed May 10 18:58:00 EST 2000
@author Erik Schnetter
@desc
Decode the symmetry parameters.
@enddesc
@version $Id$
@@*/
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
#include "Symmetry.h"
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_DecodeSymParameters_c)
void DecodeSymParameters3D(int sym[6]);
void CCTK_FCALL CCTK_FNAME(DecodeSymParameters3D)(int sym[6]);
/*@@
@routine DecodeSymParameters3D
@date Thu May 11 11:49:08 2000
@author Erik Schnetter
@desc
Decode the Symmetry parameters.
returns the symmetry flags (yes/no=1/0)
in the array sym
@enddesc
@@*/
void DecodeSymParameters3D(int sym[6]) {
DECLARE_CCTK_PARAMETERS
/* The default is as set by the explicit symmetry parameters */
/* lower faces */
sym[0] = symmetry_xmin;
sym[2] = symmetry_ymin;
sym[4] = symmetry_zmin;
/* upper faces */
sym[1] = symmetry_xmax;
sym[3] = symmetry_ymax;
sym[5] = symmetry_zmax;
/* The default can be overridden by bitant, quadrant, and octant mode */
if (CCTK_Equals(domain, "bitant")) {
if (CCTK_Equals(bitant_plane, "xy")) {
sym[4] = GFSYM_REFLECTION;
} else if (CCTK_Equals(bitant_plane, "xz")) {
sym[2] = GFSYM_REFLECTION;
} else if (CCTK_Equals(bitant_plane, "yz")) {
sym[0] = GFSYM_REFLECTION;
}
} else if (CCTK_Equals(domain, "bitant_rotate")) {
if (CCTK_Equals(bitant_plane, "xy")) {
if (CCTK_Equals(rotation_axis, "y"))
sym[4] = GFSYM_ROTATION_Y;
else if (CCTK_Equals(rotation_axis, "x"))
sym[4] = GFSYM_ROTATION_X;
} else if (CCTK_Equals(bitant_plane, "xz")) {
if (CCTK_Equals(rotation_axis, "x"))
sym[2] = GFSYM_ROTATION_X;
else if (CCTK_Equals(rotation_axis, "z"))
sym[2] = GFSYM_ROTATION_Z;
} else if (CCTK_Equals(bitant_plane, "yz")) {
if (CCTK_Equals(rotation_axis, "y"))
sym[0] = GFSYM_ROTATION_Y;
else if (CCTK_Equals(rotation_axis, "z"))
sym[0] = GFSYM_ROTATION_Z;
}
} else if (CCTK_Equals(domain, "quadrant")) {
if (CCTK_Equals(quadrant_direction, "x")) {
sym[2] = GFSYM_REFLECTION;
sym[4] = GFSYM_REFLECTION;
} else if (CCTK_Equals(quadrant_direction, "y")) {
sym[0] = GFSYM_REFLECTION;
sym[4] = GFSYM_REFLECTION;
} else if (CCTK_Equals(quadrant_direction, "z")) {
sym[0] = GFSYM_REFLECTION;
sym[2] = GFSYM_REFLECTION;
}
} else if (CCTK_Equals(domain, "quadrant_reflect_rotate")) {
if (CCTK_Equals(quadrant_direction, "x")) {
if (CCTK_Equals(rotation_axis, "y")) {
sym[2] = GFSYM_REFLECTION;
sym[4] = GFSYM_ROTATION_Y;
} else if (CCTK_Equals(rotation_axis, "z")) {
sym[2] = GFSYM_ROTATION_Z;
sym[4] = GFSYM_REFLECTION;
}
} else if (CCTK_Equals(quadrant_direction, "y")) {
if (CCTK_Equals(rotation_axis, "x")) {
sym[0] = GFSYM_REFLECTION;
sym[4] = GFSYM_ROTATION_X;
}
if (CCTK_Equals(rotation_axis, "z")) {
sym[0] = GFSYM_ROTATION_Z;
sym[4] = GFSYM_REFLECTION;
}
} else if (CCTK_Equals(quadrant_direction, "z")) {
if (CCTK_Equals(rotation_axis, "x")) {
sym[0] = GFSYM_REFLECTION;
sym[2] = GFSYM_ROTATION_X;
}
if (CCTK_Equals(rotation_axis, "y")) {
sym[0] = GFSYM_ROTATION_Y;
sym[2] = GFSYM_REFLECTION;
}
}
} else if (CCTK_Equals(domain, "octant")) {
sym[0] = GFSYM_REFLECTION;
sym[2] = GFSYM_REFLECTION;
sym[4] = GFSYM_REFLECTION;
}
}
void CCTK_FCALL CCTK_FNAME(DecodeSymParameters3D)(int sym[6]) {
DecodeSymParameters3D(sym);
}
/*@@
@file GetSymmetry.c
@date April 12 2002
@author Frank Herrmann
@desc
This file contains the routines for getting symmetry information
code stolen from SetSymmetry.c
@enddesc
@version $Id$
@@*/
#include <stdlib.h>
#include "cctk.h"
#include "cctk_Parameters.h"
#include "cctk_FortranString.h"
#include "Symmetry.h"
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_GetSymmetry_c)
/********************************************************************
********************* Local Defines ***********************
********************************************************************/
#define MAX_DIM 3
#define MAX_FACE 6
/********************************************************************
********************* Local Routine Prototypes *********************
********************************************************************/
void DecodeSymParameters3D(int sym[6]);
void CCTK_FCALL CCTK_FNAME(GetCartSymVI)(int *ierr, const cGH **GH, int *sym,
const int *vi);
void CCTK_FCALL CCTK_FNAME(GetCartSymVN)(int *ierr, const cGH **GH, int *sym,
ONE_FORTSTRING_ARG);
/********************************************************************
********************* External Routines **********************
********************************************************************/
/*@@
@routine GetCartSymVI
@date Mon Mar 15 15:10:58 1999
@author Frank Herrmann
@desc
This routine returns symmetry for variable index.
@enddesc
@@*/
int GetCartSymVI(const cGH *GH, int *sym, int vi) {
int domainsym[MAX_FACE];
SymmetryGHex *sGHex;
int dir;
DECLARE_CCTK_PARAMETERS
if (vi < 0 || vi >= CCTK_NumVars()) {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid variable index %d in GetCartSymVI", vi);
return (-1);
}
/* Pointer to the SymmetryGHextension */
sGHex = (SymmetryGHex *)CCTK_GHExtension(GH, "Symmetry");
/* Reference the hash table in the GHex and get the kind of
* symmetry being applied
*/
#ifdef SYM_DEBUG
printf("GetSymmetry: %s [%d,%d,%d]\n", CCTK_VarName(vi), sym[0], sym[1],
sym[2]);
#endif
DecodeSymParameters3D(domainsym);
for (dir = 0; dir < MAX_FACE; ++dir) {
sym[dir / 2] = GFSYM_UNKNOWN;
if (domainsym[dir])
sym[dir / 2] = sGHex->GFSym[vi][dir];
}
return 0;
}
void CCTK_FCALL CCTK_FNAME(GetCartSymVI)(int *ierr, const cGH **GH, int *sym,
const int *vi) {
*ierr = GetCartSymVI(*GH, sym, *vi);
}
/*@@
@routine GetCartSymVN
@date April 12 2002
@author Frank Herrmann
@desc
Gets symmetry boundary conditions from variable name
@enddesc
@@*/
int GetCartSymVN(const cGH *GH, int *sym, const char *vn) {
int vi;
vi = CCTK_VarIndex(vn);
if (vi > -1) {
return (GetCartSymVI(GH, sym, vi));
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Cannot find variable %s in GetCartSymVN", vn);
return (-1);
}
}
void CCTK_FCALL CCTK_FNAME(GetCartSymVN)(int *ierr, const cGH **GH, int *sym,
ONE_FORTSTRING_ARG) {
ONE_FORTSTRING_CREATE(vn)
*ierr = GetCartSymVN(*GH, sym, vn);
free(vn);
}
/*@@
@file ParamCheck.c
@date Thu Oct 7 17:11:44 1999
@author Tom Goodale
@desc
C version of Gab's paramcheck stuff
@enddesc
@@*/
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_ParamCheck_c)
void ParamCheck_CartGrid3D(CCTK_ARGUMENTS);
/*@@
@routine ParamCheckCartGrid3D
@date Tue Feb 23 1999
@author Gabrielle Allen
@desc
Check parameters for CartGrid3D
@enddesc
@calls
@calledby
@history
@hdate Thu Oct 7 17:23:15 1999 @hauthor Tom Goodale
@hdesc Converted to C
@endhistory
@@*/
void ParamCheck_CartGrid3D(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS
DECLARE_CCTK_PARAMETERS
int iflag;
iflag = 0;
if (CCTK_Equals(type, "byrange")) {
if (CCTK_Equals(domain, "octant")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant_reflect_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "bitant")) {
iflag++;
} else if (CCTK_Equals(domain, "bitant_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "full")) {
iflag++;
}
} else if (CCTK_Equals(type, "byspacing")) {
if (CCTK_Equals(domain, "bitant")) {
iflag++;
}
if (CCTK_Equals(domain, "bitant_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant_reflect_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "octant")) {
iflag++;
} else if (CCTK_Equals(domain, "full")) {
iflag++;
}
} else if (CCTK_Equals(type, "coordbase") ||
CCTK_Equals(type, "multipatch")) {
if (CCTK_IsFunctionAliased("GetDomainSpecification")) {
if (CCTK_Equals(domain, "bitant")) {
iflag++;
}
if (CCTK_Equals(domain, "bitant_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant")) {
iflag++;
} else if (CCTK_Equals(domain, "quadrant_reflect_rotate")) {
iflag++;
} else if (CCTK_Equals(domain, "octant")) {
iflag++;
} else if (CCTK_Equals(domain, "full")) {
iflag++;
}
}
} else if (CCTK_Equals(type, "box")) {
iflag++;
if (!CCTK_Equals(domain, "full"))
CCTK_PARAMWARN("No symmetries can be used with box grid");
}
/* No grid was set up */
if (iflag != 1) {
CCTK_PARAMWARN("No grid set up in CartGrid3D");
}
if (CCTK_Equals(domain, "bitant_rotate")) {
if (CCTK_nProcs(cctkGH) != 1)
CCTK_PARAMWARN("domain 'bitant_rotate' only works on a single processor");
if (CCTK_Equals(bitant_plane, "xy") && CCTK_Equals(rotation_axis, "z"))
CCTK_PARAMWARN(
"rotation_axis=\"z\" is incompatible with bitant_plane=\"xy\"");
if (CCTK_Equals(bitant_plane, "xz") && CCTK_Equals(rotation_axis, "y"))
CCTK_PARAMWARN(
"rotation_axis=\"y\" is incompatible with bitant_plane=\"xz\"");
if (CCTK_Equals(bitant_plane, "yz") && CCTK_Equals(rotation_axis, "x"))
CCTK_PARAMWARN(
"rotation_axis=\"x\" is incompatible with bitant_plane=\"yz\"");
}
if (CCTK_Equals(domain, "quadrant_reflect_rotate")) {
if (CCTK_nProcs(cctkGH) != 1)
CCTK_PARAMWARN(
"domain 'quadrant_reflect_rotate' only works on a single processor");
if (CCTK_Equals(quadrant_direction, "x") && CCTK_Equals(rotation_axis, "x"))
CCTK_PARAMWARN(
"rotation_axis=\"x\" is incompatible with quadrant_direction=\"x\"");
if (CCTK_Equals(quadrant_direction, "y") && CCTK_Equals(rotation_axis, "y"))
CCTK_PARAMWARN(
"rotation_axis=\"y\" is incompatible with quadrant_direction=\"y\"");
if (CCTK_Equals(quadrant_direction, "z") && CCTK_Equals(rotation_axis, "z"))
CCTK_PARAMWARN(
"rotation_axis=\"z\" is incompatible with quadrant_direction=\"z\"");
}
return;
}
/* $Header$ */
#include <stdlib.h>
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
#include "Symmetry.h"
void DecodeSymParameters3D(int sym[6]);
void RegisterSymmetryBoundaries(CCTK_ARGUMENTS);
void RegisterSymmetryBoundaries(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
int sym[6];
int n;
CCTK_INT faces[6];
CCTK_INT width[6];
CCTK_INT handle;
DecodeSymParameters3D(sym);
for (n = 0; n < 6; ++n) {
faces[n] = sym[n];
width[n] = cctk_nghostzones[n / 2];
}
handle = SymmetryRegister("CartGrid3D");
if (handle < 0) {
CCTK_WARN(0, "Could not register symmetry boundary condition");
}
if (SymmetryRegisterGrid(cctkGH, handle, faces, width) < 0) {
CCTK_WARN(0, "Could not register the symmetry boundaries -- probably some "
"other thorn has already registered the same boundary faces "
"for a different symmetry");
}
}
/*@@
@file Symmetry.c
@date Mon Mar 15 15:09:00 1999
@author Gerd Lanfermann
@desc
This file contains the routines for registering and applying symmetry
boundary conditions
@enddesc
@@*/
#include <stdlib.h>
#include "cctk.h"
#include "cctk_Parameters.h"
#include "cctk_FortranString.h"
#include "Symmetry.h"
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_SetSymmetry_c)
/********************************************************************
********************* External Routines **********************
********************************************************************/
void DecodeSymParameters3D(int sym[6]);
void CCTK_FCALL CCTK_FNAME(SetCartSymVI)(int *ierr, const cGH **GH,
const int *sym, const int *vi);
void CCTK_FCALL CCTK_FNAME(SetCartSymVN)(int *ierr, const cGH **GH,
const int *sym, ONE_FORTSTRING_ARG);
void CCTK_FCALL CCTK_FNAME(SetCartSymGI)(int *ierr, const cGH **GH,
const int *sym, const int *gi);
void CCTK_FCALL CCTK_FNAME(SetCartSymGN)(int *ierr, const cGH **GH,
const int *sym, ONE_FORTSTRING_ARG);
/*@@
@routine SetCartSymmetry
@date Mon Mar 15 15:10:58 1999
@author Gerd Lanfermann
@desc
This routine sets the GH extension (EinsteinBoundGHex *bGHex),
which describes the symmetry boundary type of each GF. Takes
the name of the GF ("implementation::gfname") and the
symmetry operators sx,sy,sz and inserts them in the array bGHex.
These values will looked up by the application routines
SymmetryWrappers
@enddesc
@history
enhanced by E.Schnetter
@endhistory
@@*/
int SetCartSymVI(const cGH *GH, const int *sym, int vi) {
int domainsym[MAX_FACE];
SymmetryGHex *sGHex;
int dir;
DECLARE_CCTK_PARAMETERS
if (vi < 0 || vi >= CCTK_NumVars()) {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid variable index %d in SetCartSymVI", vi);
return (-1);
}
/* Pointer to the SymmetryGHextension */
sGHex = (SymmetryGHex *)CCTK_GHExtension(GH, "Symmetry");
/* Reference the hash table in the GHex and tell it what kind of
symmetry is being applied
(depending on sym and the grid layout)
If there is no symmetry necessary,set ESYM_NOSYM
When we apply a symmetry and find ESYM_UNSET, something went wrong!
*/
#ifdef SYM_DEBUG
printf("SetSymmetry: %s [%d,%d,%d]\n", CCTK_VarName(vi), sym[0], sym[1],
sym[2]);
#endif
DecodeSymParameters3D(domainsym);
for (dir = 0; dir < MAX_FACE; ++dir) {
if (domainsym[dir] == GFSYM_REFLECTION) {
sGHex->GFSym[vi][dir] = sym[dir / 2];
} else if (domainsym[dir] == GFSYM_ROTATION_X) {
sGHex->GFSym[vi][dir] = sym[1] * sym[2];
} else if (domainsym[dir] == GFSYM_ROTATION_Y) {
sGHex->GFSym[vi][dir] = sym[0] * sym[2];
} else if (domainsym[dir] == GFSYM_ROTATION_Z) {
sGHex->GFSym[vi][dir] = sym[0] * sym[1];
} else {
sGHex->GFSym[vi][dir] = GFSYM_NOSYM;
}
}
#ifdef SYM_DEBUG
printf("SetSymmetry: %s [%d,%d,%d]\n\n", CCTK_VarName(vi),
sGHex->GFSym[vi][0], sGHex->GFSym[vi][2], sGHex->GFSym[vi][4]);
#endif
return (0);
}
void CCTK_FCALL CCTK_FNAME(SetCartSymVI)(int *ierr, const cGH **GH,
const int *sym, const int *vi) {
*ierr = SetCartSymVI(*GH, sym, *vi);
}
/*@@
@routine SetCartSymVN
@date Thu May 11 13:32:55 2000
@author Gerd Lanfermann
@desc
Applies symmetry boundary conditions from
variable index
@enddesc
@@*/
int SetCartSymVN(const cGH *GH, const int *sym, const char *vn) {
int vi, retval;
vi = CCTK_VarIndex(vn);
if (vi >= 0) {
retval = SetCartSymVI(GH, sym, vi);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Unknown variable '%s' in SetCartSymVN", vn);
retval = -1;
}
return (retval);
}
void CCTK_FCALL CCTK_FNAME(SetCartSymVN)(int *ierr, const cGH **GH,
const int *sym, ONE_FORTSTRING_ARG) {
ONE_FORTSTRING_CREATE(vn)
*ierr = SetCartSymVN(*GH, sym, vn);
free(vn);
}
/*@@
@routine SetCartSymGI
@date
@author Gerd Lanfermann
@desc
Applies symmetry boundary conditions from
Group index
@enddesc
@@*/
int SetCartSymGI(const cGH *GH, const int *sym, int gi) {
int domainsym[MAX_FACE];
SymmetryGHex *sGHex;
int first_vari, numvars, vi;
int dir;
DECLARE_CCTK_PARAMETERS
sGHex = (SymmetryGHex *)CCTK_GHExtension(GH, "Symmetry");
first_vari = CCTK_FirstVarIndexI(gi);
numvars = CCTK_NumVarsInGroupI(gi);
if (first_vari < 0) {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Cannot find group %s (grp.index: %d) in SetCartSymGI",
CCTK_GroupName(gi), first_vari);
return (-1);
}
/* Reference the hash table in the GHex and tell it what kind of
symmetry is being applied
(depending on sym and the grid layout)
If there is no symmetry necessary,set ESYM_NOSYM
When we apply a symmetry and find ESYM_UNSET, something went wrong!
*/
for (vi = first_vari; vi < first_vari + numvars; vi++) {
#ifdef SYM_DEBUG
printf("SetSymmetry: %s [%d,%d,%d]\n", CCTK_VarName(vi), sym[0], sym[1],
sym[2]);
#endif
DecodeSymParameters3D(domainsym);
for (dir = 0; dir < MAX_FACE; dir++) {
if (domainsym[dir] == GFSYM_REFLECTION) {
sGHex->GFSym[vi][dir] = sym[dir / 2];
} else if (domainsym[dir] == GFSYM_ROTATION_X) {
sGHex->GFSym[vi][dir] = sym[1] * sym[2];
} else if (domainsym[dir] == GFSYM_ROTATION_Y) {
sGHex->GFSym[vi][dir] = sym[0] * sym[2];
} else if (domainsym[dir] == GFSYM_ROTATION_Z) {
sGHex->GFSym[vi][dir] = sym[0] * sym[1];
} else {
sGHex->GFSym[vi][dir] = GFSYM_NOSYM;
}
}
#ifdef SYM_DEBUG
printf("SetSymmetry: %s [%d,%d,%d]\n\n", CCTK_VarName(vi),
sGHex->GFSym[vi][0], sGHex->GFSym[vi][2], sGHex->GFSym[vi][4]);
#endif
}
return (0);
}
void CCTK_FCALL CCTK_FNAME(SetCartSymGI)(int *ierr, const cGH **GH,
const int *sym, const int *gi) {
*ierr = SetCartSymGI(*GH, sym, *gi);
}
/*@@
@routine
@date
@author
@desc
Applies symmetry boundary conditions from
"Implementation::Groupname"
@enddesc
@@*/
int SetCartSymGN(const cGH *GH, const int *sym, const char *gn) {
int gi, retval;
gi = CCTK_GroupIndex(gn);
if (gi >= 0) {
retval = SetCartSymGI(GH, sym, gi);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Unknown group '%s' in SetCartSymGN", gn);
retval = -1;
}
return (retval);
}
void CCTK_FCALL CCTK_FNAME(SetCartSymGN)(int *ierr, const cGH **GH,
const int *sym, ONE_FORTSTRING_ARG) {
ONE_FORTSTRING_CREATE(gn)
*ierr = SetCartSymGN(*GH, sym, gn);
free(gn);
}
/*@@
@file Startup.c
@date Mon Mar 15 15:48:42 1999
@author Gerd Lanfermann
@desc
Startup file to register the GHextension and coordinates
@enddesc
@version $Id$
@@*/
#include <stdlib.h>
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
#include "util_Table.h"
#include "CoordBase.h"
#include "Symmetry.h"
/* the rcs ID and its dummy function to use it */
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_Startup_c);
/********************************************************************
******************** External Prototypes **********************
********************************************************************/
int SymmetryStartup(void);
void RegisterCartGrid3DCoords(CCTK_ARGUMENTS);
/********************************************************************
******************** Internal Prototypes **********************
********************************************************************/
static void *SetupGH(tFleshConfig *config, int convlevel, cGH *GH);
/********************************************************************
******************** External Routines ************************
********************************************************************/
/*@@
@routine SymmetryStartup
@date Mon Mar 15 15:49:16 1999
@author Gerd Lanfermann
@desc
Routine registers the GH extension for CartGrid3D
along with its setup routine.
@enddesc
@calls CCTK_RegisterGHExtension
CCTK_RegisterGHExtensionSetupGH
@history
@endhistory
@returntype void
@@*/
int SymmetryStartup(void) {
CCTK_RegisterGHExtensionSetupGH(CCTK_RegisterGHExtension("Symmetry"),
SetupGH);
return 0;
}
/*@@
@routine RegisterCartGrid3DCoords
@date
@author Gabrielle Allen
@desc
Routine registers the coordinates provided by
CartGrid3D, using both the new and old APIs. The old
CCTK_ API is deprecated.
@enddesc
@calls CCTK_CoordRegisterSystem
CCTK_CoordRegisterData
@returntype int
@returndesc
0 for success, or negative in case of errors
@endreturndesc
@@*/
void RegisterCartGrid3DCoords(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS;
DECLARE_CCTK_PARAMETERS;
int ierr, coord_system_handle;
/* Register coordinate systems */
ierr = Coord_SystemRegister(cctkGH, 3, "cart3d");
ierr += Coord_SystemRegister(cctkGH, 2, "cart2d");
ierr += Coord_SystemRegister(cctkGH, 1, "cart1d");
if (ierr < 0) {
CCTK_WARN(0, "Error registering cartnd coordinate systems");
} else {
/* Register coordinates for cart3d */
coord_system_handle = Coord_SystemHandle(cctkGH, "cart3d");
if (coord_system_handle < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Error obtaining system handle for cart3d");
}
ierr = Coord_CoordRegister(cctkGH, coord_system_handle, 1, "x");
ierr += Coord_CoordRegister(cctkGH, coord_system_handle, 2, "y");
ierr += Coord_CoordRegister(cctkGH, coord_system_handle, 3, "z");
if (ierr < 0) {
CCTK_WARN(0, "Error registering cart3d coordinates");
}
/* Fill out rest of coordinate system table for cart3d */
ierr = Util_TableSetString(coord_system_handle, "uniform", "TYPE");
if (ierr < 0) {
CCTK_WARN(1, "Error registering cart3d type");
}
/* Register coordinates for cart2d */
coord_system_handle = Coord_SystemHandle(cctkGH, "cart2d");
if (coord_system_handle < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Error obtaining system handle for cart2d");
}
ierr = Coord_CoordRegister(cctkGH, coord_system_handle, 1, "x");
ierr += Coord_CoordRegister(cctkGH, coord_system_handle, 2, "y");
if (ierr < 0) {
CCTK_WARN(0, "Error registering cart2d coordinates");
}
/* Fill out rest of coordinate system table for cart2d */
ierr = Util_TableSetString(coord_system_handle, "uniform", "TYPE");
if (ierr < 0) {
CCTK_WARN(1, "Error registering cart2d type");
}
/* Register coordinate for cart1d */
coord_system_handle = Coord_SystemHandle(cctkGH, "cart1d");
if (coord_system_handle < 0) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Error obtaining system handle for cart1d");
}
ierr = Coord_CoordRegister(cctkGH, coord_system_handle, 1, "x");
if (ierr < 0) {
CCTK_WARN(0, "Error registering cart1d coordinate");
}
/* Fill out rest of coordinate system table for cart1d */
ierr = Util_TableSetString(coord_system_handle, "uniform", "TYPE");
if (ierr < 0) {
CCTK_WARN(1, "Error registering cart1d type");
}
/* Register cartnd as the default coordinate systems */
if (register_default_coordinate_systems) {
ierr = Coord_SetDefaultSystem(cctkGH, "cart3d");
ierr += Coord_SetDefaultSystem(cctkGH, "cart2d");
ierr += Coord_SetDefaultSystem(cctkGH, "cart1d");
if (ierr < 0) {
CCTK_WARN(1, "Error registering cartnd as default coordinate systems");
}
}
}
/* Register coordinates under the old API */
CCTK_CoordRegisterSystem(3, "cart3d");
CCTK_CoordRegisterSystem(3, "spher3d");
if (CCTK_CoordRegisterData(1, "grid::x", "x", "cart3d") < 0) {
CCTK_WARN(1, "Problem with registering coordinate x");
}
if (CCTK_CoordRegisterData(2, "grid::y", "y", "cart3d") < 0) {
CCTK_WARN(1, "Problem with registering coordinate y");
}
if (CCTK_CoordRegisterData(3, "grid::z", "z", "cart3d") < 0) {
CCTK_WARN(1, "Problem with registering coordinate z");
}
if (CCTK_CoordRegisterData(1, "grid::r", "r", "spher3d") < 0) {
CCTK_WARN(1, "Problem with registering coordinate r");
}
}
/********************************************************************
******************** Internal Routines ************************
********************************************************************/
static void *SetupGH(tFleshConfig *config, int convlevel, cGH *GH) {
int i, j, maxdim, numvars;
SymmetryGHex *myGH;
/* avoid compiler warnings about unused arguments */
(void)(config + 0);
(void)(convlevel + 0);
(void)(GH + 0);
maxdim = CCTK_MaxDim();
numvars = CCTK_NumVars();
/* allocate the GH extension */
myGH = (SymmetryGHex *)malloc(sizeof(SymmetryGHex));
if (myGH) {
/* allocation for the number of grid functions */
myGH->GFSym = (int **)malloc(numvars * sizeof(int *));
/* allocation for the number of dimensions*/
for (i = 0; i < numvars; i++) {
myGH->GFSym[i] = (int *)malloc(2 * maxdim * sizeof(int));
for (j = 0; j < 2 * maxdim; j++) {
myGH->GFSym[i][j] = GFSYM_UNSET; /* not set */
}
}
}
return (myGH);
}
/*@@
@file SymmetryWrappers.c
@date April 2000
@author Gerd Lanfermann
@desc
Routines to apply the 1/2/3D Symmetries for
all symmetry domains (octant/bitant/quadrant).
@enddesc
@history
@hdate Sat 02 Nov 2002
@hauthor Thomas Radke
@hdesc routines generalized for applying to arbitrary CCTK data types
@endhistory
@version $Id$
@@*/
#include <stdlib.h>
#include "cctk.h"
#include "cctk_Arguments.h"
#include "cctk_Parameters.h"
#include "Symmetry.h"
/* the rcs ID and its dummy function to use it */
static const char *rcsid = "$Header$";
CCTK_FILEVERSION(CactusBase_CartGrid3D_Symmetry_c)
/********************************************************************
********************* Local Routine Prototypes *********************
********************************************************************/
static int ApplySymmetry(const cGH *GH, int gindex, int first_vindex,
int numvars);
/********************************************************************
******************* Fortran Wrapper Prototypes *********************
********************************************************************/
void CCTK_FCALL CCTK_FNAME(CartSymGI)(int *ierr, const cGH **GH, int *gindex);
void CCTK_FCALL
CCTK_FNAME(CartSymGN)(int *ierr, const cGH **GH, ONE_FORTSTRING_ARG);
void CCTK_FCALL CCTK_FNAME(CartSymVI)(int *ierr, const cGH **GH, int *vindex);
void CCTK_FCALL
CCTK_FNAME(CartSymVN)(int *ierr, const cGH **GH, ONE_FORTSTRING_ARG);
/********************************************************************
****************** External Routine Prototypes *********************
********************************************************************/
void DecodeSymParameters3D(int sym[6]);
void CartGrid3D_ApplyBC(CCTK_ARGUMENTS);
/*@@
@routine CartSymGI
@date April 2000
@author Gerd Lanfermann
@desc
Apply symmetry boundary routines by group index
@enddesc
@calls ApplySymmetry
@var GH
@vdesc Pointer to CCTK grid hierarchy
@vtype const cGH *
@vio in
@endvar
@var gindex
@vdesc index of group to apply symmetry BC
@vtype int
@vio in
@endvar
@returntype int
@returndesc
return code of @seeroutine ApplySymmetry <BR>
-1 if invalid group index was given
@endreturndesc
@@*/
int CartSymGI(const cGH *GH, int gindex) {
int numvars, first_vindex, retval;
numvars = CCTK_NumVarsInGroupI(gindex);
first_vindex = CCTK_FirstVarIndexI(gindex);
if (numvars > 0 && first_vindex >= 0) {
char *groupname = CCTK_GroupName(gindex);
if (!groupname)
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error returned from function CCTK_GroupName");
CCTK_VWarn(3, __LINE__, __FILE__, CCTK_THORNSTRING,
"You should not call the symmetry boundary condition routines "
"for the group \"%s\" through the CartSym* routines any more. "
"The symmetry boundary conditions are now applied automatically "
"when a physical boundary condition is applied.",
groupname);
free(groupname);
retval = ApplySymmetry(GH, gindex, first_vindex, numvars);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid group index %d in CartSymGI", gindex);
retval = -1;
}
return (retval);
}
void CCTK_FCALL CCTK_FNAME(CartSymGI)(int *ierr, const cGH **GH, int *gindex) {
*ierr = CartSymGI(*GH, *gindex);
}
/*@@
@routine CartSymGN
@date April 2000
@author Gerd Lanfermann
@desc
Apply symmetry boundary routines by group name
@enddesc
@calls ApplySymmetry
@var GH
@vdesc Pointer to CCTK grid hierarchy
@vtype const cGH *
@vio in
@endvar
@var gname
@vdesc name of group to apply symmetry BC
@vtype const char *
@vio in
@endvar
@returntype int
@returndesc
return code of @seeroutine ApplySymmetry <BR>
-1 if invalid group name was given
@endreturndesc
@@*/
int CartSymGN(const cGH *GH, const char *gname) {
int gindex, retval;
gindex = CCTK_GroupIndex(gname);
if (gindex >= 0) {
retval = CartSymGI(GH, gindex);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid group name '%s' in CartSymGN", gname);
retval = -1;
}
return (retval);
}
void CCTK_FCALL
CCTK_FNAME(CartSymGN)(int *ierr, const cGH **GH, ONE_FORTSTRING_ARG) {
ONE_FORTSTRING_CREATE(gname)
*ierr = CartSymGN(*GH, gname);
free(gname);
}
/*@@
@routine CartSymVI
@date April 2000
@author Gerd Lanfermann
@desc
Apply symmetry boundary routines by variable index
@enddesc
@calls ApplySymmetry
@var GH
@vdesc Pointer to CCTK grid hierarchy
@vtype const cGH *
@vio in
@endvar
@var gindex
@vdesc index of variable to apply symmetry BC
@vtype int
@vio in
@endvar
@returntype int
@returndesc
return code of @seeroutine ApplySymmetry <BR>
-1 if invalid variable index was given
@endreturndesc
@@*/
int CartSymVI(const cGH *GH, int vindex) {
int retval, gindex;
gindex = CCTK_GroupIndexFromVarI(vindex);
if (gindex >= 0) {
char *fullname = CCTK_FullName(vindex);
if (!fullname)
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error returned from function CCTK_FullName");
CCTK_VWarn(3, __LINE__, __FILE__, CCTK_THORNSTRING,
"You should not call the symmetry boundary condition routines "
"for the variable \"%s\" through the CartSym* routines any "
"more. The symmetry boundary conditions are now applied "
"automatically when a physical boundary condition is applied.",
fullname);
free(fullname);
retval = ApplySymmetry(GH, gindex, vindex, 1);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid variable index %d in CartSymVI", vindex);
retval = -1;
}
return (retval);
}
void CCTK_FCALL CCTK_FNAME(CartSymVI)(int *ierr, const cGH **GH, int *vindex) {
*ierr = CartSymVI(*GH, *vindex);
}
/*@@
@routine CartSymVN
@date April 2000
@author Gerd Lanfermann
@desc
Apply symmetry boundary routines by variable name
@enddesc
@calls ApplySymmetry
@var GH
@vdesc Pointer to CCTK grid hierarchy
@vtype const cGH *
@vio in
@endvar
@var gname
@vdesc name of variable to apply symmetry BC
@vtype const char *
@vio in
@endvar
@returntype int
@returndesc
return code of @seeroutine ApplySymmetry <BR>
-1 if invalid variable name was given
@endreturndesc
@@*/
int CartSymVN(const cGH *GH, const char *vname) {
int vindex, retval;
vindex = CCTK_VarIndex(vname);
if (vindex >= 0) {
retval = CartSymVI(GH, vindex);
} else {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Invalid variable name '%s' in CartSymVN", vname);
retval = -1;
}
return (retval);
}
void CCTK_FCALL
CCTK_FNAME(CartSymVN)(int *ierr, const cGH **GH, ONE_FORTSTRING_ARG) {
ONE_FORTSTRING_CREATE(vname)
*ierr = CartSymVN(*GH, vname);
free(vname);
}
/********************************************************************
********************* Local Routines *************************
********************************************************************/
/* macro to compute the linear index of a 3D point */
#define INDEX_3D(ash, i, j, k) ((i) + (ash)[0] * ((j) + (ash)[1] * (k)))
/*@@
@routine SYMMETRY_BOUNDARY
@date Sat 02 Nov 2002
@author Thomas Radke
@desc
Macro to apply symmetry boundary conditions to a variable
of given datatype
Currently it is limited up to 3D variables only.
@enddesc
@var cctk_type
@vdesc CCTK datatype of the variable
@vtype <cctk_type>
@vio in
@endvar
@var itype
@vdesc integral CCTK datatype of the variable (used for typecasting)
@vtype <cctk_type>
@vio in
@endvar
@@*/
#define APPLY_LOWER(dir, ii, jj, kk, jjend, kkend, iii, jjj, kkk, itype) \
{ \
for (kk = 0; kk < kkend; kk++) { \
for (jj = 0; jj < jjend; jj++) { \
for (ii = 0; ii < gdata.nghostzones[dir / 2]; ii++) { \
_var[INDEX_3D(ash, i, j, k)] = (itype)( \
GFSym[vindex][dir] * _var[INDEX_3D(ash, iii, jjj, kkk)]); \
} \
} \
} \
}
#define APPLY_UPPER(dir, ii, jj, kk, jjend, kkend, iii, jjj, kkk, itype) \
{ \
for (kk = 0; kk < kkend; kk++) { \
for (jj = 0; jj < jjend; jj++) { \
for (ii = lsh[dir / 2] - gdata.nghostzones[dir / 2]; \
ii < lsh[dir / 2]; ii++) { \
_var[INDEX_3D(ash, i, j, k)] = (itype)( \
GFSym[vindex][dir] * _var[INDEX_3D(ash, iii, jjj, kkk)]); \
} \
} \
} \
}
#define SYMMETRY_BOUNDARY(cctk_type, itype) \
{ \
cctk_type *_var = GH->data[vindex][0]; \
\
switch (group_static_data.dim) { \
case 3: \
/* apply symmetry to the z faces */ \
if (doSym[4] == GFSYM_REFLECTION) { \
APPLY_LOWER(4, k, j, i, lsh[1], lsh[0], i, j, offset[4] - k, itype); \
} \
if (doSym[5] == GFSYM_REFLECTION) { \
APPLY_UPPER(5, k, j, i, lsh[1], lsh[0], i, j, offset[5] - k, itype); \
} \
if (doSym[4] == GFSYM_ROTATION_X) { \
APPLY_LOWER(4, k, j, i, lsh[1], lsh[0], i, lsh[1] - j - 1, \
offset[4] - k, itype); \
} \
if (doSym[5] == GFSYM_ROTATION_X) { \
APPLY_UPPER(5, k, j, i, lsh[1], lsh[0], i, lsh[1] - j - 1, \
offset[5] - k, itype); \
} \
if (doSym[4] == GFSYM_ROTATION_Y) { \
APPLY_LOWER(4, k, j, i, lsh[1], lsh[0], lsh[0] - i - 1, j, \
offset[4] - k, itype); \
} \
if (doSym[5] == GFSYM_ROTATION_Y) { \
APPLY_UPPER(5, k, j, i, lsh[1], lsh[0], lsh[0] - i - 1, j, \
offset[5] - k, itype); \
} \
/* FALL THROUGH */ \
case 2: \
/* apply symmetry to the y faces */ \
if (doSym[2] == GFSYM_REFLECTION) { \
APPLY_LOWER(2, j, k, i, lsh[2], lsh[0], i, offset[2] - j, k, itype); \
} \
if (doSym[3] == GFSYM_REFLECTION) { \
APPLY_UPPER(3, j, k, i, lsh[2], lsh[0], i, offset[3] - j, k, itype); \
} \
if (doSym[2] == GFSYM_ROTATION_Z) { \
APPLY_LOWER(2, j, k, i, lsh[2], lsh[0], lsh[0] - i - 1, offset[2] - j, \
k, itype); \
} \
if (doSym[3] == GFSYM_ROTATION_Z) { \
APPLY_UPPER(3, j, k, i, lsh[2], lsh[0], lsh[0] - i - 1, offset[3] - j, \
k, itype); \
} \
if (group_static_data.dim > 2) { \
if (doSym[2] == GFSYM_ROTATION_X) { \
APPLY_LOWER(2, j, k, i, lsh[2], lsh[0], i, offset[2] - j, \
lsh[2] - k - 1, itype); \
} \
if (doSym[3] == GFSYM_ROTATION_X) { \
APPLY_UPPER(3, j, k, i, lsh[2], lsh[0], i, offset[3] - j, \
lsh[2] - k - 1, itype); \
} \
} \
/* FALL THROUGH */ \
case 1: \
/* apply symmetry to the x faces */ \
if (doSym[0] == GFSYM_REFLECTION) { \
APPLY_LOWER(0, i, j, k, lsh[1], lsh[2], offset[0] - i, j, k, itype); \
} \
if (doSym[1] == GFSYM_REFLECTION) { \
APPLY_UPPER(1, i, j, k, lsh[1], lsh[2], offset[1] - i, j, k, itype); \
} \
if (group_static_data.dim > 1) { \
if (doSym[0] == GFSYM_ROTATION_Z) { \
APPLY_LOWER(0, i, j, k, lsh[1], lsh[2], offset[0] - i, \
lsh[1] - j - 1, k, itype); \
} \
if (doSym[1] == GFSYM_ROTATION_Z) { \
APPLY_UPPER(1, i, j, k, lsh[1], lsh[2], offset[1] - i, \
lsh[1] - j - 1, k, itype); \
} \
} \
if (group_static_data.dim > 2) { \
if (doSym[0] == GFSYM_ROTATION_Y) { \
APPLY_LOWER(0, i, j, k, lsh[1], lsh[2], offset[0] - i, j, \
lsh[2] - k - 1, itype); \
} \
if (doSym[1] == GFSYM_ROTATION_Y) { \
APPLY_UPPER(1, i, j, k, lsh[1], lsh[2], offset[1] - i, j, \
lsh[2] - k - 1, itype); \
} \
} \
/* FALL THROUGH */ \
default: \
; \
} \
}
/* Function to apply above macros. */
#define SYMMETRY_FUNCTION(cctk_type, integral_type) \
static void cctk_type##_SymBC( \
const cGH *GH, const int vindex, const int *doSym, const int *offset, \
const int *lsh, const int *ash, const cGroup group_static_data, \
const cGroupDynamicData gdata, int **GFSym) { \
int i, j, k; \
SYMMETRY_BOUNDARY(cctk_type, integral_type); \
}
/* Create functions to apply macros.
* This is much easier for the optiser to deal with.
* E.g. on some machines we can't compile this file if we use the macros
* directly in the switch statement in ApplySymmetry.
*/
SYMMETRY_FUNCTION(CCTK_COMPLEX, CCTK_REAL)
#ifdef HAVE_CCTK_COMPLEX8
SYMMETRY_FUNCTION(CCTK_COMPLEX8, CCTK_REAL4)
#endif
#ifdef HAVE_CCTK_COMPLEX16
SYMMETRY_FUNCTION(CCTK_COMPLEX16, CCTK_REAL8)
#endif
#ifdef HAVE_CCTK_COMPLEX32
SYMMETRY_FUNCTION(CCTK_COMPLEX32, CCTK_REAL16)
#endif
SYMMETRY_FUNCTION(CCTK_BYTE, CCTK_BYTE)
SYMMETRY_FUNCTION(CCTK_INT, CCTK_INT)
#ifdef HAVE_CCTK_INT1
SYMMETRY_FUNCTION(CCTK_INT1, CCTK_INT1)
#endif
#ifdef HAVE_CCTK_INT2
SYMMETRY_FUNCTION(CCTK_INT2, CCTK_INT2)
#endif
#ifdef HAVE_CCTK_INT4
SYMMETRY_FUNCTION(CCTK_INT4, CCTK_INT4)
#endif
#ifdef HAVE_CCTK_INT8
SYMMETRY_FUNCTION(CCTK_INT8, CCTK_INT8)
#endif
#ifdef HAVE_CCTK_INT16
SYMMETRY_FUNCTION(CCTK_INT16, CCTK_INT16)
#endif
SYMMETRY_FUNCTION(CCTK_REAL, CCTK_REAL)
#ifdef HAVE_CCTK_REAL4
SYMMETRY_FUNCTION(CCTK_REAL4, CCTK_REAL4)
#endif
#ifdef HAVE_CCTK_REAL8
SYMMETRY_FUNCTION(CCTK_REAL8, CCTK_REAL8)
#endif
#ifdef HAVE_CCTK_REAL16
SYMMETRY_FUNCTION(CCTK_REAL16, CCTK_REAL16)
#endif
#define CALL_SYMBC(cctk_type) \
cctk_type##_SymBC(GH, vindex, doSym, offset, lsh, ash, group_static_data, \
gdata, GFSym)
/*@@
@routine ApplySymmetry
@date Thu Mar 2 11:02:10 2000
@author Gerd Lanfermann
@desc
Apply symmetry boundary conditions to a group of grid variables
This routine is called by the various CartSymXXX wrappers.
@enddesc
@var GH
@vdesc Pointer to CCTK grid hierarchy
@vtype const cGH *
@vio in
@endvar
@var gindex
@vdesc group index of the variables to apply symmetry BCs
@vtype int
@vio in
@endvar
@var first_var
@vdesc index of first variable to apply symmetry BCs
@vtype int
@vio in
@endvar
@var num_vars
@vdesc number of variables
@vtype int
@vio in
@endvar
@calls CCTK_GroupData
CCTK_GroupDynamicData
SYMMETRY_BOUNDARY
@history
@hdate Sat 02 Nov 2002
@hauthor Thomas Radke
@hdesc Merged separate routines for 1D, 2D, and 3D
into a single generic routine
@endhistory
@returntype int
@returndesc
0 for success, or<BR>
-1 if group dimension is not supported<BR>
-2 if group datatype is not supported
@endreturndesc
@@*/
static int ApplySymmetry(const cGH *GH, int gindex, int first_vindex,
int numvars) {
int i, dim, vindex, retval;
int **GFSym;
int domainsym[2 * MAX_DIM], doSym[2 * MAX_DIM], offset[2 * MAX_DIM];
int lsh[MAX_DIM], ash[MAX_DIM], cntstag[MAX_DIM];
cGroup group_static_data;
cGroupDynamicData gdata;
DECLARE_CCTK_PARAMETERS
DecodeSymParameters3D(domainsym);
/* check if any symmetries are to be applied */
for (i = 0; i < 2 * MAX_DIM; i++) {
if (domainsym[i]) {
break;
}
}
if (i == 2 * MAX_DIM) {
return (0);
}
/* get the group's static and dynamic data structure */
CCTK_GroupData(gindex, &group_static_data);
CCTK_GroupDynamicData(GH, gindex, &gdata);
if (group_static_data.dim <= 0 || group_static_data.dim > MAX_DIM) {
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"ApplySymmetry: group dimension must 1, 2, or 3");
return (-1);
}
/* Avoid origin? Default is yes */
cntstag[0] = no_origin && no_originx && avoid_origin && avoid_originx;
cntstag[1] = no_origin && no_originy && avoid_origin && avoid_originy;
cntstag[2] = no_origin && no_originz && avoid_origin && avoid_originz;
/* initialize array for variables with less dimensions than MAX_DIM
so that we can use the INDEX_3D macro later on */
for (i = 0; i < MAX_DIM; i++) {
if (i < group_static_data.dim) {
lsh[i] = gdata.lsh[i];
ash[i] = gdata.ash[i];
} else {
lsh[i] = 1;
ash[i] = 1;
}
offset[2 * i + 0] = 2 * gdata.nghostzones[i] - cntstag[i];
offset[2 * i + 1] = 2 * (lsh[i] - 1) - offset[2 * i + 0];
}
GFSym = ((SymmetryGHex *)CCTK_GHExtension(GH, "Symmetry"))->GFSym;
/* Apply Symmetries if:
+ the Symmetry is activated (== NOT NOSYM)
+ the Symmetry is set (== NOT UNSET)
+ the length in the direction is more than 1 grid point
+ the processor has a lower/upper physical boundary.
Whether a grid allows a symmetry along a direction (e.g. octant=all)
is part if the Symmetry Setup process.
*/
retval = 0;
for (vindex = first_vindex; vindex < first_vindex + numvars; vindex++) {
for (dim = 0; dim < 2 * group_static_data.dim; dim++) {
if (GFSym[vindex][dim] == GFSYM_UNSET) {
CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
"Symmetries unspecified for '%s'", CCTK_VarName(vindex));
}
doSym[dim] = (GFSym[vindex][dim] != GFSYM_NOSYM &&
GFSym[vindex][dim] != GFSYM_UNSET && lsh[dim / 2] > 1 &&
GH->cctk_bbox[dim])
? domainsym[dim]
: 0;
}
switch (group_static_data.vartype) {
case CCTK_VARIABLE_BYTE:
CALL_SYMBC(CCTK_BYTE);
break;
case CCTK_VARIABLE_INT:
CALL_SYMBC(CCTK_INT);
break;
case CCTK_VARIABLE_REAL:
CALL_SYMBC(CCTK_REAL);
break;
case CCTK_VARIABLE_COMPLEX:
CALL_SYMBC(CCTK_COMPLEX);
break;
#ifdef HAVE_CCTK_INT1
case CCTK_VARIABLE_INT1:
CALL_SYMBC(CCTK_INT1);
break;
#endif
#ifdef HAVE_CCTK_INT2
case CCTK_VARIABLE_INT2:
CALL_SYMBC(CCTK_INT2);
break;
#endif
#ifdef HAVE_CCTK_INT4
case CCTK_VARIABLE_INT4:
CALL_SYMBC(CCTK_INT4);
break;
#endif
#ifdef HAVE_CCTK_INT8
case CCTK_VARIABLE_INT8:
CALL_SYMBC(CCTK_INT8);
break;
#endif
#ifdef HAVE_CCTK_INT16
case CCTK_VARIABLE_INT16:
CALL_SYMBC(CCTK_INT16);
break;
#endif
#ifdef HAVE_CCTK_REAL4
case CCTK_VARIABLE_REAL4:
CALL_SYMBC(CCTK_REAL4);
break;
case CCTK_VARIABLE_COMPLEX8:
CALL_SYMBC(CCTK_COMPLEX8);
break;
#endif
#ifdef HAVE_CCTK_REAL8
case CCTK_VARIABLE_REAL8:
CALL_SYMBC(CCTK_REAL8);
break;
case CCTK_VARIABLE_COMPLEX16:
CALL_SYMBC(CCTK_COMPLEX16);
break;
#endif
#ifdef HAVE_CCTK_REAL16
case CCTK_VARIABLE_REAL16:
CALL_SYMBC(CCTK_REAL16);
break;
case CCTK_VARIABLE_COMPLEX32:
CALL_SYMBC(CCTK_COMPLEX32);
break;
#endif
default:
CCTK_VWarn(1, __LINE__, __FILE__, CCTK_THORNSTRING,
"Unsupported variable type %d for variable '%s'",
CCTK_VarTypeI(vindex), CCTK_VarName(vindex));
retval = -2;
}
}
return (retval);
}
/*@@
@routine CartGrid3D_ApplyBC
@date Sat Feb 07
@author Erik Schnetter
@desc Apply the symmetry boundary conditions
@enddesc
@@*/
void CartGrid3D_ApplyBC(CCTK_ARGUMENTS) {
DECLARE_CCTK_ARGUMENTS;
int nvars;
CCTK_INT *restrict indices;
CCTK_INT *restrict faces;
CCTK_INT *restrict widths;
CCTK_INT *restrict tables;
int vi;
int gi;
int i;
int ierr;
nvars = Boundary_SelectedGVs(cctkGH, 0, 0, 0, 0, 0, 0);
if (nvars < 0)
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error returned from function Boundary_selectedGVs");
indices = malloc(nvars * sizeof *indices);
if (!(nvars == 0 || indices))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
faces = malloc(nvars * sizeof *faces);
if (!(nvars == 0 || faces))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
widths = malloc(nvars * sizeof *widths);
if (!(nvars == 0 || widths))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
tables = malloc(nvars * sizeof *tables);
if (!(nvars == 0 || tables))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
ierr = Boundary_SelectedGVs(cctkGH, nvars, indices, faces, widths, tables, 0);
if (!(ierr == nvars))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
for (i = 0; i < nvars; ++i) {
vi = indices[i];
if (!(vi >= 0 && vi < CCTK_NumVars()))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
gi = CCTK_GroupIndexFromVarI(vi);
if ((gi < 0))
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
ierr = ApplySymmetry(cctkGH, gi, vi, 1);
if (ierr)
CCTK_VWarn(0, __LINE__, __FILE__, "CartGrid3D",
"error in function CartGrid3D_ApplyBC");
}
free(indices);
free(faces);
free(widths);
free(tables);
}
/*@@
@header Symmetry.h
@date Sun 7th Mar 1999
@author Gerd Lanfermann
@desc
The extensions to the GH structure for 3D grid symmetry treatment.
We'll have six int array for every GF, which holds a flag
for which symmetry or (physical) bnd-condition to apply
at the grid faces.
* These tables are set by SetSymmetry(GF,int,int,int)
during initialization.
* Default values ?
* The information is used during evolution
by Einstein_DoBound(GF), Einstein_DoSym(GF).
@enddesc
@version $Header$
@@*/
#ifndef _SYMMETRY_H_
#define _SYMMETRY_H_ 1
#include "cctk.h"
#define GFSYM_UNKNOWN 0
#define GFSYM_UNSET -41
#define GFSYM_NOSYM -42
#define GFSYM_REFLECTION 1
#define GFSYM_ROTATION_X 2
#define GFSYM_ROTATION_Y 3
#define GFSYM_ROTATION_Z 4
#define MAX_DIM 3
#define MAX_FACE 6
typedef struct Symmetry {
/* Symmetry[0..GF-1][0..dim-1] */
/* in each direction [0,..dim-1], this will hold the symmetry
operation across that plane, iff the grid layout requires this.
this compares to the {sx,sy,sz} of Cactus3.2 */
int **GFSym;
} SymmetryGHex;
#ifdef __cplusplus
extern "C" {
#endif
int GetCartSymVI(const cGH *GH, int *sym, int varindexi);
int GetCartSymVN(const cGH *GH, int *sym, const char *varname);
int SetCartSymVI(const cGH *GH, const int *sym, int varindex);
int SetCartSymGI(const cGH *GH, const int *sym, int groupindex);
int SetCartSymVN(const cGH *GH, const int *sym, const char *varname);
int SetCartSymGN(const cGH *GH, const int *sym, const char *groupname);
int CartSymVI(const cGH *GH, int varindex);
int CartSymGI(const cGH *GH, int groupindexi);
int CartSymVN(const cGH *GH, const char *varname);
int CartSymGN(const cGH *GH, const char *groupname);
#ifdef __cplusplus
}
#endif
#endif /* _SYMMETRY_H_ */
# Main make.code.defn file for thorn CartGrid3D
# $Header$
# Source files in this directory
SRCS = Startup.c ParamCheck.c DecodeSymParameters.c CartGrid3D.c \
GetSymmetry.c SetSymmetry.c Symmetry.c RegisterSymmetries.c