latex equation generation
This commit is contained in:
parent
b6210acb01
commit
a901ebe932
2 changed files with 163 additions and 15 deletions
|
|
@ -6,7 +6,8 @@ import argparse
|
|||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("term_file", help="name of file containing postprocessing term spec")
|
||||
parser.add_argument("-b", "--build-info", action="store_true", help="print build_info instead of code")
|
||||
parser.add_argument("-p", "--print_report", action="store_true", help="print code generation report instead of code")
|
||||
parser.add_argument("-x", "--print-latex", action="store_true", help="print latex equation instead of code")
|
||||
parser.add_argument("-p", "--print-report", action="store_true", help="print code generation report instead of code")
|
||||
args = parser.parse_args()
|
||||
|
||||
from lark import Lark, Visitor, Transformer, v_args, Token
|
||||
|
|
@ -20,14 +21,15 @@ calc_grammar = """
|
|||
|
||||
?start: statement*
|
||||
|
||||
?statement: NAME [ "(" [attr_list] ")" ] "=" sum -> assign_var
|
||||
?statement: NAME [ attr_list ] "=" sum -> assign_var
|
||||
| avg "{" [NAME ("," NAME)*] "}" -> assign_avg_var
|
||||
| varlist
|
||||
|
||||
?attr_list: attr_pair ("," attr_pair)*
|
||||
attr_list: "(" [attr_pair ("," attr_pair)*] ")"
|
||||
|
||||
?attr_pair: NAME "=" BOOL
|
||||
| NAME "=" INT
|
||||
| NAME "=" ESCAPED_STRING
|
||||
|
||||
?sum: product
|
||||
| sum "+" product -> add
|
||||
|
|
@ -42,7 +44,7 @@ calc_grammar = """
|
|||
| NAME -> var
|
||||
| NAME "'" -> fluc
|
||||
| "$" NAME -> env
|
||||
| "(" sum ")"
|
||||
| "(" sum ")" -> paren
|
||||
| inlinefunc "(" sum ")" -> icall
|
||||
| mathfunc "(" sum ("," sum)* ")" -> fcall
|
||||
| derivative "(" NAME ")" -> dnx
|
||||
|
|
@ -68,6 +70,7 @@ calc_grammar = """
|
|||
|
||||
%import common.CNAME -> NAME
|
||||
%import common.NUMBER
|
||||
%import common.ESCAPED_STRING
|
||||
%import common.INT
|
||||
%import common.WS
|
||||
|
||||
|
|
@ -89,6 +92,11 @@ def tok_to_int(tok):
|
|||
# tok.type == 'INT'
|
||||
return Token.new_borrow_pos(tok.type, int(tok), tok)
|
||||
|
||||
def tok_to_str(tok):
|
||||
"Convert the value of `tok` from string to string, while maintaining line number & column."
|
||||
# tok.type == 'ESCAPED_STRING'
|
||||
return Token.new_borrow_pos(tok.type, tok.value.strip('"'), tok)
|
||||
|
||||
class VersionInfo(object):
|
||||
|
||||
def __init__ (self, input_raw):
|
||||
|
|
@ -127,12 +135,13 @@ class VersionInfo(object):
|
|||
|
||||
|
||||
|
||||
def test(terms_raw, report=False):
|
||||
def test(terms_raw, report=False, latex=False):
|
||||
|
||||
parser = Lark(calc_grammar,
|
||||
parser='lalr',
|
||||
lexer_callbacks =
|
||||
{
|
||||
'ESCAPED_STRING': tok_to_str,
|
||||
'INT': tok_to_int,
|
||||
'BOOL': tok_to_bool
|
||||
}
|
||||
|
|
@ -150,10 +159,18 @@ def test(terms_raw, report=False):
|
|||
|
||||
cdict = ir4.print_program()
|
||||
|
||||
if not report:
|
||||
print mod_form.format( cdict )
|
||||
else:
|
||||
if report:
|
||||
ir4.save_ir()
|
||||
elif latex:
|
||||
print "{"
|
||||
for avg in ir4.averaged.values():
|
||||
print "'{}' : ".format(avg.name)
|
||||
# print r"\begin{equation}"
|
||||
print "'${}$' ,".format(avg.latex)
|
||||
# print r"\end{equation}"
|
||||
print "}"
|
||||
else:
|
||||
print mod_form.format( cdict )
|
||||
|
||||
|
||||
|
||||
|
|
@ -173,4 +190,4 @@ if __name__ == '__main__':
|
|||
if args.build_info:
|
||||
build_info(terms_raw)
|
||||
else:
|
||||
test(terms_raw, args.print_report)
|
||||
test(terms_raw, report=args.print_report, latex=args.print_latex)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
from lark import Lark, Visitor, Transformer, v_args, Token
|
||||
import warnings
|
||||
|
||||
|
||||
class CollectDefinitions(Visitor):
|
||||
|
|
@ -70,6 +71,120 @@ class ExpInspector(Visitor):
|
|||
self.deriv.add((op.data, v.value))
|
||||
|
||||
|
||||
@v_args(inline=True) # Affects the signatures of the methods
|
||||
class ExpToLatex(Transformer):
|
||||
|
||||
def __init__(self, fdict):
|
||||
self.fdict = fdict
|
||||
|
||||
def arithmatic_rooted(self, name):
|
||||
try:
|
||||
exproot = self.fdict[name].exp.data
|
||||
except AttributeError:
|
||||
exproot = "something_11fasq2afa3rfzsaerqw23"
|
||||
|
||||
return ((exproot == "add") or (exproot == "sub") or
|
||||
(exproot == "mul") or (exproot == "div"))
|
||||
|
||||
def parenthise(self, name):
|
||||
try:
|
||||
latex = self.fdict[name].latex
|
||||
latex_given = self.fdict[name].latex_given
|
||||
except KeyError:
|
||||
warnings.warn(name + " is not found")
|
||||
latex = r"\mathrm{{{}}}".format(name)
|
||||
latex_given = None
|
||||
|
||||
if self.arithmatic_rooted(name) and (latex_given is None):
|
||||
latex = "(" + latex + ")"
|
||||
|
||||
return latex
|
||||
|
||||
def number(self, numeral):
|
||||
return numeral
|
||||
|
||||
def env(self, name):
|
||||
return r"\mathrm{{{}}}".format(name.value)
|
||||
|
||||
def paren(self, name):
|
||||
return "({})".format(str(name))
|
||||
|
||||
def var(self, name):
|
||||
return self.parenthise(name.value)
|
||||
|
||||
def fluc(self, name):
|
||||
return self.parenthise(name.value)+ "''"
|
||||
|
||||
def dnx (self, partial, b):
|
||||
fmt = r"\partial_{{{}}}"
|
||||
coord = partial.data[-1]
|
||||
op = fmt.format(coord + coord if len(partial.data) > 3 else coord)
|
||||
|
||||
signature = "{}_{}".format(partial.data, b.value)
|
||||
|
||||
try:
|
||||
eq = self.fdict[signature].latex
|
||||
except KeyError:
|
||||
eq = op + self.parenthise(b.value)
|
||||
warnings.warn(signature + " is not found: " + eq)
|
||||
|
||||
return eq
|
||||
|
||||
def icall (self, a, b):
|
||||
if a.data == "sqr":
|
||||
fcode = "({0})^2".format(b)
|
||||
elif a.data == "pow3":
|
||||
fcode = "({0})^3".format(b)
|
||||
else:
|
||||
fcode = "({0})".format(b)
|
||||
return fcode
|
||||
|
||||
def fcall (self, *args):
|
||||
a = args[0]
|
||||
b = ", ".join(args[1:])
|
||||
if a == 'sqrt':
|
||||
fcode = r"\sqrt{{{}}}".format(b)
|
||||
return fcode
|
||||
elif a == 'abs':
|
||||
fcode = r"\left| {} \right|".format(b)
|
||||
return fcode
|
||||
elif a.startswith("\\"):
|
||||
fcode = r"{}{{({})}}".format(a, b)
|
||||
return fcode
|
||||
else:
|
||||
fcode = r"\mathrm{{{}}}({})".format(a, b)
|
||||
return fcode
|
||||
|
||||
def neg(self, b):
|
||||
fcode = "(-{})".format(b)
|
||||
return fcode
|
||||
|
||||
def add(self, a, b):
|
||||
fcode = "{} + {}".format(a, b)
|
||||
return fcode
|
||||
|
||||
def sub(self, a, b):
|
||||
fcode = "{} - {}".format(a, b)
|
||||
return fcode
|
||||
|
||||
def mul(self, a, b):
|
||||
fcode = "{} {}".format(a, b)
|
||||
return fcode
|
||||
|
||||
def div(self, a, b):
|
||||
fcode = "{} / {}".format(a, b)
|
||||
return fcode
|
||||
|
||||
log = lambda self : "\log"
|
||||
exp = lambda self : "\exp"
|
||||
sqrt = lambda self : "sqrt"
|
||||
abs = lambda self : "abs"
|
||||
rxn_rate = lambda self : "\omega"
|
||||
udf = lambda self, a : a.value
|
||||
|
||||
|
||||
|
||||
|
||||
@v_args(inline=True) # Affects the signatures of the methods
|
||||
class ExpToCode(Transformer):
|
||||
|
||||
|
|
@ -82,6 +197,9 @@ class ExpToCode(Transformer):
|
|||
def env(self, name):
|
||||
return name.value
|
||||
|
||||
def paren(self, name):
|
||||
return "({})".format(str(name))
|
||||
|
||||
def var(self, name):
|
||||
try:
|
||||
arrname = self.fdict[name.value].array
|
||||
|
|
@ -307,12 +425,13 @@ class Field (FieldBase):
|
|||
self.fluc, self.dep, self.derivs = ExpInspector.inspect(exp)
|
||||
self.comment = self.name + " = " + ExpToCode(self.fdict).transform(self.exp)
|
||||
|
||||
self.exporter = None
|
||||
try:
|
||||
if self.attr["export"]:
|
||||
self.exporter = FieldExporter(self.name, self.attr, self)
|
||||
except KeyError:
|
||||
pass
|
||||
self.latex_given = self.attr.get("latex")
|
||||
if self.latex_given is None:
|
||||
self.latex = ExpToLatex(self.fdict).transform(self.exp)
|
||||
else:
|
||||
self.latex = self.latex_given
|
||||
|
||||
self.exporter = self.attr.get("export")
|
||||
|
||||
'''
|
||||
for a in self.dep:
|
||||
|
|
@ -402,6 +521,8 @@ class PrimaryField (FieldBase):
|
|||
super(PrimaryField,self).__init__(name, fdict)
|
||||
self.derivs = set([])
|
||||
self.prime = True
|
||||
self.latex = name
|
||||
self.latex_given = None
|
||||
|
||||
def code (self, alloc=None):
|
||||
return "! {} is read from file".format(self.name)
|
||||
|
|
@ -425,6 +546,12 @@ class DerivedField (FieldBase):
|
|||
self.v = v
|
||||
self.dep = set([v])
|
||||
|
||||
fmt = r"\partial_{{{}}}"
|
||||
coord = op[-1]
|
||||
partial = fmt.format(coord + coord if len(op) > 3 else coord)
|
||||
|
||||
self.latex = partial + "(" + fdict[v].latex + ")"
|
||||
|
||||
def code (self, alloc=None):
|
||||
self.array = alloc[self.name] if alloc else self.name
|
||||
varray = alloc[self.v] if alloc else self.v
|
||||
|
|
@ -451,6 +578,8 @@ class AveragedField (FieldBase):
|
|||
tfield = fdict[tgt]
|
||||
self.fset = tfield.checkFluctuation()
|
||||
|
||||
self.latex = r"\langle {} \rangle".format(tfield.latex)
|
||||
|
||||
if not self.fset:
|
||||
self.tgt = tgt
|
||||
self.dep.add(tgt)
|
||||
|
|
@ -463,6 +592,8 @@ class AveragedField (FieldBase):
|
|||
if w:
|
||||
self.w = fdict[w]
|
||||
self.dep.add(w)
|
||||
self.latex += ("_{{{}}}".format(w))
|
||||
|
||||
|
||||
def code (self, alloc=None):
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue