dolfin team mailing list archive
-
dolfin team
-
Mailing list archive
-
Message #15923
Re: Value rank and geometrical dimension for Expressions
On Monday 05 October 2009 07:17:48 Anders Logg wrote:
> 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?
In the typemap I can only access public variables and methods. I do not think
that making these variables public is a good idea.
> 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;
>
> };
We can store the value_shape as std::vector, similare to ufl. But we need to
store the (geometrical_)dimension too. Otherwise we cannot figure out what the
size of 'x' should be. Note that the geometrical_dimension has nothing to do
with the value rank.
So I think we need one constructor for both dimension and value_rank.
> > 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).
I assume you mean that this is good to have in the DOLFIN library?
> We could then also reimplement the checks that are currently commented
> out in Assembler.cpp and SystemAssembler.cpp.
Ok.
Johan
> --
> Anders
>
Follow ups
References