← Back to team overview

ffc team mailing list archive

Re: Tensors

 

On Wed, Aug 31, 2005 at 07:01:02PM +0200, Johan Jansson wrote:
> On Wed, Aug 31, 2005 at 10:35:04AM -0500, Anders Logg wrote:
> 
> ...
> 
> > 2. Then Johan's suggestion. If you write
> > 
> >     epsilonu = 0.5 * (u[i].dx(i) * v[j].dx(j))
> > 
> > then this is a scalar since repeating an Index twice means summation
> > over that Index. I think the tensor notation has proven to be quite
> > powerful so I would like to keep it.
> 
> I'm very sorry, but my expression was totally wrong. I copied it from
> the wrong place, and I didn't catch it because it looked pretty
> similar. What I meant was:
> 
> epsilonu = 0.5 * (u[i].dx(j) + u[j].dx(i))

ok, now I see. Yes, this is a tensor (or more correctly a particular
component of a tensor). But it's not indexable since the indices are
already in there (i and j).

You can then declare epsilonv in the same way and do the tensor
contraction by

	    epsilonu * epsilonv

> Here the indices are not repeated, so it should not be a scalar. But
> it's still not indexable in FFC. Is it meant to be indexable? Are
> Products and Sums also supposed to be tensors?

Everything in FFC is a scalar, except for vector-valued basis
functions which need to be indexed in the declaration of a form to
produce something that is scalar. More precisely: everything in FFC is
an already indexed tensor of arbitrary rank. So if you do

   u[i].dx(j).dx(k)

then you have a scalar component of a rank 3 tensor, but with an index
(i, j, k) that need not be fixed.

> Here's a minimal example:
> 
> # Tensor test
> 
> element = FiniteElement("Vector Lagrange", "tetrahedron", 1, 3)
> 
> v = BasisFunction(element)
> u = BasisFunction(element)
> 
> gradu = u[i].dx(j)
> 
> tmp = gradu[0]
> 
> a = tmp * v[0] * dx
> 
> When I compile this, I get:
> 
>   File "Foo.py", line 36, in ?
>     tmp = gradu[0]
>   File "/usr/lib/python2.4/site-packages/ffc/compiler/algebra.py", line 383, in __getitem__
>     w.basisfunctions[0] = w.basisfunctions[0][component]
>   File "/usr/lib/python2.4/site-packages/ffc/compiler/algebra.py", line 209, in __getitem__
>     raise RuntimeError, "Cannot pick component of scalar BasisFunction."
> RuntimeError: Cannot pick component of scalar BasisFunction.

When you do tmp = u[i].dx(j), you first pick one component of the
vector-valued basis function u, so then you have a scalar. When you
then take the derivative in the j direction you obtain a new scalar
function.

It's like when you write the same thing on a piece of paper. If you
have a vector x, then x_i is not a vector but component i on the
vector. Sometimes you use the notation (x_i) to denote the vector with
components x_i for i = 1,2,.... Maybe we could add something like this
to FFC, possibly a keyword vec so that

    vec(u[i])

is the thing you want.

> Perhaps it's just a bug in FFC? I haven't been able to follow the
> error clearly. I see now that Product and Sum do have an indexing
> operator, so perhaps I was just confused about this. If they are
> indeed tensors, then we can just as well define tensor operators for
> them.

You can take two vector-valued BasisFunctions u and v and add them to
get a vector-valued Sum:

    u + v

and then you can pick a component:

    (u + v)[i] = u[i] + v[i]

> > On the other hand, you can do everything you need by indexing basis
> > functions and derivatives by integers (not Index) as you have noted.
> > This allows a user to define arbitrary operators as you have done:
> > 
> > def epsilon(u):
> >     return [ [u[i].dx(j) + u[j].dx(i) for i in range(d)] for j in range(d) ]
> 
> Here you construct a nested list structure which is a sort of tensor
> representation though (like Numeric.array). Shouldn't this work (i and
> j are Index)?:
> 
> def epsilon(u):
>     return u[i].dx(j) + u[j].dx(i)

No, same explanation as above.

> > The only thing that needs to be added to FFC is then the identity as
> > far as I can see.
> > 
> > I'm planning to add a list of predefined operators and operands to FFC
> > to simplify and beautify the notation anyway, so this would fit well
> > into that category.
> > 
> > Operators that will be added include grad(), rot() and div().
> > 
> > Operands that will be added include h (mesh size) and d (space dimension).
> > 
> > Any other suggestions?
> 
> It would also be good to have matrix operators, but that requires
> matrix-valued algebra objects. Matrix multiplication, gradient of a
> vector etc. But as I mentioned, as soon as indexing works, then the
> rest of the operators should be trivial to implement.

They are in a sense matrix-valued already (like u[i].dx(j)) but you
always work with the scalar components.

I hope things are a little more clear now. I need to write this up in
the FFC manual to avoid confusion.

> > All these can be added on top of the existing machinery (I think). As
> > far as possible, I would like to keep the basic layer simple and add
> > complexity by combining the simple primitives.
> > 
> > /Anders
> 
> Yes, I agree with this.

/Anders



References