aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README16
-rw-r--r--doc/documentation.tex529
-rw-r--r--doc/space_mask.eps203
-rw-r--r--doc/space_mask.fig68
-rw-r--r--interface.ccl17
-rw-r--r--schedule.ccl27
-rw-r--r--src/MaskInit.c94
-rw-r--r--src/MaskUtils.c496
-rw-r--r--src/SpaceMask.h113
-rw-r--r--src/make.code.defn2
10 files changed, 1521 insertions, 44 deletions
diff --git a/README b/README
index c52699d..2a6a2c5 100644
--- a/README
+++ b/README
@@ -1,19 +1,9 @@
Cactus Code Thorn SpaceMask
-Authors : Tom Goodale
+Authors : Denis Pollney
CVS info : $Header$
--------------------------------------------------------------------------
Purpose of the thorn:
-This will provide two integer grid functions
-
-space_mask
-space_table_field
-
-the first one will be a bitmask describing the point, with one bit
-indicating that there is extra data in a table the handle of which can be
-found in the corresponding point in the space_table_field.
-
-Thorns interested in the mask should inherit from this implementation.
-
-There may also be aliased query functions provided.
+Provides utilities for assigning states to individual grid points
+using a mask grid function.
diff --git a/doc/documentation.tex b/doc/documentation.tex
index 5376ec6..33cad43 100644
--- a/doc/documentation.tex
+++ b/doc/documentation.tex
@@ -8,8 +8,8 @@
\begin{document}
-\title{SpaceMask}
-\author{Tom Goodale}
+\title{Using SpaceMask}
+\author{Denis Pollney}
\date{$ $Date$ $}
\maketitle
@@ -18,25 +18,528 @@
% START CACTUS THORNGUIDE
\begin{abstract}
-Provides a mask function for the spatial slice variables
+The SpaceMask thorn provides a grid function which can be used to
+store user-defined states at each grid point. Routines are provided
+for quickly setting and checking the mask states.
\end{abstract}
-\section{Purpose}
+\section{The mask bit-field}
-This will provide two integer grid functions
+The mask is a grid function which can be used to assign a state to
+each point on the grid. It is used as a bit field, with different
+bits, or combinations of bits, assigned to represent various states.
+The mask is currently implemented as a CCTK\_INT8 grid function,
+providing 64 bits per point. Appropriate numbers of bits within
+the mask can be allocated to represent individual states of
+a given type.
-space\_mask
-space\_table\_field
+For instance, a programmer wants to record whether each point of the
+grid has \emph{state} ``interior'', ``excised'' or ``boundary''. The
+collection of these states is called a \emph{type}, and 2-bits of the
+mask (enough to represent the three possible states of the type) are
+allocated to hold this information. If an independent classification
+of points (ie. a new type) is required, bits are allocated to it from
+the remaining free bits in the mask. (See Figure \ref{fig:mask_bits}.)
-the first one will be a bitmask describing the point, with one bit
-indicating that there is extra data in a table the handle of which can be
-found in the corresponding point in the space\_table\_field.
+The SpaceMask thorn provides a set of routines for allocating bits
+within the mask, and for setting and checking the mask state at
+individual points.
-Thorns interested in the mask should inherit from this implementation.
+\begin{figure}
+ \centering
+ \includegraphics{space_mask.eps}
+ \caption{The \texttt{SpaceMask\_RegisterType()} function allocates
+ bits of the mask to a new ``type'' (eg. ``excision'' and ``colour''
+ in the figure). The number of bits that are allocated is determined
+ by the number of possible states of the given type.}
+ \label{fig:mask_bits}
+\end{figure}
-There may also be aliased query functions provided.
+\section{Using the mask}
-\section{Comments}
+A number of functions are provided for registering new types, and
+checking and setting mask values at a point. The interface to these
+functions differs slightly for C and Fortran90 code.
+
+\subsection{Accessing the mask from C Code}
+
+The following description describes the C interface for manipulating
+the mask. An example of code using these functions can be found in
+Appendix \ref{app:eg_C}.
+
+\subsubsection{Registering a new type}\label{sec:reg_C}
+
+Bits of the mask are allocated to a new type using the function:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+int SpaceMask\_RegisterType(char* \emph{type\_name}, int \emph{nstates},
+ char** \emph{state\_list})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{type\_name}] The name of the new type to be registered;
+ \item[\emph{nstates}] The number of states in the new type;
+ \item[\emph{state\_list}] A list of names, one for each state.
+\end{description}
+}
+}
+
+\noindent An appropriate number of bits of the mask are allocated to
+hold a unique value for the $n$ states specified by the \emph{nstates}
+argument. The registration must take place before the type can be
+used, so for instance, could be scheduled at CCTK\_STARTUP. New
+states can be added to an already allocated type using the function:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+ int SpaceMask\_AppendStatesToType(char* \emph{type\_name},
+ int \emph{nstates}, char** \emph{state\_list})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{type\_name}] The name of an already registered type;
+ \item[\emph{nstates}] The number of states to be added;
+ \item[\emph{state\_list}] A list of names, one for each of the new
+ states.
+\end{description}
+}}
+
+\noindent A number of new bits will be added to the specified type
+appropriate to hold the number of existing states plus the extra
+states. The allocated bits need not be contiguous within the mask.
+
+\subsubsection{Setting and checking mask states}
+
+The state of the mask at a given point is set using the function:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+void SpaceMask\_SetState(CCTK\_INT8* \emph{mask}, int \emph{point},
+ char* \emph{type\_name}, char* \emph{state})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_name}] The name of the type containing the state;
+ \item[\emph{state\_name}] The particular state to be set.
+\end{description}
+}}
+
+The state of the mask at a given point can be checked using:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+int SpaceMask\_CheckState(CCTK\_INT8* \emph{mask}, int \emph{point},
+ char* \emph{type\_name}, char* \emph{state})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_name}] The name of the type containing the state;
+ \item[\emph{state\_name}] The particular state to be compared.
+\end{description}
+}}
+
+The return value is 1 if the given \emph{state\_name} has been set at
+the point, or 0 otherwise.
+
+\subsubsection{Faster bitwise operators}
+
+The above mentioned functions for checking and setting the mask are
+rather inefficient, since they require strings to be compared at each
+point. A set of faster macros are provided which operate on the mask
+by performing bit operations directly. In order to use these
+functions, the bitmasks corresponding to the desired type and it's
+states need to be obtained using the following functions:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+CCTK\_INT8 SpaceMask\_GetTypeBits(char* \emph{type\_name})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{type\_name}] The type for which the bitmask is to be
+ determined.
+\end{description}
+}}
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+CCTK\_INT8 SpaceMask\_GetStateBits(char* \emph{type\_name},
+ char* \emph{state\_name})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{type\_name}] The type containing the state in question;
+ \item[\emph{state\_name}] The state whose bitmask is to be determined.
+\end{description}
+}}
+
+\noindent Each of these functions returns a CCTK\_INT which holds the
+bitmask corresponding to the given type or state. For example, if a
+given type uses three bits of the mask, the returned value could be
+the integer corresponding to the bitfield 001110000\ldots, where the
+location of 1s indicates the bits which have been allocated to the
+given type.
+
+The following macros have been defined for fast setting and checking
+of the mask by direct bitwise operations:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+void SpaceMask\_SetStateBits(CCTK\_INT8* \emph{mask}, int \emph{point},
+ CCTK\_INT8 \emph{type\_bits},\\\hspace*{10mm} CCTK\_INT8 \emph{state\_bits})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_bits}] The bitmask corresponding to the required
+ type;
+ \item[\emph{state\_bits}] The bitmask corrsponding to the required
+ state;
+\end{description}
+}}
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+int SpaceMask\_CheckStateBits(CCTK\_INT8* \emph{mask}, int \emph{point},
+ CCTK\_INT8 \emph{type\_bits},\\\hspace*{10mm} CCTK\_INT8 \emph{state\_bits})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_bits}] The bitmask corresponding to the required
+ type;
+ \item[\emph{state\_bits}] The bitmask corrsponding to the required
+ state;
+\end{description}
+}}
+
+\noindent The latter macro returns a 1 if the given state has been
+set, a 0 otherwise. The \emph{type\_bits} and \emph{state\_bits} can
+be obtained using the \texttt{SpaceMask\_Get*Bits} functions,
+described above.
+
+\subsection{Accessing the mask from Fortran90 Code}
+
+The following Fortran interfaces to the mask utilities apply only to
+Fortran90 code, since fast bitwise operations are not a part of the
+Fortran77 standard. An example of the use of the Fortran90 interface
+can be found in Appendix \ref{app:eg_F90}.
+
+\subsubsection{Registering a new type}
+
+Registration functions have not been implemented for the Fortran90
+interface, though they can easily be written in C by following the
+descriptions in Section \ref{sec:reg_C} and the example in Appendix
+\ref{app:eg_C}.
+
+\subsubsection{Setting and checking mask states}
+
+The mask states can be manipulated using the following functions:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_SetState(CCTK\_INT8 \emph{mask(,,)}, int \emph{point},
+ character \emph{type\_name},\\\hspace*{10mm} character \emph{state\_name})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_name}] The name of the type containing the state;
+ type;
+ \item[\emph{state\_name}] The name of the state to be set.
+\end{description}
+}}
+
+\noindent The value of the \emph{mask} variable is changed to turn on
+the specified state at the point.
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_CheckState(CCTK\_INT \emph{check}, CCTK\_INT8 \emph{mask(,,)},
+ int \emph{point},\\\hspace*{10mm} character \emph{type\_name},
+ character \emph{state\_name})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{check}] A variable which is set to 1 if the requested
+ state has been set;
+ \item[\emph{mask}] A pointer to the mask grid function;
+ \item[\emph{point}] The index of the point within the grid function
+ array;
+ \item[\emph{type\_name}] The name of the type containing the state;
+ type;
+ \item[\emph{state\_name}] The name of the state to be checked.
+\end{description}
+}}
+
+\subsubsection{Faster bitwise operators}
+
+As in the C interface, alternative bitwise operators have been defined
+in order to more quickly operate on the mask at a point. In order to
+use these functions, the bitmasks corresponding to the type and states
+in question must first be obtained using the following functions:
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_GetTypeBits(CCTK\_INT8 \emph{type\_bits},
+ character \emph{type\_name})
+}
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{type\_bits}] A variable which will be set to the bitmask of
+ the requested type;
+ \item[\emph{type\_name}] A character string naming the type.
+\end{description}
+}}
+
+\indent\parbox{\linewidth}{
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_GetStateBits(CCTK\_INT8 \emph{state\_bits},
+ character \emph{type\_name},\\\hspace*{10mm} character \emph{state\_name})
+}\\
+\hspace*{10mm}\parbox{\linewidth}{
+\begin{description}
+ \item[\emph{state\_bits}] A variable which will be set to the bitmask of
+ the requested state;
+ \item[\emph{type\_name}] A character string naming the type
+ containing the state;
+ \item[\emph{type\_name}] A character string naming the state.
+\end{description}
+}}
+
+\noindent Once the bitmasks for the type and state have been obtained,
+the following macros can be used directly:
+
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_SetStateBitsF90(mask, i, j, k, type\_bits, state\_bits)
+}\\
+
+\noindent This macro sets the value of the mask at the index $(i,j,k)$
+to the given state. It doesn't have a return value, and can be used
+directly inline (without a Fortran `call').
+
+\vspace{\baselineskip}\noindent\texttt{
+ SpaceMask\_CheckStateBitsF90(mask, i, j, k, type\_bits, state\_bits)
+}\\
+
+\noindent A value of `\texttt{.true.}' is returned if the given state
+has been set, or `\texttt{.false.}' otherwise. The macro can be used
+directly in Fortran boolean expressions, as in the examples in
+Appendix \ref{app:eg_F90}.
+
+
+\section{Notes}
+
+A proposal exists to provide a more versatile solution by allowing
+tables to be associated with each grid point. This could be
+implemented using the existing standard outlined here through the
+addition of an additional integer grid function
+
+\texttt{space\_table\_field}
+
+A bit of the existing \texttt{space\_mask} would be allocated to
+indicate whether or not a table has been associated with the given
+point. If so, then the corresponding point in the
+\texttt{space\_table\_field} would hold the table handle.
+
+
+\section{Acknowledgements}
+
+Thanks to Jonathan Thornburg, Tom Goodale, and Erik Schnetter for
+helpful comments on the original specification. Useful implementation
+of the mask required grid symmetries to work for integer grid
+functions. This was done by Thomas Radke. Peter Diener helped with the
+coding of the Fortran90 bitwise operators.
+
+\pagebreak
+\appendix
+\section{Example: C code}\label{app:eg_C}
+
+\begin{verbatim}
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+
+#include "SpaceMask.h"
+
+/*
+ * Register a mask type with three states.
+ */
+void Eg_RegisterMask (void)
+{
+ char *state_list_excision[3] = {"normal", "excise", "boundary"};
+
+ SpaceMask_RegisterType("excision", 3, state_list_excision);
+
+ return;
+}
+
+/*
+ * Set the mask to the ``normal'' state at each point using the
+ * slower name-reference function. See below for an example using
+ * the faster bitwise operator to check the mask states.
+ */
+void Eg_SetMaskStates (CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ int i, j, k, ijk;
+
+ for (k=0; k<cctk_lsh[2]; ++k)
+ {
+ for (j=0; j<cctk_lsh[1]; ++j)
+ {
+ for (i=0; i<cctk_lsh[0]; ++i)
+ {
+ ijk = CCTK_GFINDEX3D(cctkGH, i, j, k);
+
+ SpaceMask_SetState(space_mask, ijk, \"excision\", \"normal\");
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Check which of the points of the mask have been set to the
+ * ``boundary'' state using the bitwise macro.
+ */
+void Eg_CheckMaskStates (CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+ DECLARE_CCTK_PARAMETERS
+
+ int i, j, k, ijk;
+
+ CCTK_INT8 excision_mask;
+ CCTK_INT8 boundary_mask;
+
+ excision_mask = SpaceMask_GetTypeBits(\"excision\");
+ boundary_mask = SpaceMask_GetStateBits(\"boundary\");
+
+ for (k=0; k<cctk_lsh[2]; ++k)
+ {
+ for (j=0; j<cctk_lsh[1]; ++j)
+ {
+ for (i=0; i<cctk_lsh[0]; ++i)
+ {
+ ijk = CCTK_GFINDEX3D(cctkGH, i, j, k);
+
+ if (SpaceMask_CheckStateBits(space_mask, ijk, excision_mask,
+ boundary_mask))
+ {
+ CCTK_VINFO(CCTK_THORNSTRING,
+ \"Point (%d,%d,%d) is a boundary point.\n\",
+ i, j, k);
+ }
+ }
+ }
+ }
+ return;
+}
+\end{verbatim}
+
+
+\section{Example: Fortran90 code}\label{app:eg_F90}
+
+\begin{verbatim}
+#include "cctk.h"
+#include "cctk_Arguments.h"
+#include "cctk_Parameters.h"
+
+#include "SpaceMask.h"
+
+!
+! Sets each point of the mask to the 'normal' state. Here, 'normal'
+! is one of the states of the 'excision' type, which should have
+! been registered previously using the C SpaceMask_RegisterType()
+! function.
+!
+subroutine Eg_SetStateByName(CCTK_ARGUMENTS)
+ implicit none
+
+ integer ni, nj, nk
+ integer i, j, k, ijk
+
+ ni = cctk_lsh(1)
+ nj = cctk_lsh(2)
+ nk = cctk_lsh(3)
+
+ do k=1,nk
+ do j=1,nj
+ do i=1,ni
+
+ ijk = (i-1) + ni*((j-1) + nj*(k-1))
+
+ call SpaceMask_SetState(space_mask, ijk, "excision", "normal")
+
+ end do
+ end do
+ end do
+
+end subroutine Eg_SetStateByName
+
+!
+! Sets the mask values within a radius of 1 to the 'excise' state,
+! then does a check of the state of each point. The bitwise macros
+! are used in this case for greater efficiency in setting/checking
+! the mask.
+!
+subroutine Eg_SetExcisedRegionByBitmask(CCTK_ARGUMENTS)
+ implicit none
+
+ integer ni, nj, nk
+ integer i, j, k, ijk
+
+ CCTK_INT8 type_bits, excised
+
+ ni = cctk_lsh(1)
+ nj = cctk_lsh(2)
+ nk = cctk_lsh(3)
+
+ call SpaceMask_GetTypeBits(type_bits, "excision")
+ call SpaceMask_GetStateBits(excised, "excision", "excised")
+
+ do k=1,nk
+ do j=1,nj
+ do i=1,ni
+
+ if (r(i,j,k).lt.1.d0) then
+ SpaceMask_SetStateBitsF90(space_mask, i, j, k, type_bits, &
+ excised)
+ end if
+
+ end do
+ end do
+ end do
+
+ do k=1,nk
+ do j=1,nj
+ do i=1,ni
+ if (SpaceMask_CheckStateBitsF90(space_mask, i, j, k, type_bits, &
+ excised)) then
+ write(*,*) "The point (", i, j, k, ") has been excised."
+ end if
+ end do
+ end do
+ end do
+
+end subroutine Eg_SetExcisedRegionByBitmask
+\end{verbatim}
% Do not delete next line
% END CACTUS THORNGUIDE
diff --git a/doc/space_mask.eps b/doc/space_mask.eps
new file mode 100644
index 0000000..a9b2c62
--- /dev/null
+++ b/doc/space_mask.eps
@@ -0,0 +1,203 @@
+%!PS-Adobe-2.0 EPSF-2.0
+%%Title: space_mask.eps
+%%Creator: fig2dev Version 3.2 Patchlevel 3d
+%%CreationDate: Thu Nov 14 11:23:42 2002
+%%For: dp@nbdell15 (Denis Pollney,,,)
+%%BoundingBox: 0 0 400 242
+%%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 242 moveto 0 0 lineto 400 0 lineto 400 242 lineto closepath clip newpath
+-55.3 491.8 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
+15.000 slw
+n 7200 4275 m 900 4275 l 900 4725 l
+ 7200 4725 l gs col0 s gr
+% Polyline
+n 900 4275 m 1350 4275 l 1350 4725 l 900 4725 l
+ cp gs col6 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 1350 4275 m 1800 4275 l 1800 4725 l 1350 4725 l
+ cp gs col6 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 1800 4275 m 2250 4275 l 2250 4725 l 1800 4725 l
+ cp gs col3 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 2250 4275 m 2700 4275 l 2700 4725 l 2250 4725 l
+ cp gs col3 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 2700 4275 m 3150 4275 l 3150 4725 l 2700 4725 l
+ cp gs col3 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 3150 4275 m 3600 4275 l 3600 4725 l 3150 4725 l
+ cp gs col0 s gr
+% Polyline
+n 3600 4275 m 4050 4275 l 4050 4725 l 3600 4725 l
+ cp gs col0 s gr
+% Polyline
+n 4050 4275 m 4500 4275 l 4500 4725 l 4050 4725 l
+ cp gs col0 s gr
+% Polyline
+n 4500 4275 m 4950 4275 l 4950 4725 l 4500 4725 l
+ cp gs col0 s gr
+% Polyline
+n 4950 4275 m 5400 4275 l 5400 4725 l 4950 4725 l
+ cp gs col0 s gr
+% Polyline
+n 5400 4275 m 5850 4275 l 5850 4725 l 5400 4725 l
+ cp gs col0 s gr
+% Polyline
+n 5850 4275 m 6300 4275 l 6300 4725 l 5850 4725 l
+ cp gs col0 s gr
+% Polyline
+n 6300 4275 m 6750 4275 l 6750 4725 l 6300 4725 l
+ cp gs col0 s gr
+% Polyline
+n 1485 5535 m 3420 5535 l 3420 6885 l 1485 6885 l
+ cp gs col0 s gr
+% Polyline
+n 4140 5535 m 6030 5535 l 6030 7785 l 4140 7785 l
+ cp gs col0 s gr
+% Polyline
+n 1125 4725 m 1125 4950 l
+ 1575 4950 l gs col0 s gr
+% Polyline
+n 1575 4725 m
+ 1575 5535 l gs col0 s gr
+% Polyline
+n 2025 4725 m 2025 4950 l 4230 4950 l
+ 4230 5535 l gs col0 s gr
+% Polyline
+n 2475 4725 m
+ 2475 4950 l gs col0 s gr
+% Polyline
+n 2925 4725 m
+ 2925 4950 l gs col0 s gr
+% Polyline
+n 1485 5535 m 3420 5535 l 3420 5940 l 1485 5940 l
+ cp gs col6 1.00 shd ef gr gs col0 s gr
+% Polyline
+n 4140 5535 m 6030 5535 l 6030 5895 l 4140 5895 l
+ cp gs col3 1.00 shd ef gr gs col0 s gr
+/Helvetica-Bold ff 210.00 scf sf
+1575 6165 m
+gs 1 -1 sc (00 = "normal") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+1575 6420 m
+gs 1 -1 sc (01 = "excised") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+1575 6705 m
+gs 1 -1 sc (10 = "boundary") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 6165 m
+gs 1 -1 sc (000 = "black") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 6420 m
+gs 1 -1 sc (001 = "red") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 6675 m
+gs 1 -1 sc (010 = "blue") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 6930 m
+gs 1 -1 sc (011 = "green") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 7185 m
+gs 1 -1 sc (100 = "yellow") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 7440 m
+gs 1 -1 sc (101 = "orange") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 7695 m
+gs 1 -1 sc (110 = "white") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+4275 5805 m
+gs 1 -1 sc (type: "colour") col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+900 4140 m
+gs 1 -1 sc (space_mask) col0 sh gr
+/Helvetica-Bold ff 210.00 scf sf
+1575 5805 m
+gs 1 -1 sc (type: "excision") col0 sh gr
+$F2psEnd
+rs
diff --git a/doc/space_mask.fig b/doc/space_mask.fig
new file mode 100644
index 0000000..920d8ed
--- /dev/null
+++ b/doc/space_mask.fig
@@ -0,0 +1,68 @@
+#FIG 3.2
+Landscape
+Center
+Metric
+A4
+100.00
+Single
+-2
+1200 2
+2 1 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 4
+ 7200 4275 900 4275 900 4725 7200 4725
+2 2 0 2 0 6 50 0 20 0.000 0 0 -1 0 0 5
+ 900 4275 1350 4275 1350 4725 900 4725 900 4275
+2 2 0 2 0 6 50 0 20 0.000 0 0 -1 0 0 5
+ 1350 4275 1800 4275 1800 4725 1350 4725 1350 4275
+2 2 0 2 0 3 50 0 20 0.000 0 0 -1 0 0 5
+ 1800 4275 2250 4275 2250 4725 1800 4725 1800 4275
+2 2 0 2 0 3 50 0 20 0.000 0 0 -1 0 0 5
+ 2250 4275 2700 4275 2700 4725 2250 4725 2250 4275
+2 2 0 2 0 3 50 0 20 0.000 0 0 -1 0 0 5
+ 2700 4275 3150 4275 3150 4725 2700 4725 2700 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 3150 4275 3600 4275 3600 4725 3150 4725 3150 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 3600 4275 4050 4275 4050 4725 3600 4725 3600 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 4050 4275 4500 4275 4500 4725 4050 4725 4050 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 4500 4275 4950 4275 4950 4725 4500 4725 4500 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 4950 4275 5400 4275 5400 4725 4950 4725 4950 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 5400 4275 5850 4275 5850 4725 5400 4725 5400 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 5850 4275 6300 4275 6300 4725 5850 4725 5850 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 6300 4275 6750 4275 6750 4725 6300 4725 6300 4275
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 1485 5535 3420 5535 3420 6885 1485 6885 1485 5535
+2 2 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 5
+ 4140 5535 6030 5535 6030 7785 4140 7785 4140 5535
+2 1 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 3
+ 1125 4725 1125 4950 1575 4950
+2 1 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 2
+ 1575 4725 1575 5535
+2 1 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 4
+ 2025 4725 2025 4950 4230 4950 4230 5535
+2 1 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 2
+ 2475 4725 2475 4950
+2 1 0 2 0 6 50 0 -1 0.000 0 0 -1 0 0 2
+ 2925 4725 2925 4950
+2 2 0 2 0 6 50 0 20 0.000 0 0 -1 0 0 5
+ 1485 5535 3420 5535 3420 5940 1485 5940 1485 5535
+2 2 0 2 0 3 50 0 20 0.000 0 0 -1 0 0 5
+ 4140 5535 6030 5535 6030 5895 4140 5895 4140 5535
+4 0 0 50 0 18 14 0.0000 4 165 1425 1575 6165 00 = "normal"\001
+4 0 0 50 0 18 14 0.0000 4 165 1485 1575 6420 01 = "excised"\001
+4 0 0 50 0 18 14 0.0000 4 210 1710 1575 6705 10 = "boundary"\001
+4 0 0 50 0 18 14 0.0000 4 165 1380 4275 6165 000 = "black"\001
+4 0 0 50 0 18 14 0.0000 4 165 1170 4275 6420 001 = "red"\001
+4 0 0 50 0 18 14 0.0000 4 165 1275 4275 6675 010 = "blue"\001
+4 0 0 50 0 18 14 0.0000 4 210 1425 4275 6930 011 = "green"\001
+4 0 0 50 0 18 14 0.0000 4 210 1470 4275 7185 100 = "yellow"\001
+4 0 0 50 0 18 14 0.0000 4 210 1560 4275 7440 101 = "orange"\001
+4 0 0 50 0 18 14 0.0000 4 165 1365 4275 7695 110 = "white"\001
+4 0 0 50 0 18 14 0.0000 4 210 1470 4275 5805 type: "colour"\001
+4 0 0 50 0 18 14 0.0000 4 210 1275 900 4140 space_mask\001
+4 0 0 50 0 18 14 0.0000 4 210 1650 1575 5805 type: "excision"\001
diff --git a/interface.ccl b/interface.ccl
index 81fb75a..70433bd 100644
--- a/interface.ccl
+++ b/interface.ccl
@@ -8,14 +8,19 @@ USES INCLUDE: Symmetry.h
public:
+CCTK_INT8 space_mask_group type=GF
+{
+ space_mask
+}
+
+#
+# The following emask GF is kept for the sake of compatibility with
+# the existing excision thorns. Once these are translated to the new
+# mask, this function will disappear. Please don't use it for
+# anything.
+#
real mask type = GF
{
emask
} "Mask"
-# Will be changed to:
-#INTEGER spacemasks TYPE=GF
-#{
-# space_mask
-# space_table_field
-#}
diff --git a/schedule.ccl b/schedule.ccl
index 9923239..68492fb 100644
--- a/schedule.ccl
+++ b/schedule.ccl
@@ -1,15 +1,34 @@
# Schedule definitions for thorn SpaceMask
# $Header$
-if (use_mask)
+if (use_mask)
{
- STORAGE: mask
- schedule MaskOne at CCTK_INITIAL
+ STORAGE: space_mask_group
+
+ schedule MaskZero at CCTK_INITIAL
{
LANG: C
- } "Set mask to one"
+ } "Initialise mask to zero"
+
schedule MaskSym at CCTK_BASEGRID
{
LANG: C
} "Set grid symmetries for mask"
+
+ #
+ # The following is for compatibility with current excision routines,
+ # and will be removed once they are up-to-date with the new mask
+ # scheme.
+ #
+ STORAGE: mask
+ schedule MaskSym_emask at CCTK_BASEGRID
+ {
+ LANG: C
+ } "Set grid symmetries for mask"
+
+ schedule MaskOne at CCTK_INITIAL
+ {
+ LANG: C
+ } "Set mask to one"
+
}
diff --git a/src/MaskInit.c b/src/MaskInit.c
index 50760dc..9436404 100644
--- a/src/MaskInit.c
+++ b/src/MaskInit.c
@@ -14,6 +14,7 @@
#include "cctk_Arguments.h"
#include "Symmetry.h"
+#include "SpaceMask.h"
static const char *rcsid = "$Header$";
@@ -46,8 +47,61 @@ void MaskOne(CCTK_ARGUMENTS);
********************* External Routines **********************
********************************************************************/
- /*@@
+/*@@
+ @routine SetupSpaceMaskRegistry
+ @date November 2002
+ @author Denis Pollney
+ @desc
+ Allocate and initialise the global spacemask registry.
+ @enddesc
+@@*/
+void SetupSpaceMaskRegistry (void)
+{
+ SpaceMask_Registry* spacemask_registry;
+
+ spacemask_registry = (SpaceMask_Registry*) malloc
+ (sizeof(SpaceMask_Registry));
+
+ spacemask_registry->ntypes=0;
+ spacemask_registry->type_list = NULL;
+
+ return;
+}
+
+/*@@
@routine MaskSym
+ @date October 2002
+ @author Denis Pollney
+ @desc
+ Scheduled routine to set symmetries for mask
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+void MaskSym(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+
+ int one;
+ int sym[3];
+
+ one = 1;
+
+ sym[0] = one;
+ sym[1] = one;
+ sym[2] = one;
+
+ SetCartSymVN(cctkGH, sym, "spacemask::space_mask");
+
+ return;
+}
+
+/*@@
+ @routine MaskSym_emask
@date Fri 3 May 2002
@author Gabrielle Allen
@desc
@@ -60,7 +114,7 @@ void MaskOne(CCTK_ARGUMENTS);
@endhistory
@@*/
-void MaskSym(CCTK_ARGUMENTS)
+void MaskSym_emask(CCTK_ARGUMENTS)
{
DECLARE_CCTK_ARGUMENTS
@@ -69,16 +123,16 @@ void MaskSym(CCTK_ARGUMENTS)
one = 1;
- sym[0] = one;
- sym[1] = one;
- sym[2] = one;
+ sym[0] = one;
+ sym[1] = one;
+ sym[2] = one;
- SetCartSymVN(cctkGH, sym,"spacemask::emask");
+ SetCartSymVN(cctkGH, sym, "spacemask::emask");
return;
}
- /*@@
+/*@@
@routine MaskOne
@date
@author Miguel Alcubierre
@@ -105,6 +159,32 @@ void MaskOne(CCTK_ARGUMENTS)
return;
}
+/*@@
+ @routine MaskZero
+ @date
+ @author Denis Pollney
+ @desc
+ Initialise the mask to zero.
+ @enddesc
+ @calls
+ @calledby
+ @history
+
+ @endhistory
+
+@@*/
+void MaskZero(CCTK_ARGUMENTS)
+{
+ DECLARE_CCTK_ARGUMENTS
+
+ int i;
+
+ for(i = 0; i < cctk_lsh[0]*cctk_lsh[1]*cctk_lsh[2]; i++)
+ space_mask[i] = 0;
+
+ return;
+}
+
/********************************************************************
********************* Local Routines *************************
********************************************************************/
diff --git a/src/MaskUtils.c b/src/MaskUtils.c
new file mode 100644
index 0000000..f8c5a75
--- /dev/null
+++ b/src/MaskUtils.c
@@ -0,0 +1,496 @@
+/*@@
+ @file MaskUtils.c
+ @date October 2002
+ @author Denis Pollney
+ @desc
+ Utilities for registering/setting/checking the mask.
+ @desc
+ @version $Header$
+@@*/
+
+#include <stdio.h>
+
+#include "cctk.h"
+#include "cctk_FortranString.h"
+
+#include "SpaceMask.h"
+
+static const char* rcsid = "$Header$";
+
+CCTK_FILEVERSION(CACTUSEINSTEIN_SPACEMASK_MaskUtils_c);
+
+SpaceMask_Registry* spacemask_registry = NULL;
+
+/*@@
+ @routine SpaceMask_get_bit_nbr
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Return the number of bits required to represent a given number.
+ Cheesy divide-by-two method, maybe something else is quicker.
+ @enddesc
+@@*/
+
+int
+SpaceMask_get_bit_nbr(int nstates)
+{
+ int bstates;
+ int bit_nbr;
+
+ bstates = nstates-1;
+
+ for (bit_nbr=0; bstates>0; ++bit_nbr)
+ bstates /= 2;
+
+ return bit_nbr;
+}
+
+/*@@
+ @routine SpaceMask_get_free_bits
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Determine the mask bits which have not yet been allocated.
+ The return value is a bitmask with the requested number of
+ free bits set to 1. If there are not enough free bits left
+ to satisfy the request, stop with an error.
+ @enddesc
+@@*/
+
+CCTK_INT8
+SpaceMask_get_free_bits(int nbits)
+{
+ CCTK_INT8 used_bits;
+ CCTK_INT8 new_bits;
+ int i;
+ int j;
+ int n;
+
+ used_bits = 0;
+ if (spacemask_registry != NULL)
+ {
+ for (i=0; i<spacemask_registry->ntypes; ++i)
+ used_bits |= spacemask_registry->type_list[i]->bitmask;
+ }
+
+ n=1;
+ new_bits = 0;
+ j = 0;
+ for (i=0; i<sizeof(CCTK_INT8)*8 & j<nbits; ++i)
+ {
+ if (!(n & used_bits))
+ {
+ ++j;
+ new_bits |= n;
+ }
+ n *= 2;
+ }
+
+ if (j<nbits)
+ CCTK_WARN (0, "Cannot allocate mask: Not enough free bits.");
+
+ return new_bits;
+}
+
+/*@@
+ @routine SpaceMask_determine_state_mask
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Determine appropriate bitmasks to represent a number of
+ states, using the allocated bit mask.
+ That is, if allocated_bits is set to 00111000, then
+ the returned list of states are permutations of the three
+ non-zero (active) bits.
+ @enddesc
+@@*/
+
+CCTK_INT8*
+SpaceMask_determine_state_mask(CCTK_INT8 allocated_bits, int nstates)
+{
+ CCTK_INT8* state_mask;
+ int n;
+ int bit;
+ int i;
+ int j;
+
+ state_mask =
+ (CCTK_INT8*) malloc (nstates*sizeof(CCTK_INT8));
+
+ for (j=0; j<nstates; ++j)
+ state_mask[j] = 0;
+
+ n=1;
+ bit=1;
+
+ for (i=0; i<sizeof(CCTK_INT8)*8; ++i)
+ {
+ if (n & allocated_bits)
+ {
+ for (j=0; j<nstates; ++j)
+ {
+ if (bit & j)
+ state_mask[j] += n;
+ }
+ bit *= 2;
+ }
+ n *= 2;
+ }
+
+ return state_mask;
+}
+
+/*@@
+ @routine SpaceMask_setup_new_state
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Allocate a new SpaceMask_State, giving it a name and
+ a bit mask.
+ @enddesc
+@@*/
+
+SpaceMask_State*
+SpaceMask_setup_new_state(CCTK_INT8 state_mask, char* name)
+{
+ SpaceMask_State* new_state;
+
+ new_state = (SpaceMask_State*) malloc (sizeof(SpaceMask_State));
+ new_state->name = name;
+ new_state->bitmask = state_mask;
+
+ return new_state;
+}
+
+/*@@
+ @routine SpaceMask_setup_new_type
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Allocate a new SpaceMask_Type. This involves allocating
+ a set of bits within the mask to the new type, and creating
+ appropriate bitmasks (using the allocated bits) for each of
+ the requested states.
+ @enddesc
+@@*/
+
+SpaceMask_Type*
+SpaceMask_setup_new_type(CCTK_INT8 new_bits, char* type_name,
+ int nstates, char** state_list,
+ CCTK_INT8* state_mask)
+{
+ SpaceMask_Type* new_type;
+ int j;
+
+ new_type = (SpaceMask_Type*) malloc (sizeof(SpaceMask_Type));
+ new_type->bitmask = new_bits;
+ new_type->nstates = nstates;
+ new_type->name = type_name;
+ new_type->state_list =
+ (SpaceMask_State**) malloc (nstates*sizeof(SpaceMask_State*));
+
+ for (j=0; j<nstates; ++j)
+ new_type->state_list[j] = SpaceMask_setup_new_state(state_mask[j],
+ state_list[j]);
+ return new_type;
+}
+
+/*@@
+ @routine SpaceMask_append_type_to_registry
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Adds a new type to the spacemask_registry.
+ @enddesc
+@@*/
+
+void
+SpaceMask_append_type_to_registry(SpaceMask_Type* new_type)
+{
+ SpaceMask_Type** new_type_list;
+ int ntypes;
+ int i;
+
+ if (spacemask_registry == NULL)
+ {
+ spacemask_registry =
+ (SpaceMask_Registry*) malloc (sizeof(SpaceMask_Registry));
+ ntypes = 1;
+ new_type_list = (SpaceMask_Type**) malloc (sizeof(SpaceMask_Type*));
+ new_type_list[0] = new_type;
+ }
+ else
+ {
+ ntypes = spacemask_registry->ntypes + 1;
+ new_type_list =
+ (SpaceMask_Type**) malloc (ntypes*sizeof(SpaceMask_Type*));
+ for (i=0; i<ntypes-1; ++i)
+ new_type_list[i] = spacemask_registry->type_list[i];
+ new_type_list[ntypes-1] = new_type;
+ free(spacemask_registry->type_list);
+ }
+
+ spacemask_registry->ntypes = ntypes;
+ spacemask_registry->type_list = new_type_list;
+}
+
+/*@@
+ @routine SpaceMask_RegisterType
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Allocates a set of bits of the SpaceMask to represent
+ a set of states of the named type.
+ @enddesc
+@@*/
+
+int
+SpaceMask_RegisterType(char* type_name, int nstates, char** state_list)
+{
+ SpaceMask_Type* new_type;
+ CCTK_INT8 new_bits;
+ CCTK_INT8* state_mask;
+ int bit_nbr;
+
+ bit_nbr = SpaceMask_get_bit_nbr(nstates);
+ new_bits = SpaceMask_get_free_bits(bit_nbr);
+ state_mask = SpaceMask_determine_state_mask(new_bits, nstates);
+
+ new_type = SpaceMask_setup_new_type(new_bits, type_name, nstates,
+ state_list, state_mask);
+
+ SpaceMask_append_type_to_registry (new_type);
+
+ return 0;
+}
+
+/*@@
+ @routine SpaceMask_AppendStatesToType
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Adds a new set of possible states to an already existing
+ type. If required, new bits of the mask are allocated to the
+ given state. If bits are not available for this, then an
+ error is returned.
+ @enddesc
+@@*/
+
+int
+SpaceMask_AppendStatesToType(char* type_name, int nstates, char** state_list)
+{
+ CCTK_INT8 new_bits;
+ CCTK_INT8 allocated_bits;
+ CCTK_INT8* state_mask;
+ SpaceMask_Type* old_type;
+ SpaceMask_Type* new_type;
+ char** new_state_list;
+ int i;
+ int j;
+ int old_type_idx;
+ int new_bit_nbr;
+ int total_nstates;
+
+ old_type = NULL;
+ for (i=0; i<spacemask_registry->ntypes; ++i)
+ {
+ if (!strcmp(spacemask_registry->type_list[i]->name, type_name))
+ {
+ old_type = spacemask_registry->type_list[i];
+ old_type_idx = i;
+ }
+ }
+
+ if (old_type == NULL)
+ {
+ CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Mask type \"%s\" has not been registered", type_name);
+ return -1;
+ }
+
+ total_nstates = old_type->nstates + nstates;
+ new_bit_nbr = SpaceMask_get_bit_nbr(total_nstates) -
+ SpaceMask_get_bit_nbr(old_type->nstates);
+
+ new_bits = SpaceMask_get_free_bits(new_bit_nbr);
+ allocated_bits = old_type->bitmask | new_bits;
+
+ state_mask = SpaceMask_determine_state_mask(allocated_bits, total_nstates);
+
+ new_state_list = (char**) malloc (total_nstates*sizeof(char*));
+
+ i = 0;
+ for (j=0; j<old_type->nstates; ++j, ++i)
+ new_state_list[i] = old_type->state_list[j]->name;
+ for (j=0; j<nstates; ++j, ++i)
+ new_state_list[i] = state_list[j];
+
+ new_type = SpaceMask_setup_new_type(allocated_bits, type_name, total_nstates,
+ new_state_list, state_mask);
+ free(old_type);
+
+ spacemask_registry->type_list[old_type_idx] = new_type;
+
+ return 0;
+}
+
+/*@@
+ @routine SpaceMask_GetTypeBits
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Returns the bitmask corresponding to the given type. Bits
+ which are allocated to the given type are set to 1, all other
+ bits are 0.
+ @enddesc
+@@*/
+
+CCTK_INT8
+SpaceMask_GetTypeBits(char* type_name)
+{
+ int i;
+
+ for (i=0; i<spacemask_registry->ntypes; ++i)
+ {
+ if (!strcmp(spacemask_registry->type_list[i]->name, type_name))
+ return spacemask_registry->type_list[i]->bitmask;
+ }
+
+ CCTK_VInfo (CCTK_THORNSTRING, "Type \"%s\" has not been registered.\n",
+ type_name);
+
+ return 0;
+}
+
+/*@@
+ @routine SpaceMask_GetStateBits
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Returns the bitmask corresponding to the given state.
+ @enddesc
+@@*/
+
+CCTK_INT8
+SpaceMask_GetStateBits(char* type_name, char* state_name)
+{
+ SpaceMask_Type* type;
+ int i, j;
+
+ for (i=0; i<spacemask_registry->ntypes; ++i)
+ {
+ if (!strcmp(spacemask_registry->type_list[i]->name, type_name))
+ {
+ type = spacemask_registry->type_list[i];
+ for (j=0; j<type->nstates; ++j)
+ {
+ if (!strcmp(type->state_list[j]->name, state_name))
+ return type->state_list[j]->bitmask;
+ }
+ }
+ }
+
+ CCTK_VInfo (CCTK_THORNSTRING,
+ "Requested state \"%s\" could not be found in type \"%s\"\n",
+ state_name, type_name);
+
+ return 0;
+}
+
+/*@@
+ @routine SpaceMask_SetState
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Sets the mask at a point to the given state.
+ @enddesc
+@@*/
+
+void
+SpaceMask_SetState(CCTK_INT8* mask, int point, char* type_name, char* state)
+{
+ CCTK_INT8 type_bits;
+ CCTK_INT8 state_bits;
+
+ type_bits = SpaceMask_GetTypeBits(type_name);
+ state_bits = SpaceMask_GetStateBits(type_name, state);
+
+ SpaceMask_SetStateBits(mask, point, type_bits, state_bits);
+}
+
+/*@@
+ @routine SpaceMask_CheckState
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Checks that the mask at a point has the given state, in which
+ case return 1, otherwise return 0.
+ @enddesc
+@@*/
+
+int
+SpaceMask_CheckState(CCTK_INT8* mask, int point, char* type_name, char* state)
+{
+ CCTK_INT8 type_bits;
+ CCTK_INT8 state_bits;
+
+ type_bits = SpaceMask_GetTypeBits(type_name);
+ state_bits = SpaceMask_GetStateBits(type_name, state);
+
+ return SpaceMask_CheckStateBits(mask, point, type_bits, state_bits);
+}
+
+
+/********************************************************************
+ ********************* Fortran Wrappers ***************************
+ ********************************************************************/
+
+/* How do you pass the char** state list from fortran???
+void
+CCTK_FCALL CCTK_FNAME(SpaceMask_RegisterType)(int* ierr, char* type_name,
+ int* nstates, char** state_list)
+{
+ *ierr = SpaceMask_RegisterType(type_name, *nstates, state_list);
+}
+*/
+
+void
+CCTK_FCALL CCTK_FNAME(SpaceMask_GetTypeBits)(CCTK_INT8* type_bits,
+ ONE_FORTSTRING_ARG)
+{
+ ONE_FORTSTRING_CREATE(type_name)
+
+ *type_bits = SpaceMask_GetTypeBits(type_name);
+
+ free(type_name);
+}
+
+void
+CCTK_FCALL CCTK_FNAME(SpaceMask_GetStateBits)(CCTK_INT8* state_bits,
+ TWO_FORTSTRING_ARG)
+{
+
+ TWO_FORTSTRING_CREATE(type_name, state_name)
+
+ *state_bits = SpaceMask_GetStateBits(type_name, state_name);
+}
+
+void
+CCTK_FCALL CCTK_FNAME(SpaceMask_SetState)(CCTK_INT8* mask,
+ CCTK_INT* point, TWO_FORTSTRING_ARG)
+{
+ TWO_FORTSTRING_CREATE(type_name, state)
+
+ SpaceMask_SetState(mask, *point, type_name, state);
+}
+
+void
+CCTK_FCALL CCTK_FNAME(SpaceMask_CheckState)(int* retval,
+ CCTK_INT8* mask,
+ CCTK_INT* point,
+ TWO_FORTSTRING_ARG)
+{
+ TWO_FORTSTRING_CREATE(type_name, state)
+
+ *retval = SpaceMask_CheckState(mask, *point, type_name, state);
+}
diff --git a/src/SpaceMask.h b/src/SpaceMask.h
new file mode 100644
index 0000000..bbcecdf
--- /dev/null
+++ b/src/SpaceMask.h
@@ -0,0 +1,113 @@
+/*@@
+ @file MaskUtils.c
+ @date October 2002
+ @author Denis Pollney
+ @desc
+ Function prototypes and macros mask utilities.
+ @desc
+ @version $Header$
+@@*/
+
+#ifndef __CACTUSEINSTEIN_SPACEMASK_H__
+#define __CACTUSEINSTEIN_SPACEMASK_H__
+
+#define DEBUG 0
+
+/********************************************************************
+ ********************* Routine Prototypes *************************
+ ********************************************************************/
+#ifdef CCODE
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+int SpaceMask_RegisterType(char*, int, char**);
+int SpaceMask_AppendStatesToType(char*, int, char**);
+void SpaceMask_SetState(CCTK_INT8*, int, char*, char*);
+int SpaceMask_CheckState(CCTK_INT8*, int, char*, char*);
+CCTK_INT8 SpaceMask_GetTypeBits(char*);
+CCTK_INT8 SpaceMask_GetStateBits(char*, char*);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+/********************************************************************
+ ********************* Local Data Types **********************
+ ********************************************************************/
+
+#ifdef CCODE
+
+typedef struct
+{
+ char* name;
+ CCTK_INT8 bitmask;
+} SpaceMask_State;
+
+typedef struct
+{
+ char* name;
+ int nstates;
+ CCTK_INT8 bitmask;
+ SpaceMask_State** state_list;
+} SpaceMask_Type;
+
+typedef struct
+{
+ int ntypes;
+ SpaceMask_Type** type_list;
+} SpaceMask_Registry;
+
+extern SpaceMask_Registry* spacemask_Registry;
+
+#endif
+
+/********************************************************************
+ ********************* Macros ******************************
+ ********************************************************************/
+
+/*@@
+ @routine SpaceMask_SetStateBits
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Sets the mask at a point to the given state, as specified
+ using a bitmask.
+ @enddesc
+@@*/
+
+#ifdef FCODE
+#define SpaceMask_SetStateBitsF90(mask, i, j, k, type_bits, state_bits) \
+ mask(i,j,k) = ior(iand(mask(i,j,k), not(type_bits)), state_bits)
+#endif
+
+#ifdef CCODE
+#define SpaceMask_SetStateBits(mask, ijk, type_bits, state_bits) \
+ mask[ijk] = (mask[ijk] & ~type_bits) | state_bits;
+#endif
+
+/*@@
+ @routine SpaceMask_CheckStateBits
+ @author Denis Pollney
+ @date 15 October 2002
+ @desc
+ Checks that the mask at a point has the specified state,
+ in which case return 1, otherwise return 0.
+ @enddesc
+@@*/
+
+#ifdef FCODE
+#define SpaceMask_CheckStateBitsF90(mask, i, j, k, type_bits, state_bits) \
+ (iand(mask(i,j,k), type_bits) .eq. state_bits)
+#endif
+
+#ifdef CCODE
+#define SpaceMask_CheckStateBits(mask, ijk, type_bits, state_bits) \
+ (mask[ijk] & type_bits) == state_bits
+#endif
+
+#endif /* __CACTUSEINSTEIN_SPACEMASK_H__ */
diff --git a/src/make.code.defn b/src/make.code.defn
index 4a62d46..ed19aad 100644
--- a/src/make.code.defn
+++ b/src/make.code.defn
@@ -2,7 +2,7 @@
# $Header$
# Source files in this directory
-SRCS = MaskInit.c
+SRCS = MaskInit.c MaskUtils.c
# Subdirectories containing source files
SUBDIRS =