Source code for sfepy.discrete.parse_regions

"""
Grammar for selecting regions of a domain.

Regions serve for selection of certain parts of the computational domain
represented as a finite element mesh. They are used to define the boundary
conditions, the domains of terms and materials etc.

Notes
-----
History: pre-git versions already from from 13.06.2006.
"""
from __future__ import print_function
from pyparsing import Literal, CaselessLiteral, Word, delimitedList,\
     Group, Optional, ZeroOrMore, nums, alphas, alphanums,\
     Combine, StringStart, StringEnd, Forward, oneOf, ParseException

ParseException # Needed for importing elsewhere.

op_codes = ['OA_SubV', 'OA_SubE', 'OA_SubF', 'OA_SubC', 'OA_SubS',
            'OA_AddV', 'OA_AddE', 'OA_AddF', 'OA_AddC', 'OA_AddS',
            'OA_IntersectV', 'OA_IntersectE', 'OA_IntersectF',
            'OA_IntersectC', 'OA_IntersectS']
eval_codes = ['E_VIR', 'E_VOS', 'E_VBF', 'E_VOG', 'E_OVIR', 'E_VI', 'E_VOSET',
              'E_CBF', 'E_COG', 'E_CI', 'E_COSET']
kw_codes = ['KW_All', 'KW_Region']

[docs]def to_stack(stack): def push_first(str, loc, toks): if toks: stack.append(toks[0]) return toks return push_first
[docs]def replace(what, keep=False): def _replace(str, loc, toks): ret = {'token' : what, 'orig' : []} if keep: ret['orig'] = list(toks[0]) return ret return _replace
[docs]def replace_with_region(what, r_index): def _replace(str, loc, toks): ret = {'token' : what, 'orig' : []} orig = toks[0] r_orig = orig[r_index] if isinstance(r_orig, dict) and (r_orig['token'] == 'KW_Region'): orig = list(orig[:r_index]) + r_orig['orig'] ret['orig'] = orig return ret return _replace
[docs]def join_tokens(str, loc, toks): return [" ".join(toks[0])]
[docs]def visit_stack(stack, op_visitor, leaf_visitor): def visit(stack, level): op = stack.pop() token = op['token'] if token in op_codes: res2 = visit(stack, level + 1) res1 = visit(stack, level + 1) return op_visitor(level, op, res1, res2) elif token in eval_codes: return leaf_visitor(level, op) elif token in kw_codes: return leaf_visitor(level, op) else: raise ValueError(token) return visit(stack, 0)
[docs]def create_bnf(stack): point = Literal(".") e = CaselessLiteral("E") inumber = Word(nums) fnumber = Combine(Word("+-"+nums, nums) + Optional(point + Optional(Word(nums))) + Optional(e + Word("+-"+nums, nums))) _of = Literal('of') _in = Literal('in') _by = Literal('by') _copy = Literal('copy') _mv = Literal('-v').setParseAction(replace('OA_SubV')) _me = Literal('-e').setParseAction(replace('OA_SubE')) _mf = Literal('-f').setParseAction(replace('OA_SubF')) _mc = Literal('-c').setParseAction(replace('OA_SubC')) _ms = Literal('-s').setParseAction(replace('OA_SubS')) _pv = Literal('+v').setParseAction(replace('OA_AddV')) _pe = Literal('+e').setParseAction(replace('OA_AddE')) _pf = Literal('+f').setParseAction(replace('OA_AddF')) _pc = Literal('+c').setParseAction(replace('OA_AddC')) _ps = Literal('+s').setParseAction(replace('OA_AddS')) _inv = Literal('*v').setParseAction(replace('OA_IntersectV')) _ine = Literal('*e').setParseAction(replace('OA_IntersectE')) _inf = Literal('*f').setParseAction(replace('OA_IntersectF')) _inc = Literal('*c').setParseAction(replace('OA_IntersectC')) _ins = Literal('*s').setParseAction(replace('OA_IntersectS')) regop = (_mv | _me | _mf | _mc | _ms | _pv | _pe | _pf | _pc | _ps | _inv | _ine | _inf | _inc | _ins) lpar = Literal("(").suppress() rpar = Literal(")").suppress() _all = Literal('all').setParseAction(replace('KW_All')) vertex = Literal('vertex') vertices = Literal('vertices') cell = Literal('cell') cells = Literal('cells') group = Literal('group') _set = Literal('set') surface = Literal('surface') ident = Word(alphas + '_.', alphanums + '_.') set_name = Word(nums) | ident function = Word(alphas + '_', alphanums + '_') function = Group(function).setParseAction(join_tokens) region = Combine(Literal('r.') + Word(alphas + '_-', '_-' + alphas + nums + '.')) region = Group(Optional(_copy, default='nocopy') + region) region.setParseAction(replace('KW_Region', keep=True)) coor = oneOf('x y z') boolop = oneOf('& |') relop = oneOf('< > <= >= != ==') bool_term = (ZeroOrMore('(') + (coor | fnumber) + relop + (coor | fnumber) + ZeroOrMore(')')) relation = Forward() relation << (ZeroOrMore('(') + bool_term + ZeroOrMore(boolop + relation) + ZeroOrMore(')')) relation = Group(relation).setParseAction(join_tokens) nos = Group(vertices + _of + surface).setParseAction(replace('E_VOS')) nir = Group(vertices + _in + relation).setParseAction( replace('E_VIR', keep=True)) nbf = Group(vertices + _by + function).setParseAction( replace('E_VBF', keep=True)) ebf = Group(cells + _by + function).setParseAction( replace('E_CBF', keep=True)) eog = Group(cells + _of + group + Word(nums)).setParseAction( replace('E_COG', keep=True)) nog = Group(vertices + _of + group + Word(nums)).setParseAction( replace('E_VOG', keep=True)) onir = Group(vertex + _in + region).setParseAction( replace_with_region('E_OVIR', 2)) ni = Group(vertex + delimitedList(inumber)).setParseAction( replace('E_VI', keep=True)) ei = Group(cell + delimitedList(inumber)).setParseAction( replace('E_CI', keep=True)) noset = Group(vertices + _of + _set + set_name).setParseAction( replace('E_VOSET', keep=True)) eoset = Group(cells + _of + _set + set_name).setParseAction( replace('E_COSET', keep=True)) region_expression = Forward() atom1 = (_all | region | ni | onir | nos | nir | nbf | ei | ebf | eog | nog | noset | eoset) atom1.setParseAction(to_stack(stack)) atom2 = (lpar + region_expression.suppress() + rpar) atom = (atom1 | atom2) aux = (regop + region_expression) aux.setParseAction(to_stack(stack)) region_expression << atom + ZeroOrMore(aux) region_expression = StringStart() + region_expression + StringEnd() return region_expression