(* $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 Kranc; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *) BeginPackage["Helpers`", {"Kranc`"}]; TensorName::usage = "get the base name of a tensor object, i.e. TensorName[g[la, lb]] -> TensorName"; EnsureDirectory::usage = "create a directory if it does not already exist" SafeDelete::usage = "SafeDelete[filename] deletes a file only after checking that the file actually exists\ and is a normal file"; AddSuffix::usage = "AddSuffix[object,suffixString] adds a suffix to an object"; GFsFromGroupList::usage = "GFsFromGroupList[g] gives the GFs from a group list in the form {\"group\", {gf1, gf2, ...}}"; IsNotEmptyString::usage = "IsNotEmptyString[x] returns False if x == \"\" and True otherwise."; PickMatch::usage = "PickMatch[x, form] returns string x if it matches form, and \"\" otherwise."; SafeStringReplace::usage = "SafeStringReplace[x, string1, string2] replaces string1 in x by string2 if x is a string\ and otherwise returns x."; String2Char::usage = "String2Char[string] splits a string into a list of characters."; SortString::usage = "SortString[string] returns a string where the characters in the original string have been sorted lexicographically."; GroupStruct::usage = "GroupStruct[g_] returns a group structure the from {\"group\", {gf1, gf2, ...}}"; ComponentList::usage = "ComponentList[T[index]] creates a list of tensor components."; TextComponentList::usage = "TextComponentList[T[index]] call ComponentList and converts to plain text format \ (no sub- or superscripts)."; SortTensorComponentsCactusStyle::usage = "sorts a list of strings in Cactus tensor-components style,\ e.g. {\"vect3\", \"vect2\", \"vect1\"} -> {\"vect1\", \"vect2\", \"vect3\"}"; BreakTensorComponentName::usage = "BreakTensorComponentName[x] maps \"bla11rhs\" -> {\"bla\", \"11\", \"rhs\"}\ and \"blu321\" -> {\"blu\", \"321\", \"\"}"; Begin["`Private`"]; TensorName[t_[i__]] := t (* remove indices from a tensor *) AddSuffix[object_,suffix_] := ToExpression[ToString@object <> ToString@suffix] EnsureDirectory[name_] := If[FileType[name] == None, CreateDirectory[name, CreateIntermediateDirectories -> True]]; SafeDelete[filename_?StringQ] := If[FileType@filename == File, DeleteFile@filename]; GFsFromGroupList[g_] := Flatten@Map[Last,g] IsNotEmptyString[x_] := TrueQ[x != ""]; PickMatch[x_?StringQ, form_?StringQ] := If[StringMatchQ[x, form], x, ""]; SafeStringReplace[x_, string1_?StringQ, string2_?StringQ] := If[StringQ@x, StringReplace[x, string1 -> string2], x]; String2Char[x_?StringQ] := Table[StringTake[x, {n}], {n, 1, StringLength@x}]; SortString[x_?StringQ] := StringJoin@Sort@String2Char@x; If[ValueQ@Global`tensorNames2componentNames[dummy_tensor], (* we assume DecomposeTools.m is loaded -- need to load DecomposeTools before Helpers.m ! *) (* ComponentList creates a list of independent tensor components *) (* TextComponent List produces a plain text version of the output of *) (* the 2-argument versions can handle expressions instead of just single tensors *) ComponentList[T_] := T /. Global`makeSplitRules[T]; TextComponentList[T_] := Global`tensorNames2componentNames@ComponentList[T]; ComponentList[expr_, T_?AtomQ[index__]] := expr /. Global`makeSplitRules[T[index]]; TextComponentList[expr_, T_?AtomQ[index__]] := Global`tensorNames2componentNames@ComponentList[expr, T[index]]; ComponentList[TensorList_?ListQ] := Flatten@Map[ComponentList, TensorList]; TextComponentList[TensorList_?ListQ] := Global`tensorNames2componentNames@ComponentList[TensorList]; (* GroupStruct produces a Kranc-style group structure for tensors or scalars*) GroupStruct[t_[i__]] := {ToString@t, ComponentList@t[i]} // Global`tensorNames2componentNames; GroupStruct[S_?AtomQ] := {ToString@S,{S}}; ]; (* functions to sort variables in the standard Cactus lexigraphic style, e.g. for interface.ccl entries *) BreakTensorComponentName[x_?StringQ] := Module[{DropNumberRule, base, index, suffix}, DropNumberRule = { "1" -> "", "2" -> "", "3" -> "", "4" -> "", "5" -> "", "6" -> "", "7" -> "", "8" -> "", "9" -> "", "0" -> "", "rhs" -> "", "RHS" -> ""}; suffix = ""; If[StringMatchQ[x, "*rhs"], suffix = "rhs"]; If[StringMatchQ[x, "*RHS"], suffix = "RHS"]; base = StringReplace[x, DropNumberRule]; index = StringDrop[x, StringLength@base]; index = StringDrop[index, -StringLength@suffix]; {base, index, suffix} ]; tensorCompLexicalReorder[x_?StringQ] := Module[{break, base, index, suffix}, break = BreakTensorComponentName[x]; base = break[[1]]; index = break[[2]]; suffix = break[[3]]; newOrder = base <> SortString@index <> suffix ]; compareReordered[x_?StringQ, y_?StringQ] := Module[{reordered, stringlist}, stringlist = {x, y}; reordered = Map[tensorCompLexicalReorder, stringlist]; OrderedQ@reordered ]; SortTensorComponentsCactusStyle[stringlist_?ListQ] := Sort[stringlist, compareReordered]; (* this is only correct for totally symmetric objects! *) SortTensorComponentsCactusStyle[stringlist_?ListQ, type_?StringQ] := Switch[type, "scalar", stringlist, "U", Sort[stringlist, compareReordered], "D", stringlist, "DD", Sort@stringlist, "UU", Sort@stringlist, "DD_sym", Sort[stringlist, compareReordered], "UU_sym", Sort[stringlist, compareReordered], "DDD_sym", Sort[stringlist, compareReordered], _, stringlist ]; End[]; EndPackage[];