diff --git a/sympde/expr/basic.py b/sympde/expr/basic.py index f91acf9d..ed2a2c03 100644 --- a/sympde/expr/basic.py +++ b/sympde/expr/basic.py @@ -80,9 +80,9 @@ def fields(self): args = self.variables if self.is_bilinear: args = args[0]+args[1] - fields = list(atoms.difference(args)) + fields = tuple(atoms.difference(args)) else: - fields = list(atoms) + fields = tuple(atoms) return fields # TODO use .atoms @@ -90,7 +90,7 @@ def fields(self): def constants(self): ls = self.expr.atoms(Constant) # no redanduncy - return list(ls) + return tuple(ls) def annotate(self): @@ -159,9 +159,9 @@ def fields(self): args = self.variables if self.is_bilinear: args = args[0]+args[1] - fields = list(atoms.difference(args)) + fields = tuple(atoms.difference(args)) else: - fields = list(atoms) + fields = tuple(atoms) return fields # TODO use .atoms @@ -169,7 +169,7 @@ def fields(self): def constants(self): ls = self.expr.atoms(Constant) # no redanduncy - return list(ls) + return tuple(ls) @property def domain(self): diff --git a/sympde/expr/evaluation.py b/sympde/expr/evaluation.py index b499aaec..2a639492 100644 --- a/sympde/expr/evaluation.py +++ b/sympde/expr/evaluation.py @@ -1,7 +1,7 @@ # coding: utf-8 from itertools import product - +from collections import OrderedDict from sympy import S from sympy import Indexed, Matrix, ImmutableDenseMatrix from sympy import expand @@ -29,7 +29,6 @@ from sympde.topology import DetJacobian from sympde.topology import SymbolicDeterminant from sympde.topology import LogicalExpr -from sympde.topology.space import ScalarFunctionSpace from sympde.topology.space import ScalarTestFunction from sympde.topology.space import VectorTestFunction from sympde.topology.space import IndexedTestTrial @@ -48,6 +47,7 @@ from sympde.topology.derivatives import Bracket_2d from sympde.topology.derivatives import Laplace_1d, Laplace_2d, Laplace_3d from sympde.topology.derivatives import Hessian_1d, Hessian_2d, Hessian_3d +from sympde.topology.space import ScalarFunctionSpace from .basic import BasicExpr, BasicForm from .expr import BilinearForm @@ -853,26 +853,41 @@ def _split_test_function(expr): name = expr.name ls = [] - for i in range(0, dim): + for i in range(dim): Di = Interval() Vi = ScalarFunctionSpace('tmp_V_{}'.format(i), domain=Di) - ai = ScalarTestFunction(Vi, '{name}{i}'.format(name=name, i=i+1)) + ai = ScalarTestFunction(Vi, '{name}_{i}'.format(name=name, i=i+1)) ls += [ai] + return {expr:tuple(ls)} + elif isinstance(expr, VectorTestFunction): + + dim = expr.space.ldim + name = expr.name + + ls = OrderedDict() + Di = Interval() + for i in range(dim): + Vi = ScalarFunctionSpace('tmp_V_{}'.format(i), domain=Di) + ls[expr[i]] = tuple(ScalarTestFunction(Vi, '{name}_{i}_{j}'.format(name=name, i=i,j=j+1)) for j in range(dim)) + return ls elif isinstance(expr, IndexedTestTrial): - i = expr.indices - assert(len(i) == 1) - i = i[0] + dim = expr.base.space.ldim + index = expr.indices[0] + name = expr.base.name - V = expr.base.space - Vi = ScalarFunctionSpace('tmpV_{}'.format(i), V.domain) - vi = ScalarTestFunction(Vi, '{test}{i}'.format(test=expr.base.name, i=i)) + Di = Interval() - return _split_test_function(vi) + ls = [] + for i in range(dim): + Vi = ScalarFunctionSpace('tmp_V_{}'.format(i), domain=Di) + ai = ScalarTestFunction(Vi, '{name}_{j}_{i}'.format(name=name, j=index,i=i+1)) + ls += [ai] + return {expr:tuple(ls)} else: msg = 'Expecting ScalarTestFunction or IndexedTestTrial, given {}'.format(type(expr)) @@ -1155,7 +1170,7 @@ def eval(cls, *_args, **kwargs): d_atoms = {} for a in variables: new = _split_test_function(a) - d_atoms[a] = new + d_atoms[a] = new[a] # ... # ... diff --git a/sympde/expr/expr.py b/sympde/expr/expr.py index 755e80f0..78f16699 100644 --- a/sympde/expr/expr.py +++ b/sympde/expr/expr.py @@ -63,7 +63,7 @@ def _get_domain(expr): elif isinstance(a, BasicDomain): domains = domains.union([a]) if len(domains) == 1: - return list(domains)[0] + return tuple(domains)[0] return Union(*domains) #============================================================================== @@ -93,7 +93,6 @@ def expr(self): def __call__(self, *args): args = _sanitize_arguments(args, is_linear=True) - args = Tuple(*args) expr, _ = self.expr._xreplace(dict(list(zip(self.variables, args)))) return expr @@ -266,7 +265,7 @@ def __new__(cls, expr, domain, eval=True): obj = Basic.__new__(cls, expr, domain) # compute dim from fields if available - ls = list(expr.atoms((ScalarField, VectorField))) + ls = tuple(expr.atoms((ScalarField, VectorField))) if ls: F = ls[0] space = F.space diff --git a/sympde/topology/mapping.py b/sympde/topology/mapping.py index 4d5a8720..7e7e5e5b 100644 --- a/sympde/topology/mapping.py +++ b/sympde/topology/mapping.py @@ -16,6 +16,7 @@ from sympde.core.basic import BasicMapping from sympde.core.basic import CalculusFunction from sympde.core.basic import _coeffs_registery +from sympde.topology import NormalVector from .basic import BasicDomain from .space import ScalarTestFunction, VectorTestFunction, IndexedTestTrial @@ -39,7 +40,7 @@ class Mapping(BasicMapping): _expressions = None # used for analytical mapping # TODO shall we keep rdim ? - def __new__(cls, name, rdim, coordinates=None): + def __new__(cls, name, rdim, coordinates=None, **kwargs): if isinstance(rdim, (tuple, list, Tuple)): if not len(rdim) == 1: raise ValueError('> Expecting a tuple, list, Tuple of length 1') @@ -93,7 +94,10 @@ def __new__(cls, name, rdim, coordinates=None): for i in constants: # TODO shall we add the type? # by default it is real - d[i] = Constant(i.name) + if i.name in kwargs: + d[i] = kwargs[i.name] + else: + d[i] = Constant(i.name) args = args.subs(d) # ... @@ -549,6 +553,7 @@ def eval(cls, *_args): expr = _args[1] dim = M.rdim # TODO this is not the dim of the domain l_coords = ['x1', 'x2', 'x3'][:dim] + ph_coords = ['x', 'y', 'z'] if M.is_analytical: for i in range(dim): @@ -556,8 +561,13 @@ def eval(cls, *_args): if isinstance(expr, Symbol) and expr.name in l_coords: return expr + elif isinstance(expr, Symbol) and expr.name in ph_coords: + if M.is_analytical: + return M.expressions[ph_coords.index(expr.name)] + else: + return expr - if isinstance(expr, Add): + elif isinstance(expr, Add): args = [cls.eval(M, a) for a in expr.args] return Add(*args) @@ -577,7 +587,7 @@ def eval(cls, *_args): else: return expr - elif isinstance(expr, (ScalarField, ScalarTestFunction, IndexedTestTrial, IndexedVectorField)): + elif isinstance(expr, (ScalarField, ScalarTestFunction, IndexedTestTrial, IndexedVectorField, Indexed)): return expr elif isinstance(expr, (VectorField, VectorTestFunction)): @@ -691,7 +701,8 @@ def eval(cls, *_args): elif isinstance(expr, Symbol): return expr - + elif isinstance(expr, NormalVector): + return expr elif isinstance(expr, Function): func = expr.func args = expr.args @@ -776,7 +787,7 @@ def eval(cls, *_args, **kwargs): return Matrix(lines) - elif isinstance(expr, (ScalarField, ScalarTestFunction)): + elif isinstance(expr, (ScalarField, ScalarTestFunction, VectorField, VectorTestFunction)): if code: name = '{name}_{code}'.format(name=expr.name, code=code) else: @@ -784,9 +795,6 @@ def eval(cls, *_args, **kwargs): return Symbol(name) - elif isinstance(expr, (VectorField, VectorTestFunction)): - raise NotImplementedError('') - elif isinstance(expr, Indexed): base = expr.base if isinstance(base, Mapping):