From cf7a8b58f4ae85517bbe0797efdc95c2a539d76e Mon Sep 17 00:00:00 2001 From: knarf Date: Wed, 2 Dec 2009 22:22:51 +0000 Subject: thorns for general eos interface (moved from Whisky_Dev repositories) git-svn-id: http://svn.einsteintoolkit.org/cactus/EinsteinBase/EOSG_Base/trunk@2 e77735cb-7dd8-4a7a-87c7-7cc99eb84b11 --- README | 9 + configuration.ccl | 8 + doc/documentation.tex | 457 ++++++++++++++++++++ interface.ccl | 29 ++ param.ccl | 2 + schedule.ccl | 8 + src/EOSBase_Register.c | 1094 ++++++++++++++++++++++++++++++++++++++++++++++++ src/EOS_Utils.c | 68 +++ src/EOS_Utils.h | 16 + src/make.code.defn | 9 + test/test | 1 + 11 files changed, 1701 insertions(+) create mode 100755 README create mode 100755 configuration.ccl create mode 100755 doc/documentation.tex create mode 100755 interface.ccl create mode 100755 param.ccl create mode 100755 schedule.ccl create mode 100755 src/EOSBase_Register.c create mode 100755 src/EOS_Utils.c create mode 100755 src/EOS_Utils.h create mode 100755 src/make.code.defn create mode 100644 test/test diff --git a/README b/README new file mode 100755 index 0000000..77acde4 --- /dev/null +++ b/README @@ -0,0 +1,9 @@ +CVS info : $Header$ + +Cactus Code Thorn EOSBase_General +Thorn Author(s) : Ian Hawke +Thorn Maintainer(s) : Ian Hawke +-------------------------------------------------------------------------- + +Purpose of the thorn: + diff --git a/configuration.ccl b/configuration.ccl new file mode 100755 index 0000000..d9f5dfc --- /dev/null +++ b/configuration.ccl @@ -0,0 +1,8 @@ +# Configuration definitions for thorn EOSBase_General +# $Header$ + +PROVIDES EOSBase_General +{ + SCRIPT + LANG +} diff --git a/doc/documentation.tex b/doc/documentation.tex new file mode 100755 index 0000000..b1cd8d9 --- /dev/null +++ b/doc/documentation.tex @@ -0,0 +1,457 @@ +% *======================================================================* +% Cactus Thorn template for ThornGuide documentation +% Author: Ian Kelley +% Date: Sun Jun 02, 2002 +% $Header$ +% +% Thorn documentation in the latex file doc/documentation.tex +% will be included in ThornGuides built with the Cactus make system. +% The scripts employed by the make system automatically include +% pages about variables, parameters and scheduling parsed from the +% relevant thorn CCL files. +% +% This template contains guidelines which help to assure that your +% documentation will be correctly added to ThornGuides. More +% information is available in the Cactus UsersGuide. +% +% Guidelines: +% - Do not change anything before the line +% % START CACTUS THORNGUIDE", +% except for filling in the title, author, date, etc. fields. +% - Each of these fields should only be on ONE line. +% - Author names should be separated with a \\ or a comma. +% - You can define your own macros, but they must appear after +% the START CACTUS THORNGUIDE line, and must not redefine standard +% latex commands. +% - To avoid name clashes with other thorns, 'labels', 'citations', +% 'references', and 'image' names should conform to the following +% convention: +% ARRANGEMENT_THORN_LABEL +% For example, an image wave.eps in the arrangement CactusWave and +% thorn WaveToyC should be renamed to CactusWave_WaveToyC_wave.eps +% - Graphics should only be included using the graphicx package. +% More specifically, with the "\includegraphics" command. Do +% not specify any graphic file extensions in your .tex file. This +% will allow us to create a PDF version of the ThornGuide +% via pdflatex. +% - References should be included with the latex "\bibitem" command. +% - Use \begin{abstract}...\end{abstract} instead of \abstract{...} +% - Do not use \appendix, instead include any appendices you need as +% standard sections. +% - For the benefit of our Perl scripts, and for future extensions, +% please use simple latex. +% +% *======================================================================* +% +% Example of including a graphic image: +% \begin{figure}[ht] +% \begin{center} +% \includegraphics[width=6cm]{MyArrangement_MyThorn_MyFigure} +% \end{center} +% \caption{Illustration of this and that} +% \label{MyArrangement_MyThorn_MyLabel} +% \end{figure} +% +% Example of using a label: +% \label{MyArrangement_MyThorn_MyLabel} +% +% Example of a citation: +% \cite{MyArrangement_MyThorn_Author99} +% +% Example of including a reference +% \bibitem{MyArrangement_MyThorn_Author99} +% {J. Author, {\em The Title of the Book, Journal, or periodical}, 1 (1999), +% 1--16. {\tt http://www.nowhere.com/}} +% +% *======================================================================* + +% If you are using CVS use this line to give version information +% $Header$ + +\documentclass{article} + +% Use the Cactus ThornGuide style file +% (Automatically used from Cactus distribution, if you have a +% thorn without the Cactus Flesh download this from the Cactus +% homepage at www.cactuscode.org) +\usepackage{../../../../doc/latex/cactus} + +\begin{document} + +% The author of the documentation +\author{Ian Hawke \textless ih@maths.soton.ac.uk\textgreater} + +% The title of the document (not necessarily the name of the Thorn) +\title{General equations of state} + +% the date your document was last changed, if your document is in CVS, +% please use: +% \date{$ $Date$ $} +\date{March 15 2005} + +\maketitle + +% Do not delete next line +% START CACTUS THORNGUIDE + +% Add all definitions used in this documentation here +% \def\mydef etc + +% Add an abstract for this thorn's documentation +\begin{abstract} + This thorn provides a generalized equation of state interface. +\end{abstract} + +% The following sections are suggestive only. +% Remove them or add your own. + +\section{Equations of state} + +In solving the equations of hydrodynamics there are five independent +variables (typically $\rho, v^i, \epsilon$ for the rest mass density, +velocity and specific internal energy) and further variables, such as +the pressure $P$ which depend on the independent variables. Such +dependent variables are specified by an {\em equation of state} (EOS) +that closes the system of equations. Simple EOSs depend only on the +independent variables and are usually given in terms of the pressure, +i.e.\ $P = P(\rho, \epsilon)$ which then implicitly defines other +variables such as the temperature $T$, pressure derivatives $P_{\rho}, +P_{\epsilon}$ and the speed of sound $c_s$. + +However there is no physical reason to prefer such simple EOSs. A +realistic EOS will depend on the composition of the fluid as well as +the independent variables. This thorn is meant to provide an interface +so that a hydrodynamics code can depend on such a realistic EOS +without having to know about the details of the composition -- +without, in fact, needing an knowledge of the additional variables +required by the EOS at all. + +\section{Calling an EOS} + +The most efficient way of using the EOS is to call it to set grid +functions. The interface is simple on the face of it; one function +call will give you a {\em call handle}, and another function call will +actually set the EOS. The complexity comes in setting up the key value +tables involved in the function calls. + +\begin{FunctionDescription}{EOS\_SetupCall} + \label{Whisky_Dev_EOSBase_General_EOS_SetupCall} + + Sets up an equation of state call. If the call handle is stored + (which is recommended) then this only needs to be performed once at + startup time, and the call handle can be reused. + + \begin{SynopsisSection} + \begin{Synopsis}{C} +\begin{verbatim} +CCTK_INT call_handle = EOS_SetupCall(CCTK_INT table_handle) +\end{verbatim} + \end{Synopsis} + \begin{Synopsis}{Fortran} +\begin{verbatim} +CCTK_INT call_handle = EOS_SetupCall(CCTK_INT table_handle) +\end{verbatim} + \end{Synopsis} + \end{SynopsisSection} + + \begin{ResultSection} + \begin{ResultNote} + The {\tt call\_handle} return must be stored for later use in + the EOS call. The value should be $\geq 0$. Typically a level + 0 warning will be given rather than returning an error code. + \end{ResultNote} + \begin{Result}{$\geq 0$} + The call handle, to be stored for later use. + \end{Result} + \end{ResultSection} + + \begin{ParameterSection} + \begin{Parameter}{table\_handle} + The handle of an existing key value table. Appropriate + arguments will be described elsewhere. + \end{Parameter} + \end{ParameterSection} + + \begin{Discussion} + The complexity comes in setting up the key-value table to be + passed through. Effectively any arguments can be given that will + be interpreted by the EOS, but the following are expected (note + capitalization - it is always useful to set up the table using the + CASE INSENSITIVE flag): + \begin{itemize} + \item {\tt EOS Name}: This must correspond to the name that the + EOS thorn has registered. + \item {\tt Independent variable names}: This is a string (a + CCTK\_STRING) of whitespace separated names describing the + independent variables. Although there is no particular values + for these ``names'' required by this base thorns the following + conventions for variable names have been used in existing thorns + (name in parantheses is the variable name in {\sc whisky}): + \begin{itemize} + \item {\tt Rho}: Rest mass density ({\tt rho}) + \item {\tt SpecificInternalEnergy}: Specific internal energy + ({\tt eps}) + \item {\tt Pressure}: Pressure ({\tt press}) + \item {\tt DPressureDRho}: Partial derivative of pressure with + respect to rest mass density, all else being fixed ({\tt + dpdrho}) + \item {\tt DPressureDSpecificInternalEnergy}: Partial derivative + of pressure with respect to specific internal energy, all else + being fixed ({\tt dpdeps}) + \item {\tt c\_s\^{}2}: Speed of sound squared ({\tt cs2}). + \end{itemize} + \item {\tt Dependent variable names}: A string describing the + dependent variables, following the same syntax as the {\tt + Independent variable names} + \item {\tt N independent variables}: The number of independent + variables + \item {\tt N dependent variables}: The number of dependent + variables + \item {\tt Independent GFs}: An array of integers containing the + indices of the grid functions corresponding to the independent + variables. E.g., if the first dependent variable name is {\tt + Rho} which is contained in the grid function {\tt whisky::rho} + then the first entry of this array is found from {\tt + CCTK\_VarIndex("whisky::rho")}. + \item {\tt Dependent GFs}: An array of integers containing the + indices of the dependent grid functions, following the syntax of + the {\tt Independent GFs}. + \end{itemize} + \end{Discussion} + + \begin{SeeAlsoSection} + \begin{SeeAlso}{EOS\_SetGFs} + Sets the EOS. + \end{SeeAlso} + \end{SeeAlsoSection} +\end{FunctionDescription} + + + +\begin{FunctionDescription}{EOS\_SetGFs} + \label{Whisky_Dev_EOSBase_General_EOS_SetGFs} + + Actually sets the dependent GFs in an EOS call. The call must have + been previously set up using EOS\_SetupCall. Must be called from + routines scheduled in {\tt local} mode. + + \begin{SynopsisSection} + \begin{Synopsis}{C} +\begin{verbatim} +CCTK_INT ierr = EOS_SetGFs(CCTK_POINTER_TO_CONST cGH, CCTK_INT call_handle) +\end{verbatim} + \end{Synopsis} + \begin{Synopsis}{Fortran} +\begin{verbatim} +CCTK_INT ierr = EOS_SetGFs(CCTK_POINTER_TO_CONST cGH, CCTK_INT call_handle) +\end{verbatim} + \end{Synopsis} + \end{SynopsisSection} + + \begin{ResultSection} + \begin{ResultNote} + The {\tt call\_handle} should have been previously set up by + EOS\_SetupCall. Currently only successful returns (0) are + given. + \end{ResultNote} + \begin{Result}{\rm 0} + success. + \end{Result} + \end{ResultSection} + + \begin{ParameterSection} + \begin{Parameter}{cGH} + The Cactus GH structure, and the reason why this must be called + in {\tt local} mode. + \end{Parameter} + \begin{Parameter}{call\_handle} + An EOS call previously set up by EOS\_SetupCall. + \end{Parameter} + \end{ParameterSection} + + \begin{Discussion} + Once the EOS call has been setup this routine basically tells the + EOS function to apply the appropriate EOS calls at this point to + the appropriate arrays. + \end{Discussion} + + \begin{SeeAlsoSection} + \begin{SeeAlso}{EOS\_SetupCall} + Setup the EOS call. + \end{SeeAlso} + \end{SeeAlsoSection} +\end{FunctionDescription} + +\pagebreak +\section{Registering an EOS} + +Before you can use an EOS one first has to be registered. The best way +of learning how to do this is to look at the example thorns, such as +the ``generalized'' polytropic EOS (thorn {\tt EOS\_GeneralPolytrope}) or +ideal gas EOS (thorn {\tt EOS\_GeneralIdealFluid}). Here is just the +essential description. + +The essential thing that is required is a function (probably in C, +although in theory it's language independent) that sets arbitrary +sized arrays\footnote{The arbitrariness applies to the different + calls, not different arrays: all arrays, whether for independent or + dependent variables are assumed to have the same size in any given + call.} of dependent variables from the independent variables. This +function is registered using the aliased function {\tt + EOS\_RegisterCall}. This function, and the function pointer that +must be called, are as follows. + + + + +\begin{FunctionDescription}{EOS\_RegisterCall} + \label{Whisky_Dev_EOSBase_General_EOS_RegisterCall} + + Register an EOS with the base thorn. + + \begin{SynopsisSection} + \begin{Synopsis}{C} +\begin{verbatim} +CCTK_INT ierr = EOS_RegisterCall(CCTK_INT table_handle, \ + CCTK_INT CCTK_FPOINTER EOS_fn(...)) +\end{verbatim} + \end{Synopsis} + \begin{Synopsis}{Fortran} +\begin{verbatim} +CCTK_INT ierr = EOS_RegisterCall(CCTK_INT table_handle, \ + CCTK_INT CCTK_FPOINTER EOS_fn(...)) +\end{verbatim} + \end{Synopsis} + \end{SynopsisSection} + + \begin{ResultSection} + \begin{ResultNote} + The function pointer {\tt EOS\_fn} is described below on + page~\pageref{Whiskty_Dev_EOSBase_General_EOS_fn}. + + Currently only successful returns (0) are given. + \end{ResultNote} + \begin{Result}{\rm 0} + success. + \end{Result} + \end{ResultSection} + + \begin{ParameterSection} + \begin{Parameter}{table\_handle} + A key/value table containing any persistent information that the + EOS thorn may want to store. This is not used by the base thorn, + and is there for the convenience of the EOS thorn. + \end{Parameter} + \begin{Parameter}{EOS\_fn} + A function pointer for the EOS call itself, described below. + \end{Parameter} + \end{ParameterSection} + + \begin{Discussion} + The table can be used to differentiate between different + calls. For example, if one thorn implements many different + EOSs and the number is not known at compile time (e.g., a table + interpolator thorn that provides multiple tables) then only one + registration need take place, and the key/value table can be used + store which (interpolation) table is being used in the particular + call. + \end{Discussion} + + \begin{SeeAlsoSection} + \begin{SeeAlso}{EOS\_fn} + The actual EOS function. + \end{SeeAlso} + \end{SeeAlsoSection} +\end{FunctionDescription} + + +\begin{FunctionDescription}{EOS\_fn} + \label{Whisky_Dev_EOSBase_General_EOS_fn} + + The actual EOS function that must be provided. + + \begin{SynopsisSection} + \begin{Synopsis}{C} +\begin{verbatim} +CCTK_INT ierr = EOS_fn(CCTK_INT param_table, \ + CCTK_INT n_elems, \ + CCTK_POINTER* indep_arrays, \ + CCTK_INT* which_dep_arrays_to_set, \ + CCTK_POINTER* dep_arrys) +\end{verbatim} + \end{Synopsis} + \begin{Synopsis}{Fortran} +\begin{verbatim} +CCTK_INT ierr = EOS_fn(CCTK_INT param_table, \ + CCTK_INT n_elems, \ + CCTK_POINTER* indep_arrays, \ + CCTK_INT* which_dep_arrays_to_set, \ + CCTK_POINTER* dep_arrys) +\end{verbatim} + \end{Synopsis} + \end{SynopsisSection} + + \begin{ResultSection} + \begin{ResultNote} + Currently only successful returns (0) are given. + \end{ResultNote} + \begin{Result}{\rm 0} + success. + \end{Result} + \end{ResultSection} + + \begin{ParameterSection} + \begin{Parameter}{param\_table} + A key/value table containing any persistent information that the + EOS thorn may want to store. This is not used by the base thorn, + and is there for the convenience of the EOS thorn. + \end{Parameter} + \begin{Parameter}{n\_elems} + The size of the arrays that are passed in. + \end{Parameter} + \begin{Parameter}{indep\_arrays} + The independent arrays (should essentially be cast to a {\tt + CCTK\_REAL**}). + \end{Parameter} + \begin{Parameter}{which\_dep\_arrays\_to\_set} + An array telling the EOS thorn which dependent arrays should be + set in this thorn. This is important because dependent arrays + that are not needed will NOT be passed in the call; see below. + \end{Parameter} + \begin{Parameter}{dep\_arrays} + The dependent arrays (should essentially be cast to a {\tt + CCTK\_REAL**}). Note that you should not assume that all these + pointers are non-null (hence the difficulty in using this with + Fortran). In general, if the calling thorn does NOT request that + a dependent variable be set then the equivalent pointer WILL be + null. + \end{Parameter} + \end{ParameterSection} + + \begin{Discussion} + The table can be used to differentiate between different + calls. For example, if one thorn implements many different + EOSs and the number is not known at compile time (e.g., a table + interpolator thorn that provides multiple tables) then only one + registration need take place, and the key/value table can be used + store which (interpolation) table is being used in the particular + call. + \end{Discussion} + + \begin{SeeAlsoSection} + \begin{SeeAlso}{EOS\_RegisterCall} + Register the EOS function with the base thorn. + \end{SeeAlso} + \end{SeeAlsoSection} +\end{FunctionDescription} + + + +\begin{thebibliography}{9} + +\end{thebibliography} + +% Do not delete next line +% END CACTUS THORNGUIDE + +\end{document} diff --git a/interface.ccl b/interface.ccl new file mode 100755 index 0000000..8d82044 --- /dev/null +++ b/interface.ccl @@ -0,0 +1,29 @@ +# Interface definition for thorn EOSBase_General +# $Header$ + +implements: EOSBase + +INCLUDES: EOS_Utils.h IN EOS_GeneralUtils.h + +CCTK_INT FUNCTION EOS_RegisterCall(CCTK_INT IN table_handle, \ + CCTK_INT IN CCTK_FPOINTER \ + EOS_fn(CCTK_INT IN param_table, \ + CCTK_INT IN n_elems, \ + CCTK_POINTER ARRAY IN indeps, \ + CCTK_INT ARRAY IN which_deps, \ + CCTK_POINTER ARRAY OUT deps)) +PROVIDES FUNCTION EOS_RegisterCall WITH EOSBase_Register LANGUAGE C + +CCTK_INT FUNCTION EOS_SetupCall(CCTK_INT IN table_handle) +PROVIDES FUNCTION EOS_SetupCall WITH SetupCall LANGUAGE C + +CCTK_INT FUNCTION EOS_SetGFs(CCTK_POINTER_TO_CONST IN GH, \ + CCTK_INT IN call_handle) +PROVIDES FUNCTION EOS_SetGFs WITH SetGFs LANGUAGE C + +CCTK_INT FUNCTION EOS_SetArrays(CCTK_INT IN call_handle) +PROVIDES FUNCTION EOS_SetArrays WITH SetArrays LANGUAGE C + +CCTK_INT FUNCTION EOS_SetInverseArrays(CCTK_INT IN call_handle, \ + CCTK_INT IN table_handle) +PROVIDES FUNCTION EOS_SetInverseArrays WITH SetInverseArrays LANGUAGE C diff --git a/param.ccl b/param.ccl new file mode 100755 index 0000000..f1d72a1 --- /dev/null +++ b/param.ccl @@ -0,0 +1,2 @@ +# Parameter definitions for thorn EOSBase_General +# $Header$ diff --git a/schedule.ccl b/schedule.ccl new file mode 100755 index 0000000..64b959c --- /dev/null +++ b/schedule.ccl @@ -0,0 +1,8 @@ +# Schedule definitions for thorn EOSBase_General +# $Header$ + + +schedule group EOSBase_GeneralRegister AT WRAGH +{ + +} "Register EOS Thorns with EOSBase_General" diff --git a/src/EOSBase_Register.c b/src/EOSBase_Register.c new file mode 100755 index 0000000..3275c85 --- /dev/null +++ b/src/EOSBase_Register.c @@ -0,0 +1,1094 @@ +#include +#include +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "cctk_Arguments.h" + +#include "util_String.h" +#include "util_ErrorCodes.h" +#include "util_Table.h" + +#include "EOS_Utils.h" + +#define EOSBASE_DBG 1 + +/* + This part is for thorns providing an EOS. +*/ + +/* + The structure for a single EOS function. +*/ + +typedef struct +{ + const char* eos_name; /* The name of the EOS, required to match the call */ + CCTK_INT param_table; /* The parameter table allows the EOS + to store persistent information */ + CCTK_INT n_indeps; /* The number of independent variables + the EOS requires */ + CCTK_INT n_deps; /* The number of dependent variables + the EOS can return */ + char **indep_names; /* The names (labels) of the independent variables */ + char **dep_names; /* The names (labels) of the dependent variables */ + CCTK_INT (*EOS_fn)(const CCTK_INT, + const CCTK_INT, + const CCTK_REAL**, + const CCTK_INT*, + CCTK_REAL**); /* The actual function pointer */ +} EOS_Function; + +/* + The list of all EOS functions. +*/ + +struct EOSFunctionList +{ + CCTK_INT n_eos_fns; + EOS_Function* Fns; +} FnList; + + /*@@ + @routine SetupFnList + @date Fri Jun 10 04:37:10 2005 + @author Ian Hawke + @desc + Initialize the list of functions. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +void SetupFnList() +{ + FnList.n_eos_fns = 0; + FnList.Fns = NULL; +} + + /*@@ + @routine EOSBase_Register + @date Fri Jun 10 04:37:51 2005 + @author Ian Hawke + @desc + The (aliased) function called by an EOS thorn to register its call. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +CCTK_INT +EOSBase_Register(const CCTK_INT registered_table_handle, + CCTK_INT registered_EOS_fn(const CCTK_INT param_table, + const CCTK_INT n_dims, + const CCTK_POINTER* indep_vars, + const CCTK_INT* which_deps_to_set, + CCTK_POINTER* dep_vars)) +{ + + CCTK_INT ierr= 0, nfn, var, table_ierr; + const char *tmp_indep_names; + const char *tmp_dep_names; + const char* tmpbuffer; + + CCTK_INT registered_n_indeps, registered_n_deps, strlength; + + ++(FnList.n_eos_fns); + FnList.Fns = (EOS_Function*)realloc(FnList.Fns, + (FnList.n_eos_fns) * + sizeof(EOS_Function)); + nfn = FnList.n_eos_fns - 1; + + (FnList.Fns)[nfn].param_table = registered_table_handle; + + table_ierr = Util_TableGetInt(registered_table_handle, + ®istered_n_indeps, + "N independent variables"); + if (table_ierr != 1) + { + CCTK_WARN(0, "What's the number of independent variables?"); + } + + table_ierr = Util_TableGetInt(registered_table_handle, + ®istered_n_deps, + "N dependent variables"); + if (table_ierr != 1) + { + CCTK_WARN(0, "What's the number of dependent variables?"); + } + + (FnList.Fns)[nfn].n_indeps = registered_n_indeps; + (FnList.Fns)[nfn].n_deps = registered_n_deps; + + strlength = Util_TableGetString(registered_table_handle, + 0, NULL, + "EOS Name"); + if (strlength < 1) + { + CCTK_WARN(0, "What EOS do you actually want?"); + } + (FnList.Fns)[nfn].eos_name = + (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(registered_table_handle, + (strlength+1), (FnList.Fns)[nfn].eos_name, + "EOS name"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + strlength = Util_TableGetString(registered_table_handle, + 0, NULL, + "Independent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Which independent do you actually want?"); + } + tmp_indep_names = (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(registered_table_handle, + (strlength+1), tmp_indep_names, + "Independent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + strlength = Util_TableGetString(registered_table_handle, + 0, NULL, + "Dependent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Which dependent variables do you actually want?"); + } + tmp_dep_names = (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(registered_table_handle, + (strlength+1), tmp_dep_names, + "Dependent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + (FnList.Fns)[nfn].EOS_fn = registered_EOS_fn; + + (FnList.Fns)[nfn].indep_names = (char**)malloc(registered_n_indeps * + sizeof(char*)); + tmpbuffer = EOS_StrSep(&tmp_indep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the independent name string; empty???"); + } + for (var = 0; var < registered_n_indeps; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&tmp_indep_names, " "); + } + ((FnList.Fns)[nfn].indep_names)[var] = Util_Strdup(tmpbuffer); + tmpbuffer = EOS_StrSep(&tmp_indep_names, " "); + } + + (FnList.Fns)[nfn].dep_names = (char**)malloc(registered_n_deps * + sizeof(char*));; + tmpbuffer = EOS_StrSep(&tmp_dep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the dependent name string; empty???"); + } + for (var = 0; var < registered_n_deps; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&tmp_dep_names, " "); + } + ((FnList.Fns)[nfn].dep_names)[var] = Util_Strdup(tmpbuffer); + tmpbuffer = EOS_StrSep(&tmp_dep_names, " "); + } + + ierr = 0; + +#ifdef EOSBASE_DBG + printf("An eos call has been registered. The call number was %d.\n" + "The eos name is '%s'.\n" + "The number of independent variables is %d.\n" + "The number of dependent variables is %d.\n", + FnList.n_eos_fns, + (FnList.Fns)[nfn].eos_name, + (FnList.Fns)[nfn].n_indeps, + (FnList.Fns)[nfn].n_deps); + for (var = 0; var < (FnList.Fns)[nfn].n_indeps; ++var) + { + printf("Independent variable %d is '%s'\n", + var, (FnList.Fns)[nfn].indep_names[var]); + } + for (var = 0; var < (FnList.Fns)[nfn].n_deps; ++var) + { + printf("Dependent variable %d is '%s'\n", + var, (FnList.Fns)[nfn].dep_names[var]); + } +#endif + + return ierr; +} + +/* + This part is for thorns that want to call the EOS. +*/ + +/* + The structure describing a single EOS 'call'. +*/ + +typedef struct +{ + CCTK_INT fn_number; /* The number (in the EOS_FnList) of the EOS function */ + CCTK_INT* indep_gfs; /* List of independent GF indices + (if not using arrays) */ + CCTK_INT* dep_gfs; /* List of dependent GF indices + (if not using arrays) */ + CCTK_INT* which_deps_to_set; /* List of which of the dependent variables + should be set */ + CCTK_INT n_elems; /* Number of elements in the GFs/arrays */ + CCTK_REAL** indep_vars; /* Pointers to the independent variable arrays + (if not using GFs) */ + CCTK_REAL** dep_vars; /* Pointers to the dependent variable arrays + (if not using GFs) */ +} EOS_Call; + +/* + The structure describing the list of all EOS calls. +*/ + +struct EOSCallList +{ + CCTK_INT n_eos_calls; + EOS_Call* Calls; +} CallList; + + /*@@ + @routine SetupCallList + @date Fri Jun 10 04:46:17 2005 + @author Ian Hawke + @desc + Initialize the call list. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +void SetupCallList() +{ + CallList.n_eos_calls = 0; + CallList.Calls = NULL; +} + + /*@@ + @routine SetupCall + @date Fri Jun 10 04:46:31 2005 + @author Ian Hawke + @desc + Set up a single function call. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +CCTK_INT SetupCall(CCTK_INT table_handle) +{ + + CCTK_INT ncall, i, strlength, call_number, type_code, n_entries, + ierr, n_elements, var, indep_var, dep_var; + const char* fn_name; + const char *local_indep_names; + const char *local_dep_names; + char *tmpbuffer; + CCTK_INT *tmp_indep_gfs; + CCTK_INT *tmp_dep_gfs; + CCTK_REAL **tmp_indep_arrays; + CCTK_REAL **tmp_dep_arrays; + + ++(CallList.n_eos_calls); + CallList.Calls = (EOS_Call*)realloc(CallList.Calls, + (CallList.n_eos_calls) * + sizeof(EOS_Call)); + ncall = CallList.n_eos_calls - 1; + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "EOS Name"); + if (strlength < 1) + { + CCTK_WARN(0, "What EOS do you actually want?"); + } + fn_name = (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(table_handle, + (strlength+1), fn_name, + "EOS Name"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + for (call_number = 0; call_number < FnList.n_eos_fns; ++call_number) + { + if (CCTK_Equals(fn_name, FnList.Fns[call_number].eos_name)) break; + } + if (call_number < FnList.n_eos_fns) + { + CallList.Calls[ncall].fn_number = call_number; + } + else + { + CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, + "Failed to find eos function '%s'.", + fn_name); + } + + if (Util_TableQueryValueInfo(table_handle, &type_code, &n_entries, + "Independent GFs")) + { + if (type_code != CCTK_VARIABLE_INT) + { + CCTK_WARN(0, "The independent GF indices must be passed as " + "a CCTK_INT array."); + } + if (n_entries != (FnList.Fns[call_number]).n_indeps) + { + CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, + "The EOS function '%s' expects %d independent variables.\n" + "Your GF list only contains %d entries.", + fn_name, (FnList.Fns[call_number]).n_indeps, + n_entries); + } + tmp_indep_gfs = (CCTK_INT*)malloc(n_entries * sizeof(CCTK_INT)); + (CallList.Calls[ncall]).indep_gfs = (CCTK_INT*)malloc(n_entries * + sizeof(CCTK_INT)); + n_elements = Util_TableGetIntArray(table_handle, + (FnList.Fns[call_number]).n_indeps, + tmp_indep_gfs, + "Independent GFs"); + if (n_elements != n_entries) + { + CCTK_WARN(0, "What happened here?"); + } + /* Now we have to order the independent gfs correctly */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Independent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Need the independent variable names"); + } + local_indep_names = + (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(table_handle, + (strlength+1), local_indep_names, + "Independent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the independent name string; empty???"); + } + for (var = 0; var < n_entries; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + } + + (CallList.Calls[ncall]).indep_gfs[var] = -1; + for (indep_var = 0; indep_var < n_entries; ++indep_var) + { + if ( CCTK_Equals((FnList.Fns[call_number]).indep_names[indep_var], + tmpbuffer) ) + { + (CallList.Calls[ncall]).indep_gfs[var] = tmp_indep_gfs[indep_var]; + } + } + if ( (CallList.Calls[ncall]).indep_gfs[var] < 0 ) + { + CCTK_WARN(0, "Failed to set up the independent variables?"); + } + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + } + + if (Util_TableQueryValueInfo(table_handle, &type_code, &n_entries, + "Dependent GFs")) + { + if (type_code != CCTK_VARIABLE_INT) + { + CCTK_WARN(0, "The dependent GF indices must be passed as " + "a CCTK_INT array."); + } + if (n_entries > (FnList.Fns[call_number]).n_deps) + { + CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, + "The EOS function '%s' expects at most %d dependent" + " variables.\n" + "Your GF list contains %d entries.", + fn_name, (FnList.Fns[call_number]).n_deps, + n_entries); + } + tmp_dep_gfs = (CCTK_INT*)malloc(n_entries * sizeof(CCTK_INT)); + (CallList.Calls[ncall]).dep_gfs = + (CCTK_INT*)malloc((FnList.Fns[call_number]).n_deps * sizeof(CCTK_INT)); + (CallList.Calls[ncall]).which_deps_to_set = + (CCTK_INT*)malloc((FnList.Fns[call_number]).n_deps * sizeof(CCTK_INT)); + n_elements = Util_TableGetIntArray(table_handle, + n_entries, + tmp_dep_gfs, + "Dependent GFs"); + if (n_elements != n_entries) + { + CCTK_WARN(0, "What happened here?"); + } + + /* Now we have to order the dependent gfs correctly */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Dependent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Need the dependent variable names"); + } + local_dep_names = + (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(table_handle, + (strlength+1), local_dep_names, + "Dependent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the independent name string; empty???"); + } + for (dep_var = 0; + dep_var < (FnList.Fns[call_number]).n_deps; + ++dep_var) + { + (CallList.Calls[ncall]).dep_gfs[dep_var] = -1; + (CallList.Calls[ncall]).which_deps_to_set[dep_var] = 0; + } + for (var = 0; var < n_entries; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + } + + for (dep_var = 0; + dep_var < (FnList.Fns[call_number]).n_deps; + ++dep_var) + { + if ( CCTK_Equals((FnList.Fns[call_number]).dep_names[dep_var], + tmpbuffer) ) + { + (CallList.Calls[ncall]).dep_gfs[dep_var] = tmp_dep_gfs[var]; + (CallList.Calls[ncall]).which_deps_to_set[dep_var] = 1; + } + } + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + } + } + else + { + CCTK_WARN(0, "If you set the 'Independent GFs' key you should also\n" + "set the 'Dependent GFs' key."); + } + (CallList.Calls[ncall]).indep_vars = + (CCTK_REAL**)malloc((FnList.Fns[call_number]).n_indeps * + sizeof(CCTK_REAL*)); + for (var = 0; var < (FnList.Fns[call_number]).n_indeps; ++var) + { + (CallList.Calls[ncall]).indep_vars[var] = NULL; + } + (CallList.Calls[ncall]).dep_vars = + (CCTK_REAL**)malloc((FnList.Fns[call_number]).n_deps * + sizeof(CCTK_REAL*)); + for (var = 0; var < (FnList.Fns[call_number]).n_deps; ++var) + { + (CallList.Calls[ncall]).dep_vars[var] = NULL; + } + } + else /* Setting up a direct array call */ + { + (CallList.Calls[ncall]).indep_gfs = NULL; + (CallList.Calls[ncall]).dep_gfs = NULL; + + if (Util_TableQueryValueInfo(table_handle, &type_code, &n_entries, + "N array elements")) + { + if (type_code != CCTK_VARIABLE_INT) + { + CCTK_WARN(0, "The number of elements of the array in a direct " + "array call must be passed as a CCTK_INT."); + } + n_elements = Util_TableGetInt(table_handle, + &((CallList.Calls[ncall]).n_elems), + "N array elements"); + } + else + { + CCTK_WARN(0, "If setting up a direct array call the number of " + "elements\n(key 'N array elements') must be set"); + } + + if (Util_TableQueryValueInfo(table_handle, &type_code, &n_entries, + "Independent arrays")) + { + if (type_code != CCTK_VARIABLE_POINTER) + { + CCTK_WARN(0, "The independent arrays in a direct " + "array call must be passed as as a CCTK_POINTER array."); + } + if (n_entries != (FnList.Fns[call_number]).n_indeps) + { + CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, + "The EOS function '%s' expects %d independent variables.\n" + "Your direct call list only contains %d entries.", + fn_name, (FnList.Fns[call_number]).n_indeps, + n_entries); + } + tmp_indep_arrays = (CCTK_REAL**)malloc(n_entries * sizeof(CCTK_REAL*)); + (CallList.Calls[ncall]).indep_vars = + (CCTK_REAL**)malloc(n_entries * sizeof(CCTK_REAL*)); + n_elements = + Util_TableGetPointerArray(table_handle, + (FnList.Fns[call_number]).n_indeps, + (CCTK_POINTER*)tmp_indep_arrays, + "Independent arrays"); + if (n_elements != n_entries) + { + CCTK_WARN(0, "What happened here?"); + } + /* Now we have to order the independent gfs correctly */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Independent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Need the independent variable names"); + } + local_indep_names = + (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(table_handle, + (strlength+1), local_indep_names, + "Independent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the independent name string; empty???"); + } + for (var = 0; var < n_entries; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + } + + (CallList.Calls[ncall]).indep_vars[var] = NULL; + for (indep_var = 0; indep_var < n_entries; ++indep_var) + { + if ( CCTK_Equals((FnList.Fns[call_number]).indep_names[indep_var], + tmpbuffer) ) + { + (CallList.Calls[ncall]).indep_vars[var] = + tmp_indep_arrays[indep_var]; + } + } + if ( !((CallList.Calls[ncall]).indep_vars[var]) ) + { + CCTK_WARN(0, "Failed to set up the independent variables?"); + } + tmpbuffer = EOS_StrSep(&local_indep_names, " "); + } + + } + else + { + CCTK_WARN(0, "If setting up a direct array call the independent " + "arrays\n(key 'Independent arrays') must be set"); + } + + + if (Util_TableQueryValueInfo(table_handle, &type_code, &n_entries, + "Dependent arrays")) + { + if (type_code != CCTK_VARIABLE_POINTER) + { + CCTK_WARN(0, "The dependent arrays in a direct " + "array call must be passed as as a CCTK_POINTER array."); + } + if (n_entries >= (FnList.Fns[call_number]).n_deps) + { + CCTK_VWarn(0, __LINE__, __FILE__, CCTK_THORNSTRING, + "The EOS function '%s' expects at most %d dependent " + "variables.\n" + "Your direct call list only contains %d entries.", + fn_name, (FnList.Fns[call_number]).n_deps, + n_entries); + } + tmp_dep_arrays = (CCTK_REAL**)malloc(n_entries * sizeof(CCTK_REAL*)); + (CallList.Calls[ncall]).dep_vars = + (CCTK_REAL**)malloc((FnList.Fns[call_number]).n_deps * + sizeof(CCTK_REAL*)); + (CallList.Calls[ncall]).which_deps_to_set = + (CCTK_INT*)malloc((FnList.Fns[call_number]).n_deps * + sizeof(CCTK_INT)); + n_elements = + Util_TableGetPointerArray(table_handle, + n_entries, + (CCTK_POINTER*)tmp_dep_arrays, + "Dependent arrays"); + if (n_elements != n_entries) + { + CCTK_WARN(0, "What happened here?"); + } + /* Now we have to order the dependent gfs correctly */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Dependent variable names"); + if (strlength < 1) + { + CCTK_WARN(0, "Need the dependent variable names"); + } + local_dep_names = + (const char*)malloc((strlength+1) * sizeof(char)); + ierr = Util_TableGetString(table_handle, + (strlength+1), local_dep_names, + "Dependent variable names"); + if (ierr != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + if (tmpbuffer == NULL) /* line is empty */ + { + CCTK_WARN(0, "Error in the independent name string; empty???"); + } + for (dep_var = 0; dep_var < n_entries; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + } + + (CallList.Calls[ncall]).dep_vars[var] = NULL; + for (dep_var = 0; + dep_var < (FnList.Fns[call_number]).n_deps; + ++dep_var) + { + (CallList.Calls[ncall]).dep_vars[dep_var] = NULL; + (CallList.Calls[ncall]).which_deps_to_set[dep_var] = 0; + } + for (var = 0; var < n_entries; ++var) + { + while (*tmpbuffer == '\0') + { + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + } + + for (dep_var = 0; + dep_var < (FnList.Fns[call_number]).n_deps; + ++dep_var) + { + if ( CCTK_Equals((FnList.Fns[call_number]).dep_names[dep_var], + tmpbuffer) ) + { + (CallList.Calls[ncall]).dep_vars[dep_var] = tmp_dep_arrays[var]; + (CallList.Calls[ncall]).which_deps_to_set[dep_var] = 1; + } + } + tmpbuffer = EOS_StrSep(&local_dep_names, " "); + } + } + + } + else + { + CCTK_WARN(0, "If setting up a direct array call the dependent " + "arrays\n(key 'Dependent arrays') must be set"); + } + + } + + +#ifdef EOSBASE_DBG + printf("An eos call has been setup. The call handle was %d.\n" + "The eos name is '%s', corresponding to registered eos %d.\n" + "The registered structure really believes a fn number %d.\n", + ncall, + (FnList.Fns)[call_number].eos_name, call_number, + (CallList.Calls)[ncall].fn_number); + if ( (CallList.Calls)[ncall].indep_gfs) + { + for (var = 0; var < (FnList.Fns)[call_number].n_indeps; ++var) + { + printf("Independent gf number %d has index '%d' (name '%s').\n", + var, (CallList.Calls)[ncall].indep_gfs[var], + (FnList.Fns)[call_number].indep_names[var]); + } + for (var = 0; var < (FnList.Fns)[call_number].n_deps; ++var) + { + printf("Dependent gf number %d has index '%d' (to_set = %d, name '%s').\n", + var, (CallList.Calls)[ncall].dep_gfs[var], + (CallList.Calls)[ncall].which_deps_to_set[var], + (FnList.Fns)[call_number].dep_names[var]); + } + } +#endif + + return ncall; +} + + /*@@ + @routine SetGFs + @date Fri Jun 10 05:08:20 2005 + @author Ian Hawke + @desc + The aliased function call by the user thorn that actually sets + the GFs (in this case). + The call is passed on to the EOS thorn once the appropriate + information has been pulled out of the table. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +CCTK_INT SetGFs(const CCTK_POINTER_TO_CONST _GH, const CCTK_INT call_number) +{ + + const cGH* const GH = (const cGH* const) _GH; + + CCTK_INT ierr = 0; + + CCTK_INT totalsize = 1; + CCTK_INT dim; + CCTK_INT fn_number, var; + + for (dim = 0; dim < GH->cctk_dim; ++dim) + { + totalsize *= GH->cctk_lsh[dim]; + } + + fn_number = (CallList.Calls)[call_number].fn_number; + + for (var = 0; var < (FnList.Fns)[fn_number].n_indeps; ++var) + { + (CallList.Calls)[call_number].indep_vars[var] = + (CCTK_REAL*)CCTK_VarDataPtrI(GH, 0, + (CallList.Calls)[call_number].indep_gfs[var]); + } + + for (var = 0; var < (FnList.Fns)[fn_number].n_deps; ++var) + { + if ((CallList.Calls)[call_number].which_deps_to_set[var]) + { + (CallList.Calls)[call_number].dep_vars[var] = + (CCTK_REAL*)CCTK_VarDataPtrI(GH, 0, + (CallList.Calls)[call_number].dep_gfs[var]); + } + else + { + (CallList.Calls)[call_number].dep_vars[var] = NULL; + } + } + + ierr = ((FnList.Fns)[fn_number].EOS_fn) + ((FnList.Fns)[fn_number].param_table, + totalsize, + (CallList.Calls)[call_number].indep_vars, + (CallList.Calls)[call_number].which_deps_to_set, + (CallList.Calls)[call_number].dep_vars); + + return ierr; +} + + /*@@ + @routine SetArrays + @date Fri Jun 10 05:09:40 2005 + @author Ian Hawke + @desc + The aliased function call by the user thorn that actually sets + the arrays (in this case). + The call is passed on to the EOS thorn once the appropriate + information has been pulled out of the table. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + +CCTK_INT SetArrays(const CCTK_INT call_number) +{ + + CCTK_INT ierr = 0; + + CCTK_INT fn_number, totalsize; + + fn_number = (CallList.Calls)[call_number].fn_number; + + totalsize = (CallList.Calls)[call_number].n_elems; + + ierr = ((FnList.Fns)[fn_number].EOS_fn) + ((FnList.Fns)[fn_number].param_table, + totalsize, + (CallList.Calls)[call_number].indep_vars, + (CallList.Calls)[call_number].which_deps_to_set, + (CallList.Calls)[call_number].dep_vars); + + return ierr; +} + +CCTK_INT SetInverseArrays(const CCTK_INT call_number, + const CCTK_INT table_handle) +{ + + CCTK_INT ierr = 0, in_error = 1; + CCTK_INT fn_number, totalsize, i; + CCTK_INT unknown_indep_number, known_dep_number; + CCTK_INT strlength, strlength_recv; + + CCTK_REAL guess_factor = 1.01, threshold = 1e-12; + CCTK_REAL *indep_min, *indep_max, *unknown_indep, + *known_result, *tmp_result, *max_result; + + char *tmpbuffer; + + fn_number = (CallList.Calls)[call_number].fn_number; + + totalsize = (CallList.Calls)[call_number].n_elems; + + /* Find out which independent variable needs setting */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Unknown independent name"); + if (strlength < 1) + { + CCTK_WARN(0, "We need the independent variable name that you" + "actually want to set\n (key: 'Unknown independent name')"); + } + tmpbuffer = + (const char*)malloc((strlength+1) * sizeof(char)); + strlength_recv = Util_TableGetString(table_handle, + (strlength+1), tmpbuffer, + "Unknown independent name"); + if (strlength_recv != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + unknown_indep_number = -1; + for (i = 0; i < (FnList.Fns)[fn_number].n_indeps; ++i) + { + if (CCTK_Equals(tmpbuffer, (FnList.Fns)[fn_number].indep_names[i])) + { + unknown_indep_number = i; + } + } + if (unknown_indep_number < 0) + { + CCTK_WARN(0, "Unknown independent variable not recognized"); + } + +#ifdef EOSBASE_DBG + printf("Inverse array call: unknown indep '%s' index %d.\n", + tmpbuffer, unknown_indep_number); +#endif + + /* Find out which dependent variable is actually known */ + + strlength = Util_TableGetString(table_handle, + 0, NULL, + "Known dependent name"); + if (strlength < 1) + { + CCTK_WARN(0, "We need the dependent variable name that you" + "have already set\n (key: 'Known dependent name')"); + } + tmpbuffer = + (const char*)malloc((strlength+1) * sizeof(char)); + strlength_recv = Util_TableGetString(table_handle, + (strlength+1), tmpbuffer, + "Known dependent name"); + if (strlength_recv != strlength) + { + CCTK_WARN(0, "What happened here?"); + } + + known_dep_number = -1; + for (i = 0; i < (FnList.Fns)[fn_number].n_deps; ++i) + { + if (CCTK_Equals(tmpbuffer, (FnList.Fns)[fn_number].dep_names[i])) + { + known_dep_number = i; + } + } + if (known_dep_number < 0) + { + CCTK_WARN(0, "Known dependent variable not recognized"); + } + +#ifdef EOSBASE_DBG + printf("Inverse array call: known dep '%s' index %d.\n", + tmpbuffer, known_dep_number); +#endif + + /* Ensure that the 'known' variable is set */ + + (CallList.Calls)[call_number].which_deps_to_set[known_dep_number] = 1; + + /* Juggle... */ + + unknown_indep = + (CallList.Calls)[call_number].indep_vars[unknown_indep_number]; + known_result = + (CallList.Calls)[call_number].dep_vars[known_dep_number]; + + indep_min = (CCTK_REAL*)malloc(totalsize * sizeof(CCTK_REAL)); + indep_max = (CCTK_REAL*)malloc(totalsize * sizeof(CCTK_REAL)); + tmp_result = (CCTK_REAL*)malloc(totalsize * sizeof(CCTK_REAL)); + max_result = (CCTK_REAL*)malloc(totalsize * sizeof(CCTK_REAL)); + + for (i = 0; i < totalsize; ++i) + { + indep_min[i] = unknown_indep[i] / guess_factor; + indep_max[i] = unknown_indep[i] * guess_factor; + +#ifdef EOSBASE_DBG + printf("Inverse array call: index %d (/%d), range [%g, %g].\n", + i, totalsize, indep_min[i], indep_max[i]); +#endif + + } + + for (i = 0; i < totalsize; ++i) + { + unknown_indep[i] = indep_max[i]; + } + + (CallList.Calls)[call_number].dep_vars[known_dep_number] = max_result; + ierr = ((FnList.Fns)[fn_number].EOS_fn) + ((FnList.Fns)[fn_number].param_table, + totalsize, + (CallList.Calls)[call_number].indep_vars, + (CallList.Calls)[call_number].which_deps_to_set, + (CallList.Calls)[call_number].dep_vars); + + for (i = 0; i < totalsize; ++i) + { + unknown_indep[i] = indep_min[i]; + } + + (CallList.Calls)[call_number].dep_vars[known_dep_number] = tmp_result; + ierr = ((FnList.Fns)[fn_number].EOS_fn) + ((FnList.Fns)[fn_number].param_table, + totalsize, + (CallList.Calls)[call_number].indep_vars, + (CallList.Calls)[call_number].which_deps_to_set, + (CallList.Calls)[call_number].dep_vars); + + for (i = 0; i < totalsize; ++i) + { + if ( ((known_result[i] - tmp_result[i]) * + (known_result[i] - max_result[i])) > 0 ) + { +#ifdef EOSBASE_DBG + printf("Inverse array call: index %d (/%d), bracketing failed?\n" + "Range [%g, %g], result %g.\n", + i, totalsize, tmp_result[i], max_result[i], known_result[i]); +#endif + + CCTK_WARN(0, "Failed to bracket root!"); + } + unknown_indep[i] = 0.5 * (indep_min[i] + indep_max[i]); + } + + + while (in_error) + { + + ierr = ((FnList.Fns)[fn_number].EOS_fn) + ((FnList.Fns)[fn_number].param_table, + totalsize, + (CallList.Calls)[call_number].indep_vars, + (CallList.Calls)[call_number].which_deps_to_set, + (CallList.Calls)[call_number].dep_vars); + + in_error = 0; + + for (i = 0; i < totalsize; ++i) + { + if ( ((known_result[i] - tmp_result[i]) * + (known_result[i] - max_result[i])) < 0 ) + { + indep_min[i] = unknown_indep[i]; + } + else + { + indep_max[i] = unknown_indep[i]; + max_result[i] = tmp_result[i]; + } + unknown_indep[i] = 0.5 * (indep_min[i] + indep_max[i]); + if (indep_max[i] - indep_min[i] > threshold) + { + in_error = 1; + } + } + + } + + (CallList.Calls)[call_number].dep_vars[known_dep_number] = known_result; + + free(indep_min); indep_min = NULL; + free(indep_max); indep_max = NULL; + free(tmp_result); tmp_result = NULL; + free(max_result); max_result = NULL; + + return ierr; +} diff --git a/src/EOS_Utils.c b/src/EOS_Utils.c new file mode 100755 index 0000000..815a665 --- /dev/null +++ b/src/EOS_Utils.c @@ -0,0 +1,68 @@ +#include +#include +#include +#include + +#include "cctk.h" +#include "cctk_Parameters.h" +#include "cctk_Arguments.h" + +#include "util_String.h" +#include "util_ErrorCodes.h" +#include "util_Table.h" + + /*@@ + @routine EOS_StrSep + @date Wed Mar 2 14:57:50 2005 + @author Ian Hawke + @desc + A wrapper to Util_StrSep that returns the last token if there + are no more delimiters. Note that the documentation is incorrect; + delim_set (here delim) cannot be a set but must be a single + character. + @enddesc + @calls + @calledby + @history + + @endhistory + +@@*/ + + +const char * EOS_StrSep(const char ** string_ptr, const char * delim); + +const char * EOS_StrSep(const char ** string_ptr, const char * delim) +{ + + const char * token; + const char ** string; + + string = string_ptr; + + if (string == NULL) + { + return NULL; + } + + token = Util_StrSep(string_ptr, delim); + + if ( (token == NULL) && (strlen(*string) > 0) && + (!(CCTK_Equals(*string, "\n"))) ) + { + string_ptr = string; + token = Util_StrSep(string_ptr, "\n"); + if ( (token == NULL) && (strlen(*string) > 0) ) + { + string_ptr = '\0'; + token = *string; + } + } + +#ifdef EOS_GTR_DEBUG + printf("EOS_StrSep: token '%s' and string_ptr '%s' (%s)\n", + token, *string_ptr, *string); +#endif + + return token; +} diff --git a/src/EOS_Utils.h b/src/EOS_Utils.h new file mode 100755 index 0000000..8aa6793 --- /dev/null +++ b/src/EOS_Utils.h @@ -0,0 +1,16 @@ + +#ifndef _EOS_UTILS_H_ +#define _EOS_UTILS_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +const char * EOS_StrSep(const char ** string_ptr, const char * delim); + +#ifdef __cplusplus +} +#endif + +#endif /* Eos_Utils.h */ diff --git a/src/make.code.defn b/src/make.code.defn new file mode 100755 index 0000000..1617c8e --- /dev/null +++ b/src/make.code.defn @@ -0,0 +1,9 @@ +# Main make.code.defn file for thorn EOSBase_General +# $Header$ + +# Source files in this directory +SRCS = EOSBase_Register.c \ + EOS_Utils.c + +# Subdirectories containing source files +SUBDIRS = diff --git a/test/test b/test/test new file mode 100644 index 0000000..2a63253 --- /dev/null +++ b/test/test @@ -0,0 +1 @@ +again testing -- cgit v1.2.3