// Automatically generated by FFC, the FEniCS Form Compiler, version 0.3.5.
// For further information, go to http://www/fenics.org/ffc/.
// Licensed under the GNU GPL Version 2.

#ifndef __MIXEDPOISSON_H
#define __MIXEDPOISSON_H

#include <dolfin/Mesh.h>
#include <dolfin/Cell.h>
#include <dolfin/Point.h>
#include <dolfin/AffineMap.h>
#include <dolfin/FiniteElement.h>
#include <dolfin/FiniteElementSpec.h>
#include <dolfin/BilinearForm.h>
#include <dolfin/LinearForm.h>
#include <dolfin/Functional.h>
#include <dolfin/FEM.h>

namespace dolfin { namespace MixedPoisson {

/// This class contains the form to be evaluated, including
/// contributions from the interior and boundary of the domain.

class BilinearForm : public dolfin::BilinearForm
{
public:

  class TestElement;

  class TrialElement;

  BilinearForm();
  

  bool interior_contribution() const;

  void eval(real block[], const AffineMap& map) const;

  bool boundary_contribution() const;

  void eval(real block[], const AffineMap& map, unsigned int facet) const;

};

class BilinearForm::TestElement : public dolfin::FiniteElement
{
public:

  TestElement() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 3;

    subelements = new FiniteElement* [2];
    subelements[0] = new SubElement_0();
    subelements[1] = new SubElement_1();
  }

  ~TestElement()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 7;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 2;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
    int offset = 2*mesh.topology().size(1);
    nodes[6] = offset + cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
    int offset = 2*mesh.topology().size(1);
    vertex_nodes[1] = offset + vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *subelements[i];
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *subelements[i];
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("mixed");
    return s;
  }
  
private:

class SubElement_0 : public dolfin::FiniteElement
{
public:

  SubElement_0() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 2;

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_0()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 6;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Brezzi-Douglas-Marini", "triangle", 1, 2);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

class SubElement_1 : public dolfin::FiniteElement
{
public:

  SubElement_1() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    // Element is scalar, don't need to initialize tensordims

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_1()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 1;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_error("Element is scalar.");
    return 0;
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 0;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    nodes[0] = cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Discontinuous Lagrange", "triangle", 0);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

  unsigned int* tensordims;
  FiniteElement** subelements;

};

class BilinearForm::TrialElement : public dolfin::FiniteElement
{
public:

  TrialElement() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 3;

    subelements = new FiniteElement* [2];
    subelements[0] = new SubElement_0();
    subelements[1] = new SubElement_1();
  }

  ~TrialElement()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 7;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 2;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
    int offset = 2*mesh.topology().size(1);
    nodes[6] = offset + cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
    int offset = 2*mesh.topology().size(1);
    vertex_nodes[1] = offset + vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *subelements[i];
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *subelements[i];
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("mixed");
    return s;
  }
  
private:

class SubElement_0 : public dolfin::FiniteElement
{
public:

  SubElement_0() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 2;

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_0()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 6;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Brezzi-Douglas-Marini", "triangle", 1, 2);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

class SubElement_1 : public dolfin::FiniteElement
{
public:

  SubElement_1() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    // Element is scalar, don't need to initialize tensordims

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_1()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 1;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_error("Element is scalar.");
    return 0;
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 0;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    nodes[0] = cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Discontinuous Lagrange", "triangle", 0);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

  unsigned int* tensordims;
  FiniteElement** subelements;

};

BilinearForm::BilinearForm() : dolfin::BilinearForm(0)
{
  // Create finite element for test space
  _test = new TestElement();

  // Create finite element for trial space
  _trial = new TrialElement();
}

// Contribution from the interior
bool BilinearForm::interior_contribution() const { return true; }

void BilinearForm::eval(real block[], const AffineMap& map) const
{
  // Compute geometry tensors
  const real G0_ = map.det;
  const real G1_ = map.det;
  const real G2_0 = map.det*map.g00;
  const real G2_1 = map.det*map.g10;
  const real G3_0 = map.det*map.g01;
  const real G3_1 = map.det*map.g11;
  const real G4_0 = map.det*map.g00;
  const real G4_1 = map.det*map.g10;
  const real G5_0 = map.det*map.g01;
  const real G5_1 = map.det*map.g11;

  // Compute element tensor
  block[0] = 6.666666666666655e-01*G0_ + 1.666666666666665e-01*G1_;
  block[1] = -3.333333333333328e-01*G0_ - 3.333333333333330e-01*G1_;
  block[2] = -1.178511301977578e-01*G0_ - 2.357022603955155e-01*G1_;
  block[3] = -1.178511301977577e-01*G0_ + 1.178511301977577e-01*G1_;
  block[4] = -2.357022603955155e-01*G0_ + 5.892556509887884e-02*G1_;
  block[5] = 4.714045207910309e-01*G0_ + 5.892556509887888e-02*G1_;
  block[6] = -1.414213562373094e+00*G2_0 + 7.071067811865470e-01*G3_1;
  block[7] = -3.333333333333328e-01*G0_ - 3.333333333333330e-01*G1_;
  block[8] = 1.666666666666664e-01*G0_ + 6.666666666666660e-01*G1_;
  block[9] = 5.892556509887889e-02*G0_ + 4.714045207910311e-01*G1_;
  block[10] = 5.892556509887885e-02*G0_ - 2.357022603955155e-01*G1_;
  block[11] = 1.178511301977578e-01*G0_ - 1.178511301977577e-01*G1_;
  block[12] = -2.357022603955155e-01*G0_ - 1.178511301977578e-01*G1_;
  block[13] = 7.071067811865470e-01*G2_0 - 1.414213562373094e+00*G3_1;
  block[14] = -1.178511301977578e-01*G0_ - 2.357022603955155e-01*G1_;
  block[15] = 5.892556509887889e-02*G0_ + 4.714045207910311e-01*G1_;
  block[16] = 2.499999999999995e-01*G0_ + 3.333333333333328e-01*G1_;
  block[17] = -1.249999999999998e-01*G0_ - 1.666666666666664e-01*G1_;
  block[18] = 4.166666666666662e-02*G0_ - 8.333333333333312e-02*G1_;
  block[19] = -8.333333333333320e-02*G0_ - 8.333333333333319e-02*G1_;
  block[20] = 4.999999999999996e-01*G2_0 + 1.499999999999999e+00*G2_1 - 9.999999999999993e-01*G3_1;
  block[21] = -1.178511301977577e-01*G0_ + 1.178511301977577e-01*G1_;
  block[22] = 5.892556509887885e-02*G0_ - 2.357022603955155e-01*G1_;
  block[23] = -1.249999999999998e-01*G0_ - 1.666666666666664e-01*G1_;
  block[24] = 2.499999999999995e-01*G0_ + 8.333333333333316e-02*G1_;
  block[25] = 4.166666666666660e-02*G0_ + 4.166666666666656e-02*G1_;
  block[26] = -8.333333333333316e-02*G0_ + 4.166666666666659e-02*G1_;
  block[27] = -9.999999999999991e-01*G2_0 - 1.499999999999999e+00*G2_1 + 4.999999999999996e-01*G3_1;
  block[28] = -2.357022603955155e-01*G0_ + 5.892556509887881e-02*G1_;
  block[29] = 1.178511301977578e-01*G0_ - 1.178511301977576e-01*G1_;
  block[30] = 4.166666666666662e-02*G0_ - 8.333333333333311e-02*G1_;
  block[31] = 4.166666666666661e-02*G0_ + 4.166666666666655e-02*G1_;
  block[32] = 8.333333333333325e-02*G0_ + 2.499999999999995e-01*G1_;
  block[33] = -1.666666666666664e-01*G0_ - 1.249999999999998e-01*G1_;
  block[34] = 4.999999999999998e-01*G2_0 - 1.499999999999999e+00*G3_0 - 9.999999999999991e-01*G3_1;
  block[35] = 4.714045207910308e-01*G0_ + 5.892556509887887e-02*G1_;
  block[36] = -2.357022603955155e-01*G0_ - 1.178511301977577e-01*G1_;
  block[37] = -8.333333333333322e-02*G0_ - 8.333333333333318e-02*G1_;
  block[38] = -8.333333333333316e-02*G0_ + 4.166666666666659e-02*G1_;
  block[39] = -1.666666666666664e-01*G0_ - 1.249999999999998e-01*G1_;
  block[40] = 3.333333333333327e-01*G0_ + 2.499999999999995e-01*G1_;
  block[41] = -9.999999999999993e-01*G2_0 + 1.499999999999999e+00*G3_0 + 4.999999999999996e-01*G3_1;
  block[42] = 1.414213562373094e+00*G4_0 - 7.071067811865470e-01*G5_1;
  block[43] = -7.071067811865470e-01*G4_0 + 1.414213562373094e+00*G5_1;
  block[44] = -4.999999999999996e-01*G4_0 - 1.499999999999999e+00*G4_1 + 9.999999999999993e-01*G5_1;
  block[45] = 9.999999999999991e-01*G4_0 + 1.499999999999999e+00*G4_1 - 4.999999999999996e-01*G5_1;
  block[46] = -4.999999999999998e-01*G4_0 + 1.499999999999999e+00*G5_0 + 9.999999999999991e-01*G5_1;
  block[47] = 9.999999999999993e-01*G4_0 - 1.499999999999999e+00*G5_0 - 4.999999999999996e-01*G5_1;
  block[48] = 0.000000000000000e+00;
}

// No contribution from the boundary
bool BilinearForm::boundary_contribution() const { return false; }

void BilinearForm::eval(real block[], const AffineMap& map, unsigned int facet) const {}

/// This class contains the form to be evaluated, including
/// contributions from the interior and boundary of the domain.

class LinearForm : public dolfin::LinearForm
{
public:

  class TestElement;

  LinearForm();
  

  bool interior_contribution() const;

  void eval(real block[], const AffineMap& map) const;

  bool boundary_contribution() const;

  void eval(real block[], const AffineMap& map, unsigned int facet) const;

};

class LinearForm::TestElement : public dolfin::FiniteElement
{
public:

  TestElement() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 3;

    subelements = new FiniteElement* [2];
    subelements[0] = new SubElement_0();
    subelements[1] = new SubElement_1();
  }

  ~TestElement()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 7;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 2;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
    int offset = 2*mesh.topology().size(1);
    nodes[6] = offset + cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
    int offset = 2*mesh.topology().size(1);
    vertex_nodes[1] = offset + vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *subelements[i];
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *subelements[i];
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("mixed");
    return s;
  }
  
private:

class SubElement_0 : public dolfin::FiniteElement
{
public:

  SubElement_0() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    tensordims = new unsigned int [1];
    tensordims[0] = 2;

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_0()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 6;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_assert(i < 1);
    return tensordims[i];
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 1;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    static unsigned int edge_reordering_0[2][2] = {{0, 1}, {1, 0}};
    int alignment = cell.alignment(1, 0);
    nodes[0] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][0];
    nodes[1] = 2*cell.entities(1)[0] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 1);
    nodes[2] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][0];
    nodes[3] = 2*cell.entities(1)[1] + edge_reordering_0[alignment][1];
    alignment = cell.alignment(1, 2);
    nodes[4] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][0];
    nodes[5] = 2*cell.entities(1)[2] + edge_reordering_0[alignment][1];
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Brezzi-Douglas-Marini", "triangle", 1, 2);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

class SubElement_1 : public dolfin::FiniteElement
{
public:

  SubElement_1() : dolfin::FiniteElement(), tensordims(0), subelements(0)
  {
    // Element is scalar, don't need to initialize tensordims

    // Element is simple, don't need to initialize subelements
  }

  ~SubElement_1()
  {
    if ( tensordims ) delete [] tensordims;
    if ( subelements )
    {
      for (unsigned int i = 0; i < elementdim(); i++)
        delete subelements[i];
      delete [] subelements;
    }
  }

  inline unsigned int spacedim() const
  {
    return 1;
  }

  inline unsigned int shapedim() const
  {
    return 2;
  }

  inline unsigned int tensordim(unsigned int i) const
  {
    dolfin_error("Element is scalar.");
    return 0;
  }

  inline unsigned int elementdim() const
  {
    return 1;
  }

  inline unsigned int rank() const
  {
    return 0;
  }

  void nodemap(int nodes[], const Cell& cell, const Mesh& mesh) const
  {
    nodes[0] = cell.index();
  }

  void pointmap(Point points[], unsigned int components[], const AffineMap& map) const
  {
    points[0] = map(3.333333333333334e-01, 3.333333333333334e-01);
    components[0] = 0;
  }

  void vertexeval(uint vertex_nodes[], unsigned int vertex, const Mesh& mesh) const
  {
    // FIXME: Temporary fix for Lagrange elements
    vertex_nodes[0] = vertex;
  }

  const FiniteElement& operator[] (unsigned int i) const
  {
    return *this;
  }

  FiniteElement& operator[] (unsigned int i)
  {
    return *this;
  }

  FiniteElementSpec spec() const
  {
    FiniteElementSpec s("Discontinuous Lagrange", "triangle", 0);
    return s;
  }
  
private:

  unsigned int* tensordims;
  FiniteElement** subelements;

};

  unsigned int* tensordims;
  FiniteElement** subelements;

};

LinearForm::LinearForm() : dolfin::LinearForm(0)
{
  // Create finite element for test space
  _test = new TestElement();
}

// Contribution from the interior
bool LinearForm::interior_contribution() const { return true; }

void LinearForm::eval(real block[], const AffineMap& map) const
{
  // Compute geometry tensors
  const real G0_ = map.det;

  // Compute element tensor
  block[0] = 0.000000000000000e+00;
  block[1] = 0.000000000000000e+00;
  block[2] = 0.000000000000000e+00;
  block[3] = 0.000000000000000e+00;
  block[4] = 0.000000000000000e+00;
  block[5] = 0.000000000000000e+00;
  block[6] = 1.499999999999999e+00*G0_;
}

// No contribution from the boundary
bool LinearForm::boundary_contribution() const { return false; }

void LinearForm::eval(real block[], const AffineMap& map, unsigned int facet) const {}

} }

#endif
