From 58eb73177f4ea930b8380772bd4c7fdaa663dc8f Mon Sep 17 00:00:00 2001 From: Ian Hinder Date: Mon, 21 May 2012 18:03:15 +0200 Subject: [PATCH] Add ParameterConditions option for CreateThorn This option allows the user to set certain conditions on parameters which must be satisfied otherwise the thorn aborts with a given error message (details in Doc/KrancDoc.tex). --- Doc/KrancDoc.tex | 6 +++ Tools/CodeGen/Kranc.m | 3 +- Tools/CodeGen/KrancThorn.m | 10 +++-- Tools/CodeGen/ParamCheck.m | 83 ++++++++++++++++++++++++++++++++++++++ Tools/CodeGen/Schedule.m | 6 ++- 5 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 Tools/CodeGen/ParamCheck.m diff --git a/Doc/KrancDoc.tex b/Doc/KrancDoc.tex index a39cb741..c4f06bc1 100644 --- a/Doc/KrancDoc.tex +++ b/Doc/KrancDoc.tex @@ -968,6 +968,12 @@ \subsubsection{Named Arguments} KeywordParameters & list of KeywordParameterDefinition structures & A list of parameter definition structures for all the keyword parameters which this thorn will define and use. (optional) & \{\} \\ + ParameterConditions & list of parameter conditions & Each condition + is of the form \{\textit{condition}, \textit{message}\}, where + \textit{condition} is a boolean expression in parameter names, and + \textit{message} is the message for a fatal error which is generated + when the thorn starts if \textit{condition} is not satisfied & \{\} \\ + InheritedImplementations & list of strings & A list of all the implementations which this thorn will inherit from. This is necessary to use grid functions provided by these implementations. (optional) & \{\} \\ diff --git a/Tools/CodeGen/Kranc.m b/Tools/CodeGen/Kranc.m index 296b2c0d..fa2263d6 100644 --- a/Tools/CodeGen/Kranc.m +++ b/Tools/CodeGen/Kranc.m @@ -94,7 +94,8 @@ Variables -> Automatic, Shorthands -> {}, ParentDirectory -> ".", - GenerateScript -> False}; + GenerateScript -> False, + ParameterConditions -> {}}; ExecuteOn; Device; diff --git a/Tools/CodeGen/KrancThorn.m b/Tools/CodeGen/KrancThorn.m index 2cd4ed2f..85ebd4ca 100644 --- a/Tools/CodeGen/KrancThorn.m +++ b/Tools/CodeGen/KrancThorn.m @@ -29,7 +29,7 @@ "MapLookup`", "KrancGroups`", "Differencing`", "CalculationFunction`", "Errors`", "Helpers`", "CactusBoundary`", "KrancTensor`", "Param`", "Schedule`", "Interface`", "Kranc`", "Jacobian`", - "ConservationCalculation`", "CaKernel`", "Calculation`"}]; + "ConservationCalculation`", "CaKernel`", "Calculation`", "ParamCheck`"}]; CreateKrancThorn::usage = "Construct a Kranc thorn"; @@ -331,7 +331,7 @@ Thorn generation (main entry point for non-tensorial thorns) (* Makefile *) InfoMessage[Terse, "Creating make file"]; make = CreateMakefile[Join[{"Startup.cc", "RegisterSymmetries.cc"}, - {"RegisterMoL.cc"}, + {"RegisterMoL.cc"}, If[Length[OptionValue[ParameterConditions]] > 0, {"ParamCheck.cc"}, {}], incFilenames, Map[lookup[#, Filename] &, boundarySources]]]; @@ -350,7 +350,11 @@ Thorn generation (main entry point for non-tensorial thorns) {Filename -> "RegisterSymmetries.cc", Contents -> symregister}, {Filename -> "Differencing.h", Contents -> diffHeader}}, MapThread[{Filename -> #1, Contents -> #2} &, - {calcFilenames, calcSources}], boundarySources]}; + {calcFilenames, calcSources}], boundarySources, + If[Length[OptionValue[ParameterConditions]] > 0, + {{Filename -> "ParamCheck.cc", + Contents -> ParameterCheckSource[thornName, OptionValue[ParameterConditions]]}}, + {}]]}; InfoMessage[Terse, "Creating thorn"]; CreateThorn[thornspec]]; diff --git a/Tools/CodeGen/ParamCheck.m b/Tools/CodeGen/ParamCheck.m new file mode 100644 index 00000000..db79fb47 --- /dev/null +++ b/Tools/CodeGen/ParamCheck.m @@ -0,0 +1,83 @@ + +(* Copyright 2012 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["ParamCheck`", {"Errors`", "Helpers`", "Kranc`", "CodeGenCactus`", + "CodeGenC`", "CodeGen`"}]; + +ParameterCheckSource; +ParameterCheckSchedule; + +Begin["`Private`"]; + +DefFn[ + ParameterCheckSource[thornName_String, conditions_List] := + {Map[IncludeFile, + {"cctk.h", "cctk_Arguments.h", "cctk_Parameters.h"}], + + DefineCCTKFunction[ + thornName, "void", + ConditionalOnParameterTextual[ + "CCTK_MyProc(cctkGH) == 0", + Map[checkCondition, conditions]]]}]; + +DefFn[ + ParameterCheckSchedule[thornName_String] := + {Name -> thornName<>"_ParamCheck", + SchedulePoint -> "at CCTK_PARAMCHECK", + Options -> "global", + Language -> "C", + Comment -> "Check parameter consistency"}]; + +DefFn[checkCondition[{cond_, error_String}] := + Module[ + {render, renderbool, paramPattern}, + + paramPattern = Except[True | False, _Symbol | _Parameter]; + + renderbool[Equal[a:paramPattern,b_String]] := {"CCTK_EQUALS(", rendervalue[a], ",\"", b,"\")"}; + renderbool[Unequal[a:paramPattern,b_String]] := {"!CCTK_EQUALS(", rendervalue[a], ",\"", b,"\")"}; + renderbool[Equal[a:paramPattern,b_?NumberQ]] := {rendervalue[a], " == ", rendervalue[b]}; + renderbool[Unequal[a:paramPattern,b_?NumberQ]] := {rendervalue[a], " != ", rendervalue[b]}; + + renderbool[Or[a_,b_]] := {"(",renderbool[a]," || ", renderbool[b],")"}; + renderbool[And[a_,b_]] := {"(",renderbool[a]," && ", renderbool[b],")"}; + renderbool[Not[a_]] := {"(!", renderbool[a],")"}; + renderbool[a:paramPattern] := ToString[a/.(Parameter[x_]->x)]; (* Boolean parameter *) + + (* rendervalue[a_String] := a; -- Allow literal pass-through *) + rendervalue[a_?NumberQ] := ToString[a]; + rendervalue[Parameter[a_String]] := a; + rendervalue[a_ /; MemberQ[params,a]] := ToString[a]; + renderbool[x_] := ThrowError["Unexpected value in run-time conditional expression (boolean):", x, "in", cond]; + render[x_] := ThrowError["Unexpected value in run-time conditional expression (value):", x, "in", cond]; + + unparen[s_] := + Module[ + {s2 = FlattenBlock[s],result}, + result = StringReplace[FlattenBlock[s2],StartOfString ~~ "(" ~~ any__ ~~ ")" ~~ EndOfString :> any]; + If[result === s2, result, unparen[result]]]; + + ConditionalOnParameterTextual[ + unparen@renderbool[cond], + {"CCTK_WARN(0, ", StringDrop[Stringify[error],-1], ");\n"}]]]; + +End[]; + +EndPackage[]; diff --git a/Tools/CodeGen/Schedule.m b/Tools/CodeGen/Schedule.m index 225b447a..9ac7ca47 100644 --- a/Tools/CodeGen/Schedule.m +++ b/Tools/CodeGen/Schedule.m @@ -18,7 +18,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) -BeginPackage["Schedule`", {"Thorn`", "KrancGroups`", "MapLookup`", "Errors`", "Helpers`", "Kranc`", "CaKernel`", "Calculation`"}]; +BeginPackage["Schedule`", {"Thorn`", "KrancGroups`", "MapLookup`", "Errors`", "Helpers`", "Kranc`", "CaKernel`", "Calculation`", "ParamCheck`"}]; CreateKrancScheduleFile; @@ -300,7 +300,9 @@ scheduledFunctions = Join[{scheduledStartup, scheduleRegisterSymmetries}, scheduledCalcs, CactusBoundary`GetScheduledFunctions[thornName, evolvedGroups], - {scheduleMoLRegister}]; + {scheduleMoLRegister}, If[Length[OptionValue[ParameterConditions]] > 0, + {ParameterCheckSchedule[thornName]}, + {}]]; If[OptionValue[UseCaKernel], scheduledFunctions = Join[scheduledFunctions, CaKernelSchedule[thornName]]];