aboutsummaryrefslogtreecommitdiff
path: root/Tools/CodeGen/Thorn.m
diff options
context:
space:
mode:
authorshusa <shusa>2004-05-09 19:34:21 +0000
committershusa <shusa>2004-05-09 19:34:21 +0000
commit7c05ab152724573b390868b99d4d3eef00e147da (patch)
tree418b79742833ccd22b4e90bf0b98ba7c9ac83f4d /Tools/CodeGen/Thorn.m
parentd62d08ade47fd11fa8999c2d66b8f506462503f8 (diff)
Initial revision
SKIPPED: Examples/ADM/ADMEqs.m Examples/ADM/ADMTT.m Examples/ADM/BuildADMTT Examples/ADM/KrancADMRicciMetric100.par Examples/ADM/KrancADMRicciStandard100.par Examples/ADM/KrancADMTT.m Examples/ADM/Makefile Examples/ADM/README Examples/ADM/ThornGenADM_front.nb Examples/ADM/ThornGen_ADM.m Examples/ADM/ThornGen_ADM2.m Examples/ADM/arrangement_KrancADM.tar.gz Examples/ADM/data_adm.tar.gz Examples/BSSN/BSSNTT.m Examples/BSSN/BuildBSSNTT Examples/BSSN/Makefile Examples/BSSN/freeBSSN/freeBSSN.th Examples/BSSN/freeBSSN/BSSNMoL/interface.ccl Examples/BSSN/freeBSSN/BSSNMoL/param.ccl Examples/BSSN/freeBSSN/BSSNMoL/schedule.ccl Examples/BSSN/freeBSSN/BSSNMoL/src/BSSNMoL_ApplyExcision.F90 Examples/BSSN/freeBSSN/BSSNMoL/src/BSSNMoL_Boundaries.c Examples/BSSN/freeBSSN/BSSNMoL/src/BSSNMoL_CalcRHS.c Examples/BSSN/freeBSSN/BSSNMoL/src/BSSNMoL_RegisterVars.c Examples/BSSN/freeBSSN/BSSNMoL/src/Startup.c Examples/BSSN/freeBSSN/BSSNMoL/src/make.code.defn Examples/BSSN/freeBSSN/BSSNMoL/src/precomputations.h Examples/BSSN/freeBSSN/BSSNTranslator/interface.ccl Examples/BSSN/freeBSSN/BSSNTranslator/param.ccl Examples/BSSN/freeBSSN/BSSNTranslator/schedule.ccl Examples/BSSN/freeBSSN/BSSNTranslator/src/BSSNTranslator_Setter.c Examples/BSSN/freeBSSN/BSSNTranslator/src/Startup.c Examples/BSSN/freeBSSN/BSSNTranslator/src/make.code.defn Examples/BSSN/freeBSSN/BSSNTranslator/src/precomputations.h Examples/BSSN/freeBSSN/OLDpar/BSSN2GaugeWaveR0.par Examples/BSSN/freeBSSN/OLDpar/BSSN2GaugeWaveR1.par Examples/BSSN/freeBSSN/OLDpar/BSSN2GaugeWaveR2.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyCollapseR0.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyCollapseR1.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyCollapseR2.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyExpandR0.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyExpandR1.par Examples/BSSN/freeBSSN/OLDpar/BSSN2PolarizedGowdyExpandR2.par Examples/BSSN/freeBSSN/OLDpar/BSSN2RobustR0.par Examples/BSSN/freeBSSN/OLDpar/BSSN2RobustR1.par Examples/BSSN/freeBSSN/OLDpar/BSSN2RobustR2.par Examples/BSSN/freeBSSN/evalBSSNConstraints/interface.ccl Examples/BSSN/freeBSSN/evalBSSNConstraints/param.ccl Examples/BSSN/freeBSSN/evalBSSNConstraints/schedule.ccl Examples/BSSN/freeBSSN/evalBSSNConstraints/src/Startup.c Examples/BSSN/freeBSSN/evalBSSNConstraints/src/evalBSSNConstraints_Eval.c Examples/BSSN/freeBSSN/evalBSSNConstraints/src/make.code.defn Examples/BSSN/freeBSSN/evalBSSNConstraints/src/precomputations.h Examples/BSSN/freeBSSN/freeBSSNBase/interface.ccl Examples/BSSN/freeBSSN/freeBSSNBase/param.ccl Examples/BSSN/freeBSSN/freeBSSNBase/schedule.ccl Examples/BSSN/freeBSSN/freeBSSNBase/src/RegisterSymmetries.c Examples/BSSN/freeBSSN/freeBSSNBase/src/Startup.c Examples/BSSN/freeBSSN/freeBSSNBase/src/make.code.defn Examples/BSSN/freeBSSN/harmonicLapseMoL/interface.ccl Examples/BSSN/freeBSSN/harmonicLapseMoL/param.ccl Examples/BSSN/freeBSSN/harmonicLapseMoL/schedule.ccl Examples/BSSN/freeBSSN/harmonicLapseMoL/src/Startup.c Examples/BSSN/freeBSSN/harmonicLapseMoL/src/harmonicLapseMoL_ApplyExcision.F90 Examples/BSSN/freeBSSN/harmonicLapseMoL/src/harmonicLapseMoL_Boundaries.c Examples/BSSN/freeBSSN/harmonicLapseMoL/src/harmonicLapseMoL_CalcRHS.c Examples/BSSN/freeBSSN/harmonicLapseMoL/src/harmonicLapseMoL_RegisterVars.c Examples/BSSN/freeBSSN/harmonicLapseMoL/src/make.code.defn Examples/BSSN/freeBSSN/harmonicLapseMoL/src/precomputations.h Examples/BSSN/freeBSSN/par/BSSN2GaugeWaveR0.par Examples/BSSN/freeBSSN/par/BSSN2GaugeWaveR1.par Examples/BSSN/freeBSSN/par/BSSN2GaugeWaveR2.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyCollapseR0.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyCollapseR1.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyCollapseR2.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyExpandR0.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyExpandR1.par Examples/BSSN/freeBSSN/par/BSSN2PolarizedGowdyExpandR2.par Examples/BSSN/freeBSSN/par/BSSN2RobustR0.par Examples/BSSN/freeBSSN/par/BSSN2RobustR1.par Examples/BSSN/freeBSSN/par/BSSN2RobustR2.par Examples/BSSN/freeBSSN/projectAlgebraicConstraints/interface.ccl Examples/BSSN/freeBSSN/projectAlgebraicConstraints/param.ccl Examples/BSSN/freeBSSN/projectAlgebraicConstraints/schedule.ccl Examples/BSSN/freeBSSN/projectAlgebraicConstraints/src/Startup.c Examples/BSSN/freeBSSN/projectAlgebraicConstraints/src/make.code.defn Examples/BSSN/freeBSSN/projectAlgebraicConstraints/src/precomputations.h Examples/BSSN/freeBSSN/projectAlgebraicConstraints/src/projectAlgebraicConstraints_Set.c Examples/BSSN/freeBSSN/setHarmonicLapse/interface.ccl Examples/BSSN/freeBSSN/setHarmonicLapse/param.ccl Examples/BSSN/freeBSSN/setHarmonicLapse/schedule.ccl Examples/BSSN/freeBSSN/setHarmonicLapse/src/Startup.c Examples/BSSN/freeBSSN/setHarmonicLapse/src/make.code.defn Examples/BSSN/freeBSSN/setHarmonicLapse/src/precomputations.h Examples/BSSN/freeBSSN/setHarmonicLapse/src/setHarmonicLapse_Set.c Examples/BSSN/freeBSSN/setUnitLapse/interface.ccl Examples/BSSN/freeBSSN/setUnitLapse/param.ccl Examples/BSSN/freeBSSN/setUnitLapse/schedule.ccl Examples/BSSN/freeBSSN/setUnitLapse/src/Startup.c Examples/BSSN/freeBSSN/setUnitLapse/src/make.code.defn Examples/BSSN/freeBSSN/setUnitLapse/src/precomputations.h Examples/BSSN/freeBSSN/setUnitLapse/src/setUnitLapse_Set.c Examples/BSSN/freeBSSN/setZeroShift/interface.ccl Examples/BSSN/freeBSSN/setZeroShift/param.ccl Examples/BSSN/freeBSSN/setZeroShift/schedule.ccl Examples/BSSN/freeBSSN/setZeroShift/src/Startup.c Examples/BSSN/freeBSSN/setZeroShift/src/make.code.defn Examples/BSSN/freeBSSN/setZeroShift/src/precomputations.h Examples/BSSN/freeBSSN/setZeroShift/src/setZeroShift_Set.c Examples/KleinGordon/Components.nb Examples/KleinGordon/KGTT.m Examples/KleinGordon/ListOfEqsLhsRhsComp.m Examples/KleinGordon/MKG100.par Examples/KleinGordon/MKGTT.m Examples/KleinGordon/README Examples/KleinGordon/ThornGen_front.nb Examples/KleinGordon/arrangement_MKG.tar.gz Examples/KleinGordon/data_mkg.tar.gz Examples/Maxwell/3+1_Decomp_Maxwell.nb Examples/Maxwell/EM100.par Examples/Maxwell/EMTT.m Examples/Maxwell/Initializations_Maxwell.nb Examples/Maxwell/ListOfConstrComp.m Examples/Maxwell/ListOfEqsLhsRhsComp.m Examples/Maxwell/Maxwell_Demo.nb Examples/Maxwell/README Examples/Maxwell/README_internal Examples/Maxwell/ThornGen_front.nb Examples/Maxwell/Using_Tools_Constr.nb Examples/Maxwell/arrangement_EM.tar.gz Examples/Maxwell/data_em.tar.gz Tools/TensorFactory/ComponentsTools.nb Tools/TensorFactory/DecomposeTools.nb Tools/TensorFactory/FrameDecomposeTools.nb Tools/TensorFactory/GaussCodazzi.nb Tools/TensorFactory/Ricci.tex Tools/TensorFactory/StartMathTensor.m Tools/TensorFactory/TeXTools.nb Tools/TensorFactory/Doc/Characteristics.nb Tools/TensorFactory/Doc/DocGaussCodazzi.nb Tools/TensorFactory/Doc/Om1EvolEqs.m Tools/TensorFactory/Doc/exampleTeX.nb Tools/TensorFactory/Doc/Papers/ERE2003.pdf Tools/TensorFactory/Doc/Talks/compalg.pdf
Diffstat (limited to 'Tools/CodeGen/Thorn.m')
-rw-r--r--Tools/CodeGen/Thorn.m791
1 files changed, 791 insertions, 0 deletions
diff --git a/Tools/CodeGen/Thorn.m b/Tools/CodeGen/Thorn.m
new file mode 100644
index 0000000..3224228
--- /dev/null
+++ b/Tools/CodeGen/Thorn.m
@@ -0,0 +1,791 @@
+
+(* $Id$ *)
+
+(* Copyright 2004 Sascha Husa, Ian Hinder, Christiane Lechner
+
+ 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 Foobar; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*)
+
+(* This package provides a set of functions to create the various
+ parts of a Cactus thorn and assemble them. *)
+
+BeginPackage["sym`"];
+
+(* These symbols are used in this file. Whenever this package is
+ used, the symbols will be added into the sym` context. You will
+ need to make sure the sym` context is on your ContextPath to use
+ the symbols without the sym` prefix. *)
+
+{AccumulatorBase, Name, Type, Extend, Default, Comment, Range, Implementation, Group,
+SchedulePoint, Language, SynchronizedGroups, StorageGroups,
+Timelevels, VariableType, GridType, Visibility, Variables,
+Implementations, Value, AllowedValues, UsedParameters, Description,
+ExtendedParameters, NewParameters, Directory, Interface, Param,
+Schedule, Sources, Makefile, Filename, Contents, ThornName,
+BaseImplementation, EvolvedGFs, PrimitiveGFs, Groups, Calculation,
+GridFunctions, Shorthands, Equations, Parameter, Value, UsesFunctions,
+ArgString, Conditional, D1, D2, D3, D11, D22, D33, D21, D31, D32,
+Textual, TriggerGroups};
+
+{ExcisionGFs};
+
+EndPackage[];
+
+BeginPackage["Thorn`", "CodeGen`", "CalculationFunction`", "MapLookup`"];
+
+(* These functions are externally visible, and comprise the public
+ interface to this package. *)
+CreateSchedule::usage = "Create the content of the schedule.ccl file.";
+CreateMakefile::usage = "Create the content of the Cactus make.code.defn file.";
+CreateInterface::usage = "Create the content of the interface.ccl file.";
+CreateParam::usage = "Create the content of the param.ccl file.";
+Quote::usage = ""; (* This should not be in this package *)
+CreateThorn::usage = "Create a general Cactus thorn from
+a thorn specification structure";
+CreateSymmetriesRegistrationSource::usage = "";
+CreateMoLRegistrationSource::usage = "";
+CreateMoLBoundariesSource::usage = "";
+CreateMoLExcisionSource::usage = "";
+CreateSetterSource::usage = "";
+CreatePrecompMacros::usage = "";
+CreateStartupFile::usage = "";
+
+(* Ensure that we can refer to symbols without the `sym prefix *)
+$ContextPath = Join[{"sym`"}, $ContextPath];
+
+Begin["`Private`"];
+
+
+(* ------------------------------------------------------------------------
+ Miscellaneous definitions, could be moved elsewhere
+ ------------------------------------------------------------------------ *)
+
+(* Create a directory if it does not exist already *)
+ensureDirectory[name_] :=
+ If[FileType[name] == None,
+ CreateDirectory[name]];
+
+
+(* date, user, etc. *)
+date[] := ToString[Date[][[3]]] <> "/" <>
+ ToString[Date[][[2]]] <> "/" <>
+ ToString[Date[][[1]]]
+
+
+dateLong[] := ToString[Date[][[3]]] <> "/" <>
+ ToString[Date[][[2]]] <> "/" <>
+ ToString[Date[][[1]]] <> "/" <> " " <>
+ ToString[Date[][[4]]] <> ":" <>
+ ToString[Date[][[5]]] <> ":" <>
+ ToString[Date[][[6]]];
+
+
+user[] := ToString[<< "!whoami"];
+
+
+whoWhen[lang_] := Module[{com1, com2},
+
+com1 = "UNRECOGNIZED LANGUAGE";
+com2 = "UNRECOGNIZED LANGUAGE";
+
+If[(lang == "C" || lang == "c"),
+ com1 = "/* "; com2 = " */";
+];
+
+If[(lang == "Fortran" || lang == "FORTRAN" || lang == "F90" || lang == "F95"),
+ com1 = "!"; com2 = "";
+];
+
+If[(lang == "F77"),
+ com1 = "C"; com2 = "";
+];
+
+If[(lang == "shell" || lang == "CCL"),
+ com1 = "#"; com2 = "";
+];
+
+{com1 <> " file produced by user " <> user[] <> ", " <> date[] <> com2 <> "\n" <>
+ com1 <> " Produced with Mathematica Version " <> ToString[$Version] <> com2 <> "\n\n"<>
+ com1 <> " Mathematica script written by Ian Hinder and Sascha Husa" <> com2 <> "\n\n"<>
+ com1 <> " $Id" <> "$" <> com2 <> "\n\n"}
+
+];
+
+
+(* ------------------------------------------------------------------------
+ Makefile
+ ------------------------------------------------------------------------ *)
+
+(* Return a CodeGen block representing a makefile which refers to the
+ list of filenames sourceFiles *)
+CreateMakefile[sourceFiles_] :=
+ {whoWhen["shell"],
+ "SRCS = ", Map[{#, " "} &, sourceFiles]};
+
+(* ------------------------------------------------------------------------
+ Parameter file
+ ------------------------------------------------------------------------ *)
+
+(* parameterFileSpec = {Implementations -> {}, NewParameters -> {}}
+
+ implementation = {Name -> "",
+ UsedParameters (optional) -> {spec1, spec2, ...},
+ ExtendedParameters (optional) -> {spec1, spec2, ...}}
+
+ (optional) allowedValue = {Value -> "", Description -> ""}
+
+ parameter spec = {Name -> "", Type -> "", Default -> "",
+ Description -> "", Visibility -> "private",
+ AllowedValues -> {...}} *)
+
+(* Return a CodeGen block which represents the quoted value of x *)
+Quote[x_] := {"\"", x, "\""};
+
+(* To be used for parameters; will quote it if it is a keyword *)
+renderValue[type_, value_] :=
+ If[type == "KEYWORD",
+ Quote[value],
+ value];
+
+(* Return a block defining a parameter with the given
+ parameterSpec (defined above). This is used for defining new
+ parameters, as well as extending existing ones. *)
+parameterBlock[spec_] :=
+ {lookup[spec, Type], " ",
+ lookup[spec, Name], " ",
+ Quote[lookup[spec, Description]],
+
+ If[mapContains[spec, AccumulatorBase],
+ {" ACCUMULATOR-BASE=", lookup[spec, AccumulatorBase]},
+ {}],
+
+ "\n",
+ SuffixedCBlock[
+
+ (* For each allowed value of the parameter specified in the spec,
+ create a line with the value and the description *)
+ Map[{renderValue[lookup[spec,Type], lookup[#, Value]], " :: ",
+ Quote[lookup[#, Description]], "\n"} &,
+ lookupDefault[spec, AllowedValues, {}]],
+
+ (* Output the line describing the default value of the parameter *)
+ renderValue[lookup[spec,Type], lookup[spec, Default]]],
+
+ "\n"};
+
+(* Given a particular implementation, return a CodeGen block defining
+ which parameters are used or extended from that implementation *)
+parameterImplementationSection[spec_] :=
+ {"\nshares: ", lookup[spec, Name], "\n", "\n",
+
+ (* For each used parameter in the spec, output a line indicating
+ that it is used *)
+ Map[{"USES ", lookup[#, Type], " ", lookup[#, Name], "\n"} &,
+ lookupDefault[spec, UsedParameters, {}]], "\n",
+
+ (* For each extended parameter in the spec, output a parameter
+ block containing the specified extension prefixed with EXTENDS *)
+ Map[{"EXTENDS ", parameterBlock[#], "\n"} &,
+ lookupDefault[spec, ExtendedParameters, {}]]};
+
+(* Given a parameterFileSpec structure, return a CodeGen block for the
+ param.ccl file *)
+CreateParam[spec_] :=
+ {whoWhen["CCL"],
+
+ (* For each implementation defined in the spec, output a block
+ which declares which parameters are used and extended by this
+ implementation *)
+ Map[parameterImplementationSection,
+ lookupDefault[spec, Implementations, {}]],
+
+ (* For each new parameter being defined by this implementation,
+ output a parameter block for it *)
+ Map[{lookup[#, Visibility], ":\n", parameterBlock[#]} &,
+ lookupDefault[spec, NewParameters, {}]]};
+
+(* ------------------------------------------------------------------------
+ Interface file
+ ------------------------------------------------------------------------ *)
+
+(* The following "group" structure defines a Cactus group of variables
+ to be included in an interface.ccl file.
+
+ group:
+
+ {Name -> "", VariableType -> "", Timelevels -> 2, GridType -> "GF",
+ Comment -> "", Visibility -> "public"
+ Variables -> {phi, h11, ...}} *)
+
+(* Given the specification of a group structure, return a CodeGen
+ block for the interface.ccl file to define that group *)
+interfaceGroupBlock[spec_] :=
+ {lookup[spec, Visibility], ":\n",
+ lookup[spec, VariableType], " ", lookup[spec, Name],
+ " type=", lookup[spec,GridType], " ",
+ "timelevels=", lookup[spec, Timelevels], "\n",
+ SuffixedCBlock[{CommaNewlineSeparated[lookup[spec, Variables]],"\n"},
+ "\"" <> lookup[spec, Comment] <> "\""]};
+
+(* Function aliasing *)
+
+(* A definition of an aliased function is:
+
+ {Name -> "MoLRegisterEvolvedGroup",
+ Type -> "CCTK_INT",
+ ArgString -> "CCTK_INT IN EvolvedIndex, CCTK_INT IN RHSIndex"}
+
+*)
+
+usesFunction[f_] :=
+ {lookup[f, Type], " FUNCTION ", lookup[f, Name], "(", lookup[f,ArgString], ")\n",
+ "USES FUNCTION ", lookup[f, Name], "\n\n"};
+
+
+(* Given the name of an implementation, a list of implementation names
+ that we inherit from, a list of include files to mention, and a
+ list of group structures as defined above, return a CodeGen block
+ representing the interface.ccl file. As an optional argument, one
+ can specify Friends -> {list of implementations we want as
+ friends}. Can also have UsesFunction -> {functions}*)
+CreateInterface[implementation_, inheritedImplementations_, includeFiles_,
+ groups_, opts___] :=
+ {whoWhen["CCL"],
+ "implements: ", implementation, "\n\n",
+ "inherits: ", SpaceSeparated[inheritedImplementations], "\n\n",
+ If[mapContains[{opts}, Friends],
+ {"friend: ", SpaceSeparated[lookup[{opts}, Friends]]},{}],
+ "\n\n",
+ Map[{"USES INCLUDE: ", #, "\n"} &, includeFiles],
+ "\n",
+
+ Map[usesFunction, lookupDefault[{opts}, UsesFunctions, {}]],
+
+
+ NewlineSeparated[Map[FlattenBlock[interfaceGroupBlock[#]] &, groups]]};
+
+(* ------------------------------------------------------------------------
+ Scheduling
+ ------------------------------------------------------------------------ *)
+
+(* storage group
+
+ (represents the fact that we want to allocate storage for a Cactus
+ variable group with the given number of timelevels)
+
+ {Group -> "admbase::metric", Timelevels -> 3,
+ Conditional -> {Parameter -> "", Value -> ""},
+ Conditional -> {Textual -> "CCTK_EQUALS(name,value)"}}
+
+ A "conditional" structure looks like this: {Parameter -> "", Value -> ""}
+
+ scheduled function: (a function to be scheduled at a particular point)
+
+ {Name -> "ADM_BSSN_CalcRHS_fn", SchedulePoint -> "in POSTINITIAL before ExternalLapse",
+ Language -> "C", Comment -> "",
+ (optional) SynchronizedGroups -> {ADM_BSSN_gamma, ...},
+ (optional) StorageGroups -> {Group -> "mygroup", Timelevels -> 1},
+ (optional) Conditional -> {Parameter -> "", Value -> ""}}
+
+ scheduled group:
+
+ {... sameish}
+
+*)
+
+(* Given a storage group structure defined above, return a CodeGen
+ structure for inclusion in the schedule.ccl file to allocate
+ storage for this group. *)
+groupStorage[spec_] :=
+ {"STORAGE: ", lookup[spec, Group], "[", lookup[spec, Timelevels], "]\n"}
+
+
+(* Given a function scheduling specification as defined above, return
+ a CodeGen block to schedule the function for the schedule.ccl file *)
+scheduleUnconditionalFunction[spec_] :=
+ {"schedule ", lookup[spec, Name], " ", lookup[spec,SchedulePoint], "\n",
+ SuffixedCBlock[
+ {"LANG: ", lookup[spec, Language], "\n\n",
+
+ (* Insert a SYNC line for each group we want to synchronize. *)
+ Map[{"SYNC: ", #, "\n"} &, lookupDefault[spec, SynchronizedGroups, {}]],
+
+ Map[{"TRIGGERS: ", #, "\n"} &, lookupDefault[spec, TriggerGroups, {}]],
+
+ (* Insert a storage block for each group we want to allocate
+ storage for *)
+ Map[groupStorage, lookupDefault[spec, StorageGroups, {}]]},
+
+ Quote[lookup[spec, Comment]]]};
+
+(* Handle the aspect of scheduling the function conditionally *)
+scheduleFunction[spec_] :=
+ Module[{condition, parameter, value, u},
+
+ u = scheduleUnconditionalFunction[spec];
+
+ If[mapContains[spec, Conditional],
+
+ (* Output the conditional structure *)
+ condition = lookup[spec, Conditional];
+
+ If[mapContains[condition, Textual],
+
+ ConditionalOnParameterTextual[lookup[condition, Textual], u],
+
+ If[mapContains[condition, Parameter],
+
+ parameter = lookup[condition, Parameter];
+ value = lookup[condition, Value];
+ ConditionalOnParameter[parameter, value, u],
+
+ If[condition != {},
+ Throw["Unrecognized conditional structure", condition],
+ u]]],
+ u]];
+
+
+(* Schedule a schedule group. Use a slightly dirty trick; given that
+ the structure is identical to that for a function except with the
+ word "GROUP" added before the function name, just use the existing
+ function. *)
+scheduleGroup[spec_] :=
+ scheduleFunction[mapReplace[spec, Name, "group " <> lookup[spec, Name]]];
+
+(* Taking a list of group storage specifications for global storage,
+ and lists of scheduled function and scheduled group structures,
+ return a CodeGen block representing a schdule.ccl file. *)
+CreateSchedule[globalStorageGroups_, scheduledGroups_, scheduledFunctions_] :=
+ {whoWhen["CCL"],
+ Map[SeparatedBlock[groupStorage[#]] &, globalStorageGroups],
+ Map[SeparatedBlock[scheduleFunction[#]] &, scheduledFunctions],
+ Map[SeparatedBlock[scheduleGroup[#]] &, scheduledGroups]};
+
+
+(* ------------------------------------------------------------------------
+ Setter
+ ------------------------------------------------------------------------ *)
+
+(* calculation = {Name -> "ClassicADM_Setter",
+ optional Before -> {functions},
+ optional After -> {functions},
+ Shorthands -> {gInv11, ...},
+ GridFunctions -> {g11rhs, K11},
+ CollectList -> {hInv11, hInv22, ...},
+ optional DeclarationIncludes -> {include file list},
+ optional LoopPreIncludes -> {include file list},
+ Equations -> {{K11_rhs -> 2 A K11, ...}...}} *)
+
+calculationMacros[] :=
+ CommentedBlock["Define macros used in calculations",
+ Map[{"#define ", #, "\n"} &,
+ {"INITVALUE (42)",
+ "INV(x) ((1) / (x))" ,
+ "SQR(x) ((x) * (x))" ,
+ "CUB(x) ((x) * (x) * (x))" ,
+ "QAD(x) ((x) * (x) * (x) * (x))"}]];
+
+(* Given a list of Calculation structures as defined above, create a
+ CodeGen representation of a source file that defines a function for
+ each Calculation. *)
+
+CreateSetterSource[calcs_, debug_] :=
+ {whoWhen[CodeGen`SOURCELANGUAGE],
+
+ "#define KRANC_" <> ToUpperCase[CodeGen`SOURCELANGUAGE] <> "\n\n",
+
+ If[CodeGen`SOURCELANGUAGE == "C",
+ IncludeFile["math.h"],
+ "\n"
+ ],
+
+ Map[IncludeFile, {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h",
+ "precomputations.h", "GenericFD.h"}],
+ calculationMacros[],
+
+ (* For each function structure passed, create the function and
+ insert it *)
+ Map[CreateCalculationFunction[# , debug]& ,
+ calcs]};
+
+
+
+(* ------------------------------------------------------------------------
+ Symmetries Registration
+ ------------------------------------------------------------------------ *)
+
+(* Symmetries registration spec = {{FullName -> "impl::GFname",
+ Sym -> {symX, symY, symZ}}, ...} *)
+
+SymmetriesBlock[spec_] :=
+
+ Module[{i, KrancDim},
+
+ KrancDim = 3;
+
+ sym = lookup[spec, Sym];
+
+ {Table["sym[" <> ToString[i - 1] <> "] = " <>
+ ToString@sym[[i]] <> ";\n", {i, 1, KrancDim}],
+
+ "SetCartSymVN(cctkGH, sym, \"" <> lookup[spec, FullName] <> "\");\n\n"
+}
+];
+
+
+calcSymmetry[gf_] := Module[{sym, q, string},
+
+sym = {1, 1, 1}; (* default *)
+
+string = ToString@gf;
+
+While[IntegerQ[q = ToExpression@StringTake[string, -1]],
+
+Module[{},
+ sym[[q]] = -sym[[q]];
+ string = StringDrop[string, -1]
+ ]
+];
+sym
+];
+
+
+(* Given a symmetries registration structure as defined above, return a
+ C CodeGen structure of a source file which will register the symmetries. *)
+CreateSymmetriesRegistrationSource[thornName_, implementationName_, GFs_, debug_] :=
+
+ Module[{spec, j, lang, tmp},
+
+ If[debug,
+ Print["Registering Symmetries for: ", GFs];
+ ];
+
+ lang = CodeGen`SOURCELANGUAGE;
+ CodeGen`SOURCELANGUAGE = "C";
+
+ spec = Table[{FullName -> implementationName <> "::" <> ToString@GFs[[j]],
+ Sym -> calcSymmetry[GFs[[j]] ]
+ }, {j, 1, Length@GFs}];
+
+ tmp = {whoWhen["C"],
+
+ Map[IncludeFile,
+ {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h", "Symmetry.h"}],
+
+ DefineCCTKFunction[ thornName <> "_RegisterSymmetries", "void",
+ {CommentedBlock["array holding symmetry definitions",
+
+ "CCTK_INT sym[3];\n\n"],
+
+ CommentedBlock["Register symmetries of grid functions",
+
+ Map[SymmetriesBlock, spec]]}
+]
+ };
+
+ CodeGen`SOURCELANGUAGE = lang;
+
+tmp
+];
+
+
+(* ------------------------------------------------------------------------
+ MoL Registration
+ ------------------------------------------------------------------------ *)
+
+(* MoL registration = {EvolvedGFs -> {h11, ...}, PrimitiveGFs -> {trK, ...},
+ BaseImplementation -> "ADMBase", ThornName -> "ADMMoL"} *)
+
+(* Given a MoL registration structure as defined above, return a
+ CodeGen structure of a source file which will register the
+ variables given with MoL. *)
+CreateMoLRegistrationSource[spec_, debug_] :=
+
+ Module[{tmp, lang},
+
+ If[debug,
+ Print["Registering for MoL:"];
+ Print[];
+ Print[" Evolved Gridfunctions: ", lookup[spec, EvolvedGFs] ];
+ Print[" Primitive Gridfunctions: ", lookup[spec, PrimitiveGFs] ];
+ ];
+
+ lang = CodeGen`SOURCELANGUAGE;
+ CodeGen`SOURCELANGUAGE= "C";
+
+ tmp = {whoWhen["C"],
+
+ Map[IncludeFile,
+ {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h"}],
+
+ DefineCCTKFunction[lookup[spec,ThornName] <> "_RegisterVars", "CCTK_INT",
+ {DefineVariable["ierr", "CCTK_INT", "0"],
+
+ CommentedBlock["Register all the evolved grid functions with MoL",
+
+ Map[{"ierr += MoLRegisterEvolved(CCTK_VarIndex(\"",
+ lookup[spec,BaseImplementation], "::", #, "\"), CCTK_VarIndex(\"",
+ lookup[spec,BaseImplementation], "::", #, "rhs\"));\n"} &,
+ lookup[spec, EvolvedGFs]]],
+
+ CommentedBlock["Register all the primitive grid functions with MoL",
+ Map[{"ierr += MoLRegisterConstrained(CCTK_VarIndex(\"",
+ lookup[spec,BaseImplementation], "::", #, "\"));\n"} &,
+ lookup[spec, PrimitiveGFs]]],
+ "return ierr;\n"}]};
+
+ CodeGen`SOURCELANGUAGE = lang;
+
+tmp
+];
+
+(* ------------------------------------------------------------------------
+ MoL Boundaries
+ ------------------------------------------------------------------------ *)
+(* currently this only does periodic boundaries, i.e. provides
+ a place for SYNCing evolution variables *)
+
+(* boundaries spec = {Groups -> {trK, h11, ...},
+ BaseImplementation -> "ADMBase", ThornName -> "ADMMoL"} *)
+
+(* the boundary treatment is split into 3 steps:
+ 1. excision
+ 2. symmetries
+ 3. "other" boundary conditions, e.g. radiative
+
+To simplify scheduling, testing, etc. the 3 steps are currently applied
+in separate functions!
+*)
+
+cleanCPP[x_] := Map[StringReplace[FlattenBlock[#], " #" -> "#"]&, x];
+
+(* Given a BC registration structure as defined above, return a
+ CodeGen structure of a source file which does nothing yet! *)
+CreateMoLBoundariesSource[spec_] :=
+
+ Module[{groups, tmp, lang},
+
+ groups = lookup[spec, Groups];
+ groups = Map[lookup[spec, BaseImplementation] <> "::" <> ToString@# &, groups];
+
+ noBCGroup[group_] :=
+ " ierr = Boundary_SelectGroupForBC(cctkGH, CCTK_ALL_FACES, 1, -1, \"" <>
+ ToString@group <> "\",\t\"None\");\n";
+
+
+ flatBCGroup[group_] :=
+ " ierr = Boundary_SelectGroupForBC(cctkGH, CCTK_ALL_FACES, 1, -1, \"" <>
+ ToString@group <> "\",\t\"Flat\");\n";
+
+ lang = CodeGen`SOURCELANGUAGE;
+ CodeGen`SOURCELANGUAGE = "C";
+
+ tmp = {whoWhen["C"],
+
+
+ Map[IncludeFile,
+ {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h",
+ "cctk_Faces.h", "util_Table.h"}],
+
+ {"\n\n",
+ "/* the boundary treatment is split into 3 steps: */\n",
+ "/* 1. excision */\n",
+ "/* 2. symmetries */\n",
+ "/* 3. \"other\" boundary conditions, e.g. radiative */\n\n",
+ "/* to simplify scheduling and testing, the 3 steps */\n",
+ "/* are currently applied in separate functions */\n\n"},
+
+
+ cleanCPP@DefineCCTKFunction[lookup[spec,ThornName] <> "_CheckBoundaries",
+ "CCTK_INT",
+ {"/* check whether we can use excision */\n\n",
+ "#ifdef EXCISION_LEGOEXCISION\n",
+ "CCTK_INFO(\"Compiled with LegoExcision\");\n",
+ "#endif\n",
+ "\n",
+ "return 0;\n"}],
+
+
+ cleanCPP@DefineCCTKFunction[lookup[spec,ThornName] <> "_ApplyBoundConds",
+ "CCTK_INT",
+ {DefineVariable["ierr", "CCTK_INT", "0"],
+
+ "\n",
+ "if (CCTK_EQUALS(bound, \"none\" ) ||\n",
+ " CCTK_EQUALS(bound, \"static\") ||\n",
+ " CCTK_EQUALS(bound, \"zero\" ) ) \n",
+ "{\n",
+ " /* None or static: Do nothing, as well for Zero - why?? */\n",
+
+ Map[noBCGroup, groups],
+
+ "}\n",
+
+ "else if(CCTK_EQUALS(bound, \"flat\"))\n",
+ "{\n",
+ " /* Flat BCs ... what was it that they do?? */\n",
+
+ Map[flatBCGroup, groups],
+
+ "}\n",
+
+
+ "return ierr;\n"}]
+ };
+
+ CodeGen`SOURCELANGUAGE = lang;
+tmp
+];
+
+CreateMoLExcisionSource[spec_] :=
+
+ Module[{gfs, currentlang, body, excisionExtrap},
+
+ gfs = lookup[spec, ExcisionGFs];
+
+ Print["Applying excision to GFs: ", gfs];
+
+ currentlang = CodeGen`SOURCELANGUAGE;
+ CodeGen`SOURCELANGUAGE = "Fortran";
+
+ excisionExtrap[gf_] := "call excision_extrapolate(ierr, "
+ <> ToString@gf <> ", " <> ToString@gf
+ <> "_p, emask, exnormx, exnormy, exnormz, nx, ny, nz, v0)\n";
+
+ body = {whoWhen["Fortran"],
+
+ Map[IncludeFile,
+ {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h"}],
+
+ {"\n\n",
+ "! the boundary treatment is split into 3 steps: \n",
+ "! 1. excision \n",
+ "! 2. symmetries \n",
+ "! 3. \"other\" boundary conditions, e.g. radiative \n\n",
+ "! to simplify scheduling and testing, the 3 steps \n",
+ "! are currently applied in separate functions \n\n"},
+
+
+ cleanCPP@DefineCCTKSubroutine[lookup[spec,ThornName] <> "_ApplyExcision",
+ {"#ifdef EXCISION_LEGOEXCISION\n",
+ "! APPLY EXCISION\n\n",
+ DefineVariable["ierr", "CCTK_INT", "0"],
+ "",
+
+ "integer :: nx, ny, nz\n\n",
+ "CCTK_REAL :: v0 = 0.0d0 ! constant value used within excision mask\n\n",
+
+ "! grid parameters\n",
+
+ "nx = cctk_lsh(1)\n",
+ "ny = cctk_lsh(2)\n",
+ "nz = cctk_lsh(3)\n\n",
+
+ "call excision_findboundary(ierr, emask, nx, ny, nz)\n",
+ "call excision_findnormals (ierr, emask, exnormx, exnormy, exnormz, nx, ny, nz)",
+ "\n\n",
+
+ Map[excisionExtrap, gfs],
+ "",
+ "#endif\n\n",
+ "return\n",
+ "end subroutine\n"}]
+};
+
+CodeGen`SOURCELANGUAGE = currentlang;
+
+body
+];
+
+
+
+(* --------------------------------------------------------------------------
+ Precompmacros
+ -------------------------------------------------------------------------- *)
+
+(* Argument to this is the same as for CreateSetterSource. This is
+ not implemented currently because the precomputations are performed
+ in the setter file itself. We want to change this for readability
+ reasons. The change will be to have this precompMacros.h file
+ define a macro performing the precomputations for *each loop* in
+ each function. Then the setter source file just has a line
+ invoking the macro in each loop. *)
+CreatePrecompMacros[functions_] :=
+ Module[{},
+ {}];
+
+(* ------------------------------------------------------------------------
+ Startup file
+ ------------------------------------------------------------------------ *)
+
+CreateStartupFile[thornName_, bannerText_] :=
+ Module[{tmp, lang},
+
+ lang = CodeGen`SOURCELANGUAGE;
+ CodeGen`SOURCELANGUAGE = "C";
+
+ tmp = {whoWhen["C"],
+
+ IncludeFile["cctk.h"],
+ DefineFunction[thornName <> "_Startup", "int", "void",
+ {DefineVariable["banner", "const char *", Quote[bannerText]],
+ "CCTK_RegisterBanner(banner);\n",
+ "return 0;\n"}]};
+
+ CodeGen`SOURCELANGUAGE = lang;
+
+ tmp
+ ];
+
+(* ------------------------------------------------------------------------
+ Thorn creation
+ ------------------------------------------------------------------------ *)
+
+(* source = {Filename -> "MoLRegister.c", Contents -> "#include ..."} *)
+
+(* thorn = {Name -> "ClassicADMMolEvolve", Directory -> "ClassicADM",
+ Interface -> i, Schedule -> s, Param -> p, Makefile -> m,
+ Sources -> {s1, s2, ...} *)
+
+(* Given a thorn specification structure as defined above, create a
+ thorn. Note that if you specify a path to the thorn, then you are
+ responsible for making sure that the parent directory exists; this
+ function does not automatically create any parent directories. *)
+CreateThorn[thorn_] :=
+ Module[{thornDirectory, sourceDirectory},
+
+ thornDirectory = lookup[thorn, Directory] <> "/" <> lookup[thorn, Name];
+ sourceDirectory = thornDirectory <> "/src";
+
+ Print["Creating thorns in directory ", thornDirectory];
+
+ ensureDirectory[thornDirectory];
+ ensureDirectory[sourceDirectory];
+
+ GenerateFile[thornDirectory <> "/interface.ccl", lookup[thorn, Interface]];
+ GenerateFile[thornDirectory <> "/param.ccl", lookup[thorn, Param]];
+ GenerateFile[thornDirectory <> "/schedule.ccl", lookup[thorn, Schedule]];
+
+ Map[GenerateFile[sourceDirectory <> "/" <> lookup[#, Filename],
+ lookup[#, Contents]] &,
+ lookup[thorn, Sources]];
+
+ GenerateFile[sourceDirectory <> "/make.code.defn", lookup[thorn, Makefile]]];
+
+End[];
+
+EndPackage[];