aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpollney <pollney@a491c6a4-70bf-4b89-8b36-d6c0cb1f094e>2002-11-14 13:19:55 +0000
committerpollney <pollney@a491c6a4-70bf-4b89-8b36-d6c0cb1f094e>2002-11-14 13:19:55 +0000
commitad38e65250a779b827586e44f7963969a182db65 (patch)
tree09b290fde34d8ef8d38da6acc96e2b82b1ec22be
parentacf684447216dd5f57dc52c3e55f5e943df25463 (diff)
Implementation of the recently discussed spacemask spec. See the
doc/documentation.tex for details. The existing mask grid-function (emask) has been retained for the time being, until the excision related thorns can be brought up to date with the new interface. These thorns should see no change in their behaviour. In the meantime, the space_mask GF can be used simultaneously via the new interfaces. git-svn-id: http://svn.cactuscode.org/arrangements/CactusNumerical/SpaceMask/trunk@15 a491c6a4-70bf-4b89-8b36-d6c0cb1f094e
-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 =