← Back to team overview

dolfin team mailing list archive

Re: Value rank and geometrical dimension for Expressions

 

On Mon, Oct 05, 2009 at 12:13:30AM +0200, Johan Hake wrote:
> Hello!
>
> I am trying to work my way through the Python stuff that needs to be updated.
> I have now encountered a problem with the director typemaps for double* values
> and double* x.
>
> We need the value rank and geometrical dimension to be able to wrap the value
> to Python. Previously we just used the provided FunctionSpace. Now with this
> gone we need to come up with something else.
>
> I know Anders commented that we could add these as optional virtual functions.
> That could work, but that would cause another two callbacks to Python each
> time the expression is evaluated during assemble, and what even worse:
>
>    larger code when subclassing ;)

Yes! We don't want that...

> What if we defined an optional constructor taking the value rank and
> geometrical dimensions as arguments and added two access-methods?
>
>     /// Constructor
>     Expression():_value_rank(-1),_dim(-1);
>
>     /// Constructor
>     Expression(uint value_rank, uint::dim):_value_rank(value_rank),_dim(dim);
>
>     ...
>
>     uint value_rank()
>     {
>        if _value_rank == -1
>            error("value_rank is not initialized")
>        return _value_rank
>     }
>
>     uint dim()
>     {
>        if _dim == -1
>            error("dim is not initialized")
>        return _dim
>     }
>
> A user will not instantiate an Expression using the optional constructor, this
> will be done for him behind the scene. So user code would look like:
>
>   class MyExpression(Expression):
>       eval(value,x):
>          ...
>
>   f = MyExpression(v.ufl_element())

Sounds good, but why do we need the two access functions? Shouldn't
the extra constructor be enough? We could store the value rank and
dimension as std::vector<uint> (a shape thing, same as numpy) in the
Expression class:

class Expression
{
public:

  /// Create scalar expressioin
  Expression(); // scalar

  /// Create vector-valued expression with given dimension
  Expression(uint dim);

  /// Create tensor-valued expression with given shape
  Expression(const std::vector<uint>& shape);

  std::uint rank() const;
  std::uint dim(uint i) const;
  const std::vector<uint>& shape() const;

private:

  std::vector<uint> _shape;

};

> If this is too ugly for you I can probably just add such functionality into a
> PythonExpression class. The Expression class is not that large now, or would
> that interfere with some other logic in the new GenericFunction remake?

This would be good to have and we could also check that things match
against the incoming element in the restrict() call (using assert).

We could then also reimplement the checks that are currently commented
out in Assembler.cpp and SystemAssembler.cpp.

--
Anders

Attachment: signature.asc
Description: Digital signature


Follow ups

References