aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Auxiliary/Cactus/KrancNumericalTools/GenericFD/param.ccl12
-rw-r--r--Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.c36
-rw-r--r--Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.h2
-rw-r--r--Doc/KrancDoc.tex97
-rw-r--r--Tools/CodeGen/CalculationFunction.m14
-rw-r--r--Tools/CodeGen/Jacobian.m124
-rw-r--r--Tools/CodeGen/Kranc.m3
-rw-r--r--Tools/CodeGen/KrancThorn.m2
-rw-r--r--Tools/CodeGen/Param.m7
9 files changed, 288 insertions, 9 deletions
diff --git a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/param.ccl b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/param.ccl
index 91075c9..85de1f9 100644
--- a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/param.ccl
+++ b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/param.ccl
@@ -30,3 +30,15 @@ CCTK_INT boundary_width "width of boundary (fix later to use Cactus boundary ca
{
-1:* :: "Any integer"
} 1
+
+restricted:
+CCTK_STRING jacobian_group "Name of group containing Jacobian" STEERABLE=RECOVER
+{
+ "" :: "String of the form <implementation>::<groupname>"
+} ""
+
+restricted:
+CCTK_STRING jacobian_derivative_group "Name of group containing Jacobian derivative" STEERABLE=RECOVER
+{
+ "" :: "String of the form <implementation>::<groupname>"
+} ""
diff --git a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.c b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.c
index f23f8dc..1663231 100644
--- a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.c
+++ b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.c
@@ -508,3 +508,39 @@ void GenericFD_AssertGroupStorage(cGH const * restrict const cctkGH, const char
}
}
}
+
+/* Return a list of pointers to the members of a named group */
+void GenericFD_GroupDataPointers(cGH const * restrict const cctkGH, const char *group_name,
+ int nvars, CCTK_REAL **ptrs)
+{
+ int group_index, status;
+ cGroup group_info;
+
+ group_index = CCTK_GroupIndex(group_name);
+ if (group_index < 0)
+ CCTK_VWarn(CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Error return %d trying to get group index for group \'%s\'",
+ group_index,
+ group_name);
+
+ status = CCTK_GroupData(group_index, &group_info);
+ if (status < 0)
+ CCTK_VWarn(CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Error return %d trying to get info for group \'%s\'",
+ status,
+ group_name);
+
+ if (group_info.numvars != nvars)
+ {
+ CCTK_VWarn(CCTK_WARN_ABORT, __LINE__, __FILE__, CCTK_THORNSTRING,
+ "Group \'%s\' has %d variables but %d were expected",
+ group_name, group_info.numvars, nvars);
+ }
+
+ int v1 = CCTK_FirstVarIndex(group_name);
+
+ for (int v = 0; v < nvars; v++)
+ {
+ ptrs[v] = (CCTK_REAL *) CCTK_VarDataPtrI(cctkGH, 0 /* timelevel */, v1+v);
+ }
+}
diff --git a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.h b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.h
index b7a4239..5974e63 100644
--- a/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.h
+++ b/Auxiliary/Cactus/KrancNumericalTools/GenericFD/src/GenericFD.h
@@ -152,6 +152,8 @@ void GenericFD_LoopOverBoundary(cGH const * restrict cctkGH, Kranc_Calculation c
void GenericFD_LoopOverBoundaryWithGhosts(cGH const * restrict cctkGH, Kranc_Calculation calc);
void GenericFD_LoopOverInterior(cGH const * restrict cctkGH, Kranc_Calculation calc);
+void GenericFD_GroupDataPointers(cGH const * restrict const cctkGH, const char *group_name,
+ int nvars, CCTK_REAL **ptrs);
#ifdef __cplusplus
diff --git a/Doc/KrancDoc.tex b/Doc/KrancDoc.tex
index e357de5..131f5c2 100644
--- a/Doc/KrancDoc.tex
+++ b/Doc/KrancDoc.tex
@@ -3,6 +3,7 @@
\usepackage{tabularx}
\usepackage{graphicx}
\usepackage{alltt}
+\usepackage{hyperref}
\addtolength{\oddsidemargin}{-0.25in}
\addtolength{\textwidth}{1in}
@@ -243,6 +244,7 @@ by the Kranc system, such as a name for the calculation.
%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\chapter{Using Kranc}
+\label{chp:usingkranc}
%% \section{Types of arguments}
@@ -925,6 +927,101 @@ same arguments, but they can be tensorial in nature.
\end{tabularx}
\end{center}
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+\chapter{Additional Features}
+
+In addition to the basic functionality described in Chapter
+\ref{chp:usingkranc}, Kranc provides a number of additional features.
+Each of these features can be used independently, and are typically
+enabled by an option of the form \verb|Use* -> True| in the call to
+\verb|CreateThorn|.
+
+\section{Jacobians}
+
+Kranc allows the user to relate finite differencing operators to
+partial derivatives via an arbitrary user-defined Jacobian
+transformation provided in a grid function. This feature is enabled
+by setting \verb|UseJacobian -> True| in the options to \verb|CreateThorn| or
+\verb|CreateThornTT|.
+
+Kranc does not provide the Jacobian grid function; it might be
+provided by an external infrastructure (for example for multi-block
+schemes), or could be provided easily in the user's thorn, or another
+Kranc-generated thorn. Wherever the Jacobian is provided, it must
+adhere to the following conventions. There should be one Cactus group
+for the components of the Jacobian matrix and another for the
+components of its first spatial derivative (this is necessary for
+systems containing second spatial derivatives). The components should
+be real-valued grid functions declared in a similar manner to the
+following:
+
+\begin{verbatim}
+CCTK_REAL jac type=GF timelevels=1
+{
+ J11, J12, J13, J21, J22, J23, J31, J32, J33
+} "Jacobian of the coordinate transformation"
+
+CCTK_REALd djac type=GF timelevels=1
+{
+ dJ111, dJ112, dJ113, dJ122, dJ123, dJ133,
+ dJ211, dJ212, dJ213, dJ222, dJ223, dJ233,
+ dJ311, dJ312, dJ313, dJ322, dJ323, dJ333,
+} "Derivative of the Jacobian"
+\end{verbatim}
+
+The names of the groups and variables are not important, but the order
+of the variables within the groups is critical.
+
+The GenericFD thorn provides two parameters, \verb|jacobian_group| and
+\verb|jacobian_derivative_group| which should be set by the user in their
+parameter file to the names of the Jacobian and Jacobian derivative
+groups. With the above Jacobian definition, provided by a thorn with
+implementation \verb|MyCoordTransform| the user would set
+
+\begin{verbatim}
+GenericFD::jacobian = "MyCoordTransform::jac"
+GenericFD::jacobian_derivative = "MyCoordTransform::djac"
+\end{verbatim}
+
+The partial derivatives, associated with certain finite difference
+operators, specified in the user's calculation, will then be
+multiplied by the Jacobian. If the user specifies the following,
+
+\begin{center}
+\begin{minipage}{0.8 \textwidth}
+\begin{verbatim}
+derivs = {
+ PDstandard2nd[i_] -> DZero[i]}
+
+...
+
+dot[v] -> PDstandard2nd[v,1]
+\end{verbatim}
+\end{minipage}
+\end{center}
+
+the code that will actually be generated will be
+
+\begin{center}
+\begin{minipage}{0.8 \textwidth}
+\begin{verbatim}
+dot[v] -> J11 PDstandard2nd[v,1] + J21 PDstandard2nd[v,2]
+ + J31 PDstandard2nd[v,3]
+\end{verbatim}
+\end{minipage}
+\end{center}
+
+Note:
+
+\begin{itemize}
+\item The Jacobian multiplication introduces an additional performance
+ cost to the simulation, so it should not be enabled unless
+ necessary.
+\item It is currently not possible to generate a thorn which applies
+ the Jacobians optionally based on a run-time parameter or depending
+ on the current Carpet map. This is planned for the future.
+\end{itemize}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/Tools/CodeGen/CalculationFunction.m b/Tools/CodeGen/CalculationFunction.m
index 99d4343..1ca9513 100644
--- a/Tools/CodeGen/CalculationFunction.m
+++ b/Tools/CodeGen/CalculationFunction.m
@@ -20,7 +20,7 @@
BeginPackage["CalculationFunction`", {"CodeGen`",
"MapLookup`", "KrancGroups`", "Differencing`", "Errors`",
- "Helpers`", "Kranc`", "Optimize`"}];
+ "Helpers`", "Kranc`", "Optimize`", "Jacobian`"}];
CreateCalculationFunction::usage = "";
VerifyCalculation::usage = "";
@@ -344,11 +344,13 @@ pdCanonicalOrdering[name_[inds___] -> x_] :=
Options[CreateCalculationFunction] = ThornOptions;
-CreateCalculationFunction[calc_, debug_, imp_, opts:OptionsPattern[]] :=
+CreateCalculationFunction[calcp_, debug_, imp_, opts:OptionsPattern[]] :=
Module[{gfs, allSymbols, knownSymbols,
shorts, eqs, parameters, parameterRules,
functionName, dsUsed, groups, pddefs, cleancalc, eqLoop, where,
- addToStencilWidth, pDefs, haveCondTextuals, condTextuals},
+ addToStencilWidth, pDefs, haveCondTextuals, condTextuals, calc},
+
+ calc = If[OptionValue[UseJacobian], InsertJacobian[calcp, opts], calcp];
cleancalc = removeUnusedShorthands[calc];
If[OptionValue[CSE],
@@ -359,6 +361,7 @@ CreateCalculationFunction[calc_, debug_, imp_, opts:OptionsPattern[]] :=
eqs = lookup[cleancalc, Equations];
parameters = lookupDefault[cleancalc, Parameters, {}];
groups = lookup[cleancalc, Groups];
+ If[OptionValue[UseJacobian], groups = Join[groups, JacobianGroups[]]];
pddefs = lookupDefault[cleancalc, PartialDerivatives, {}];
where = lookupDefault[cleancalc, Where, Everywhere];
addToStencilWidth = lookupDefault[cleancalc, AddToStencilWidth, 0];
@@ -420,7 +423,8 @@ CreateCalculationFunction[calc_, debug_, imp_, opts:OptionsPattern[]] :=
allSymbols = calculationSymbols[cleancalc];
knownSymbols = Join[lookupDefault[cleancalc, AllowedSymbols, {}], gfs, shorts, parameters,
{dx,dy,dz,idx,idy,idz,t, Pi, E, Symbol["i"], Symbol["j"], Symbol["k"], normal1, normal2,
- normal3, tangentA1, tangentA2, tangentA3, tangentB1, tangentB2, tangentB3}];
+ normal3, tangentA1, tangentA2, tangentA3, tangentB1, tangentB2, tangentB3},
+ If[OptionValue[UseJacobian], JacobianSymbols[], {}]];
unknownSymbols = Complement[allSymbols, knownSymbols];
@@ -452,6 +456,8 @@ CreateCalculationFunction[calc_, debug_, imp_, opts:OptionsPattern[]] :=
InitialiseFDVariables[OptionValue[UseVectors]],
definePreDefinitions[pDefs],
+ If[OptionValue[UseJacobian], CreateJacobianVariables[], {}],
+
If[Cases[{pddefs}, SBPDerivative[_], Infinity] != {},
CommentedBlock["Compute Summation By Parts derivatives",
IncludeFile["sbp_calc_coeffs.h"]],
diff --git a/Tools/CodeGen/Jacobian.m b/Tools/CodeGen/Jacobian.m
new file mode 100644
index 0000000..59a57f9
--- /dev/null
+++ b/Tools/CodeGen/Jacobian.m
@@ -0,0 +1,124 @@
+
+(* Copyright 2011 Ian Hinder
+
+ This file is part of Kranc.
+
+ Kranc is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ Kranc is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Kranc; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*)
+
+BeginPackage["Jacobian`", {"Errors`", "Helpers`", "Kranc`", "Differencing`", "MapLookup`", "CodeGen`"}];
+
+JacobianQ;
+InsertJacobian;
+CreateJacobianVariables;
+JacobianGenericFDParameters;
+JacobianSymbols;
+JacobianGroups;
+
+Begin["`Private`"];
+
+Options[JacobianQ] = ThornOptions;
+JacobianQ[opts:OptionsPattern[]] :=
+ Length[OptionValue[Jacobian]] > 0;
+
+(* Assign a shorthand containing the Jacobian multiplied by the passed
+ 1st derivative *)
+jacobianShorthand[d:(deriv_[var_, i_])] :=
+ Module[{},
+ derivToJacDeriv[d] ->
+ Sum[Symbol["J"<>ToString[j]<>ToString[i]] deriv[var, j], {j, 1 3}]
+ ];
+
+(* Assign a shorthand containing the Jacobian multiplied by the passed
+ 2nd derivative *)
+jacobianShorthand[d:(deriv_[var_, i_,j_])] :=
+ Module[{ip,jp},
+ {ip,jp} = Sort[{i,j}]; (* dJ is symmetric in the last two indices *)
+ derivToJacDeriv[d] ->
+ Sum[Symbol["dJ"<>ToString[a]<>ToString[ip]<>ToString[jp]] deriv[var, a], {a, 1 3}] +
+ Sum[Symbol["J"<>ToString[a]<>ToString[i]] Symbol["J"<>ToString[b]<>ToString[j]] deriv[var, a, b], {a, 1 3}, {b, 1, 3}]
+ ];
+
+(* Convert a 1st derivative to a Jacobian-multiplied derivative *)
+derivToJacDeriv[deriv_[var_, i_]] :=
+ Symbol["Global`Jac"<>ToString[deriv]<>ToString[i]<>ToString[var]];
+
+(* Convert a 2nd derivative to a Jacobian-multiplied derivative *)
+derivToJacDeriv[deriv_[var_, i_, j_]] :=
+ Symbol["Global`Jac"<>ToString[deriv]<>ToString[i]<>ToString[j]<>ToString[var]];
+
+(* Given a calculation containing partial derivatives, return a
+ version of the calculation with all the partial derivatives multiplied
+ by the Jacobian *)
+Options[InsertJacobian] = ThornOptions;
+InsertJacobian[calc_List, opts:OptionsPattern[]] :=
+ Module[{pdDefs, derivs, newShortDefs, newShorts, combinedShorts, combinedEqs, combinedCalc, eqs, newEqs},
+ pdDefs = OptionValue[PartialDerivatives];
+ derivs = GridFunctionDerivativesInExpression[pdDefs, lookup[calc, Equations]];
+ If[Length[derivs] === 0, Return[calc]];
+ newShortDefs = Map[jacobianShorthand, derivs];
+ newShorts = Map[First, newShortDefs];
+ combinedShorts = Join[lookupDefault[calc, Shorthands, {}], newShorts];
+ eqs = lookup[calc, Equations];
+ newEqs = eqs /. (x_?(MemberQ[derivs, #] &) :> derivToJacDeriv[x]);
+ combinedEqs = Join[newShortDefs, newEqs];
+ combinedCalc = mapReplace[mapReplace[mapEnsureKey[calc, Shorthands, {}], Shorthands, combinedShorts], Equations, combinedEqs];
+ combinedCalc];
+
+(* Define local pointers to the members of the Jacobian and Jacobian
+ derivatives groups *)
+CreateJacobianVariables[] :=
+CommentedBlock["Jacobian variable pointers",
+ {"if (strlen(jacobian_group) == 0 || strlen(jacobian_derivative_group) == 0)\n",
+ "{\n",
+ " CCTK_WARN (1, \"GenericFD::jacobian_group and GenericFD::jacobian_derivative_group must both be set to valid group names\");\n",
+ "}\n\n",
+ "CCTK_REAL *jacobian_ptrs[9];\n",
+ "GenericFD_GroupDataPointers(cctkGH, jacobian_group,\n",
+ " 9, jacobian_ptrs);\n",
+ "\n",
+ Table[{"CCTK_REAL *J",i,j," = jacobian_ptrs[",(i-1)*3+j-1,"];\n"},{i,1,3},{j,1,3}],
+ "\n",
+ "CCTK_REAL *jacobian_derivative_ptrs[18];\n",
+ "GenericFD_GroupDataPointers(cctkGH, jacobian_derivative_group,\n",
+ " 18, jacobian_derivative_ptrs);\n",
+ "\n",
+ Module[{syms = Flatten[Table[{"dJ",i,j,k},{i,1,3},{j,1,3},{k,j,3}],2]},
+ MapIndexed[{"CCTK_REAL *", #1, " = jacobian_derivative_ptrs[", #2-1, "];\n"} &, syms]]}];
+
+(* List of symbols which should be allowed in a calculation *)
+JacobianSymbols[] :=
+ Map[Symbol, Join[Flatten[Table[FlattenBlock[{"dJ",i,j,k}],{i,1,3},{j,1,3},{k,j,3}],2],
+ Flatten[Table[FlattenBlock[{"J",i,j}],{i,1,3},{j,1,3}],1]]];
+
+(* Parameters to inherit from GenericFD *)
+JacobianGenericFDParameters[] :=
+ {{Name -> "jacobian_group", Type -> "CCTK_STRING"},
+ {Name -> "jacobian_derivative_group", Type -> "CCTK_STRING"}};
+
+(* The symbols which are used for the Jacobian variables in the
+ generated source code. These do not have to coincide with the
+ actual variable names, as the variable pointers are read using
+ CCTK_VarDataPtr. *)
+JacobianGroups[] :=
+ {{"unknown::unknown", {Global`J11, Global`J12, Global`J13, Global`J21, Global`J22, Global`J23, Global`J31, Global`J32, Global`J33}},
+ {"unknown::unknown", {Global`dJ111, Global`dJ112, Global`dJ113, Global`dJ122, Global`dJ123, Global`dJ133,
+ Global`dJ211, Global`dJ212, Global`dJ213, Global`dJ222, Global`dJ223, Global`dJ233,
+ Global`dJ311, Global`dJ312, Global`dJ313, Global`dJ322, Global`dJ323, Global`dJ333}}};
+
+
+End[];
+
+EndPackage[];
diff --git a/Tools/CodeGen/Kranc.m b/Tools/CodeGen/Kranc.m
index bd2c9c7..1077305 100644
--- a/Tools/CodeGen/Kranc.m
+++ b/Tools/CodeGen/Kranc.m
@@ -73,7 +73,8 @@ ThornOptions =
UseVectors -> False,
ProhibitAssignmentToGridFunctionsRead -> False,
IncludeFiles -> {},
- CSE -> False};
+ CSE -> False,
+ UseJacobian -> False};
(* Thorn.m *)
diff --git a/Tools/CodeGen/KrancThorn.m b/Tools/CodeGen/KrancThorn.m
index 6463345..bb1b115 100644
--- a/Tools/CodeGen/KrancThorn.m
+++ b/Tools/CodeGen/KrancThorn.m
@@ -179,7 +179,7 @@ CreateKrancThorn[groupsOrig_, parentDirectory_, thornName_, opts:OptionsPattern[
inheritedRealParams, inheritedIntParams, inheritedKeywordParams,
extendedRealParams, extendedIntParams, extendedKeywordParams,
evolutionTimelevels, defaultEvolutionTimelevels,
- calcs];
+ calcs, opts];
(* Construct the schedule file *)
InfoMessage[Terse, "Creating schedule file"];
diff --git a/Tools/CodeGen/Param.m b/Tools/CodeGen/Param.m
index 90cbb7d..1b4ad37 100644
--- a/Tools/CodeGen/Param.m
+++ b/Tools/CodeGen/Param.m
@@ -18,7 +18,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*)
-BeginPackage["Param`", {"Thorn`", "Errors`", "Helpers`", "MapLookup`", "KrancGroups`", "Kranc`"}];
+BeginPackage["Param`", {"Thorn`", "Errors`", "Helpers`", "MapLookup`", "KrancGroups`", "Kranc`", "Jacobian`"}];
CreateKrancParam;
MakeFullParamDefs;
@@ -118,12 +118,13 @@ extendParameters[imp_, reals_, ints_, keywords_] :=
Return[{Name -> imp, ExtendedParameters -> Join[realStructs, intStructs, keywordStructs]}],
Return[{}]]];
+Options[CreateKrancParam] = ThornOptions;
CreateKrancParam[evolvedGroups_, nonevolvedGroups_, groups_, thornName_,
reals_, ints_, keywords_,
inheritedReals_, inheritedInts_, inheritedKeywords_,
extendedReals_, extendedInts_, extendedKeywords_,
evolutionTimelevels_, defaultEvolutionTimelevels_,
- calcs_] :=
+ calcs_, opts:OptionsPattern[]] :=
Module[{nEvolved, evolvedMoLParam, evolvedGFs,
(*constrainedMoLParam,*) genericfdStruct, realStructs, intStructs,
allInherited, allExtended, implementationNames, molImplementation,
@@ -194,7 +195,7 @@ CreateKrancParam[evolvedGroups_, nonevolvedGroups_, groups_, thornName_,
{
Name -> "GenericFD",
UsedParameters ->
- {}
+ If[OptionValue[UseJacobian], JacobianGenericFDParameters[], {}]
};
realStructs = Map[krancParamStruct[#, "CCTK_REAL", False] &, reals];