← Back to team overview

ffc team mailing list archive

Projections

 

I have added support for general projections between function spaces.

Here's a short tutorial before we get this into the manual:

- A Projection is constructed from a given FiniteElement and
  represents the local L2 projection onto that element:

    element = FiniteElement(...)
    pi = Projection(element)

- Projections can only be applied to Functions:

    L = v*pi(f)*dx

  They can not be applied to BasisFunctions or expressions.

- Multiple projections of a Function and the Function itself can be
  mixed:

    pi0 = Projection(e0)
    pi1 = Projection(e1)
   
    L = v*f*pi0(f)*pi1(f)*dx

- One of the main uses for Projections will be to simplify and speed
  up the use of Functions in complicated forms, in particular the
  stabilization term of Navier-Stokes:

    P1 = FiniteElement("Vector Lagrange", "tetrahedron", 1)
    P0 = FiniteElement("Discontinuous vector Lagrange", "tetrahedron", 0)
 
    U  = Function(P1)
    pi = Projection(P0)

  Then U and its piecewise constant projection pi(U) can be mixed
  freely in the form. (Use pi(U) in the stabilization term.)

  I will add a new operator mean() that automates the projection onto
  piecewise constants, but use this in the meantime.

- I've added a simple example in src/demo/Projection.form:

    P0 = FiniteElement("Discontinuous Lagrange", "triangle", 0)
    P1 = FiniteElement("Lagrange", "triangle", 1)
    P2 = FiniteElement("Lagrange", "triangle", 2)

    v = BasisFunction(P1)
    f = Function(P1)

    pi0 = Projection(P0)
    pi1 = Projection(P1)
    pi2 = Projection(P2)

    L = v*(pi0(f) + pi1(f) + pi2(f))*dx

  This defines a piecewise linear function f and uses its projection
  onto P0, P1 (which has no effect) and P2. Here's some of the code
  that this demo generates:

  void eval(real block[], const AffineMap& map) const
  {
    // Compute coefficients
    const real c0_0 = 3.333333333333333e-01*c[0][0] + 3.333333333333334e-01*c[0][1] + 3.333333333333333e-01*c[0][2];
    const real c1_0 = c[0][0];
    const real c1_1 = c[0][1];
    const real c1_2 = c[0][2];
    const real c2_0 = c[0][0];
    const real c2_1 = c[0][1];
    const real c2_2 = c[0][2];
    const real c2_3 = 5.000000000000000e-01*c[0][1] + 4.999999999999998e-01*c[0][2];
    const real c2_4 = 4.999999999999999e-01*c[0][0] + 4.999999999999997e-01*c[0][2];
    const real c2_5 = 5.000000000000000e-01*c[0][0] + 5.000000000000001e-01*c[0][1];

    // Compute geometry tensors
    const real G0_0 = map.det*c0_0;
    const real G1_0 = map.det*c1_0;
    const real G1_1 = map.det*c1_1;
    const real G1_2 = map.det*c1_2;
    const real G2_0 = map.det*c2_0;
    const real G2_1 = map.det*c2_1;
    const real G2_2 = map.det*c2_2;
    const real G2_3 = map.det*c2_3;
    const real G2_4 = map.det*c2_4;
    const real G2_5 = map.det*c2_5;

    ...
  }

There will be new release of FFC when I have received some
confirmation that there are no obvious bugs.

/Anders