Subject: [UFC-dev] Functions

From: "Martin Sandve Alnæs" <[email-masked]>
Date: Thu, 4 Jan 2007 10:54:27 +0100

I'm writing ufc::function wrappers for ScalarFunction, VectorFunction
and TensorFunction, to use in typemaps in the assembly. There is a
slight problem. I need to know the topological dimension to extract
the element number from ufc::cell, but the dimension is located in
ufc::mesh which is not sent to the function, and *Function doesn't
have the dimension either.

Possible solutions to this:
- pycc::*Function can know the expected dimension
- ufc::cell can have its dimension as a member
- ufc::mesh can be an additional argument to ufc::function::evaluate
What do you prefer? I think perhaps sending in ufc::mesh is the best.

Example code:

/*
 * A wrapper functor for VectorFunction.
 */
class vector_ufc_function: public ufc::function
{
  VectorFunction * func;
  int dim;

public:

  vector_ufc_function(VectorFunction * func_, int dim_):
    func(func_), dim(dim_)
  {
  }

  ~vector_ufc_function()
  {
  }

  /// Evaluate the function at the point x = (x[0], x[1], ...) in the cell
  virtual void evaluate(double* values,
                        const double* x,
                        const ufc::cell& c) const
  {
    int elm_no = c.entity_indices[dim][0];
    Ptv p(dim, const_cast<double*>(x)); // TODO: Ptv should be updated
    Ptv v(dim);
    (*func)(p, v, elm_no);
    for(unsigned int i=0; i<dim; i++)
    {
      values[i] = v[i];
    }
  }

};

martin

---

From: Kent-Andre Mardal <[email-masked]>
Date: Thu, 04 Jan 2007 11:46:55 +0100

To me, the two first options are reasonable, but the last seems a bit
overkill. 

Also, in the below code, it
is not necessary that the Ptvs v and p are of the same dimension.

I think both pycc::*Functions and ufc::function should know 
the length of the arrays in both input and output. The cell
argument should be optional.

---

From: "Martin Sandve Alnæs" <[email-masked]>
Date: Thu, 4 Jan 2007 12:08:13 +0100

On 1/4/07, Kent-Andre Mardal <[email-masked]> wrote:
> the length of the arrays in both input and output.

If you want to redesign pycc::*Function, that's fine with me. But we
should be careful with adding too much to ufc::function. It could be
something like this, consistent with the value_rank etc in
finite_element:

class function
{
  ... evaluate ...

    /// Return the rank of the domain space
    virtual unsigned int domain_rank() const = 0;

    /// Return the dimension of the domain space for axis i
    virtual unsigned int domain_dimension(unsigned int i) const = 0;

    /// Return the rank of the range space
    virtual unsigned int range_rank() const = 0;

    /// Return the dimension of the range space for axis i
    virtual unsigned int range_dimension(unsigned int i) const = 0;
}

> The cell argument should be optional.

I don't think so, since ufc::function is a minimal functor for use
with the ufc interface. Making it optional only complicates things.

martin

---

From: "Martin Sandve Alnæs" <[email-masked]>
Date: Thu, 4 Jan 2007 13:36:27 +0100

On 1/4/07, Martin Sandve Alnæs <[email-masked]> wrote:
> > tor, 04,.01.2007 kl. 12.08 +0100, skrev Martin Sandve Alnæs:
> > > class function
> > > {
> > >   ... evaluate ...
> > >
> > yes, although I am not sure if we need both rank and dimension.
>
> We could skip the rank and just let dimension be the total number of
> entries in the tensor, but in finite_element we have value_rank and
> value_dimension so I think this is more consistent. Also, it does give
> more informasjon which should be easy to provide. I'm almost done
> implementing it in SyFi.ufccodegen.

Sorry, the list got out of the loop here :)

But this still doesn't fix the problem. I'll have to do the same with
pycc::*Function to know the dimensions of them. And we need the
dimensions of the cell to interpret the arrays there (and f.ex. get
the element number). Which means either adding ufc::mesh as an
argument to function::evaluate, or duplicate topological_dimension and
geometric_dimension in the ufc::cell class. I still think I like
better to add ufc::mesh as an argument.

martin

---

From: "Martin Sandve Alnæs" <[email-masked]>
Date: Thu, 4 Jan 2007 13:58:23 +0100

> > > yes, although I am not sure if we need both rank and dimension.

Sorry, I was a bit quick here. Rank is only needed for the range, not
for the domain. For the domain, the dimension of the cell should be
enough. So I'll remove domain_*(), and rename range_* to value_* just
like in finite_element.

martin