// This code conforms with the UFC specification version 1.0
// and was automatically generated by FFC version 0.4.0.

#ifndef __MIXEDMIXEDELEMENT_H
#define __MIXEDMIXEDELEMENT_H

#include <cmath>
#include <stdexcept>
#include <ufc.h>

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_0_0: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_0_0() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_0_0()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Lagrange finite element of degree 3 on a triangle";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 10;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 0;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 1;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    *values = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Extract relevant coefficients
    const double coeff0_0 = coefficients0[dof][0];
    const double coeff0_1 = coefficients0[dof][1];
    const double coeff0_2 = coefficients0[dof][2];
    const double coeff0_3 = coefficients0[dof][3];
    const double coeff0_4 = coefficients0[dof][4];
    const double coeff0_5 = coefficients0[dof][5];
    const double coeff0_6 = coefficients0[dof][6];
    const double coeff0_7 = coefficients0[dof][7];
    const double coeff0_8 = coefficients0[dof][8];
    const double coeff0_9 = coefficients0[dof][9];
    
    // Compute value(s)
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
      values[j] = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Interesting (new) part
    // Tables of derivatives of the polynomial base (transpose)
    const static double dmats0[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
    {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
    {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
    {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
    const static double dmats1[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
    {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
    {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
    {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
    {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
    {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
    {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
    // Compute reference derivatives
    // Declare pointer to array of derivatives on FIAT element
    double *derivatives = new double [num_derivatives];
    
    // Declare coefficients
    double coeff0_0 = 0;
    double coeff0_1 = 0;
    double coeff0_2 = 0;
    double coeff0_3 = 0;
    double coeff0_4 = 0;
    double coeff0_5 = 0;
    double coeff0_6 = 0;
    double coeff0_7 = 0;
    double coeff0_8 = 0;
    double coeff0_9 = 0;
    
    // Declare new coefficients
    double new_coeff0_0 = 0;
    double new_coeff0_1 = 0;
    double new_coeff0_2 = 0;
    double new_coeff0_3 = 0;
    double new_coeff0_4 = 0;
    double new_coeff0_5 = 0;
    double new_coeff0_6 = 0;
    double new_coeff0_7 = 0;
    double new_coeff0_8 = 0;
    double new_coeff0_9 = 0;
    
    // Loop possible derivatives
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
    {
      // Get values from coefficients array
      new_coeff0_0 = coefficients0[dof][0];
      new_coeff0_1 = coefficients0[dof][1];
      new_coeff0_2 = coefficients0[dof][2];
      new_coeff0_3 = coefficients0[dof][3];
      new_coeff0_4 = coefficients0[dof][4];
      new_coeff0_5 = coefficients0[dof][5];
      new_coeff0_6 = coefficients0[dof][6];
      new_coeff0_7 = coefficients0[dof][7];
      new_coeff0_8 = coefficients0[dof][8];
      new_coeff0_9 = coefficients0[dof][9];
    
      // Loop derivative order
      for (unsigned int j = 0; j < n; j++)
      {
        // Update old coefficients
        coeff0_0 = new_coeff0_0;
        coeff0_1 = new_coeff0_1;
        coeff0_2 = new_coeff0_2;
        coeff0_3 = new_coeff0_3;
        coeff0_4 = new_coeff0_4;
        coeff0_5 = new_coeff0_5;
        coeff0_6 = new_coeff0_6;
        coeff0_7 = new_coeff0_7;
        coeff0_8 = new_coeff0_8;
        coeff0_9 = new_coeff0_9;
    
        if(combinations[deriv_num][j] == 0)
        {
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
          new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
          new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
          new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
          new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
          new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
          new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
        }
        if(combinations[deriv_num][j] == 1)
        {
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
          new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
          new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
          new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
          new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
          new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
          new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
        }
    
      }
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
    }
    
    // Transform derivatives back to physical element
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        values[row] += transform[row][col]*derivatives[col];
      }
    }
    // Delete pointer to array of derivatives on FIAT element
    delete [] derivatives;
    
    // Delete pointer to array of combinations of derivatives
    delete [] combinations;
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[1];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[10][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 1;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    return new MixedMixedElement_finite_element_0_0_0();
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_0_1: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_0_1() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_0_1()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Lagrange finite element of degree 3 on a triangle";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 10;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 0;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 1;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    *values = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Extract relevant coefficients
    const double coeff0_0 = coefficients0[dof][0];
    const double coeff0_1 = coefficients0[dof][1];
    const double coeff0_2 = coefficients0[dof][2];
    const double coeff0_3 = coefficients0[dof][3];
    const double coeff0_4 = coefficients0[dof][4];
    const double coeff0_5 = coefficients0[dof][5];
    const double coeff0_6 = coefficients0[dof][6];
    const double coeff0_7 = coefficients0[dof][7];
    const double coeff0_8 = coefficients0[dof][8];
    const double coeff0_9 = coefficients0[dof][9];
    
    // Compute value(s)
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
      values[j] = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Interesting (new) part
    // Tables of derivatives of the polynomial base (transpose)
    const static double dmats0[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
    {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
    {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
    {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
    const static double dmats1[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
    {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
    {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
    {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
    {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
    {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
    {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
    // Compute reference derivatives
    // Declare pointer to array of derivatives on FIAT element
    double *derivatives = new double [num_derivatives];
    
    // Declare coefficients
    double coeff0_0 = 0;
    double coeff0_1 = 0;
    double coeff0_2 = 0;
    double coeff0_3 = 0;
    double coeff0_4 = 0;
    double coeff0_5 = 0;
    double coeff0_6 = 0;
    double coeff0_7 = 0;
    double coeff0_8 = 0;
    double coeff0_9 = 0;
    
    // Declare new coefficients
    double new_coeff0_0 = 0;
    double new_coeff0_1 = 0;
    double new_coeff0_2 = 0;
    double new_coeff0_3 = 0;
    double new_coeff0_4 = 0;
    double new_coeff0_5 = 0;
    double new_coeff0_6 = 0;
    double new_coeff0_7 = 0;
    double new_coeff0_8 = 0;
    double new_coeff0_9 = 0;
    
    // Loop possible derivatives
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
    {
      // Get values from coefficients array
      new_coeff0_0 = coefficients0[dof][0];
      new_coeff0_1 = coefficients0[dof][1];
      new_coeff0_2 = coefficients0[dof][2];
      new_coeff0_3 = coefficients0[dof][3];
      new_coeff0_4 = coefficients0[dof][4];
      new_coeff0_5 = coefficients0[dof][5];
      new_coeff0_6 = coefficients0[dof][6];
      new_coeff0_7 = coefficients0[dof][7];
      new_coeff0_8 = coefficients0[dof][8];
      new_coeff0_9 = coefficients0[dof][9];
    
      // Loop derivative order
      for (unsigned int j = 0; j < n; j++)
      {
        // Update old coefficients
        coeff0_0 = new_coeff0_0;
        coeff0_1 = new_coeff0_1;
        coeff0_2 = new_coeff0_2;
        coeff0_3 = new_coeff0_3;
        coeff0_4 = new_coeff0_4;
        coeff0_5 = new_coeff0_5;
        coeff0_6 = new_coeff0_6;
        coeff0_7 = new_coeff0_7;
        coeff0_8 = new_coeff0_8;
        coeff0_9 = new_coeff0_9;
    
        if(combinations[deriv_num][j] == 0)
        {
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
          new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
          new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
          new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
          new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
          new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
          new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
        }
        if(combinations[deriv_num][j] == 1)
        {
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
          new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
          new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
          new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
          new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
          new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
          new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
        }
    
      }
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
    }
    
    // Transform derivatives back to physical element
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        values[row] += transform[row][col]*derivatives[col];
      }
    }
    // Delete pointer to array of derivatives on FIAT element
    delete [] derivatives;
    
    // Delete pointer to array of combinations of derivatives
    delete [] combinations;
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[1];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[10][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 1;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    return new MixedMixedElement_finite_element_0_0_1();
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_0: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_0() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_0()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 20;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 1;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 2;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    values[0] = 0;
    values[1] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 2*num_derivatives; j++)
      values[j] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[2];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[20][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}, {0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
    // Evaluate at vertices and use affine mapping
    vertex_values[3] = dof_values[10];
    vertex_values[4] = dof_values[11];
    vertex_values[5] = dof_values[12];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 2;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_finite_element_0_0_0();
      break;
    case 1:
      return new MixedMixedElement_finite_element_0_0_1();
      break;
    }
    return 0;
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_1_0: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_1_0() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_1_0()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Lagrange finite element of degree 3 on a triangle";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 10;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 0;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 1;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    *values = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Extract relevant coefficients
    const double coeff0_0 = coefficients0[dof][0];
    const double coeff0_1 = coefficients0[dof][1];
    const double coeff0_2 = coefficients0[dof][2];
    const double coeff0_3 = coefficients0[dof][3];
    const double coeff0_4 = coefficients0[dof][4];
    const double coeff0_5 = coefficients0[dof][5];
    const double coeff0_6 = coefficients0[dof][6];
    const double coeff0_7 = coefficients0[dof][7];
    const double coeff0_8 = coefficients0[dof][8];
    const double coeff0_9 = coefficients0[dof][9];
    
    // Compute value(s)
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
      values[j] = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Interesting (new) part
    // Tables of derivatives of the polynomial base (transpose)
    const static double dmats0[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
    {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
    {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
    {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
    const static double dmats1[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
    {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
    {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
    {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
    {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
    {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
    {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
    // Compute reference derivatives
    // Declare pointer to array of derivatives on FIAT element
    double *derivatives = new double [num_derivatives];
    
    // Declare coefficients
    double coeff0_0 = 0;
    double coeff0_1 = 0;
    double coeff0_2 = 0;
    double coeff0_3 = 0;
    double coeff0_4 = 0;
    double coeff0_5 = 0;
    double coeff0_6 = 0;
    double coeff0_7 = 0;
    double coeff0_8 = 0;
    double coeff0_9 = 0;
    
    // Declare new coefficients
    double new_coeff0_0 = 0;
    double new_coeff0_1 = 0;
    double new_coeff0_2 = 0;
    double new_coeff0_3 = 0;
    double new_coeff0_4 = 0;
    double new_coeff0_5 = 0;
    double new_coeff0_6 = 0;
    double new_coeff0_7 = 0;
    double new_coeff0_8 = 0;
    double new_coeff0_9 = 0;
    
    // Loop possible derivatives
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
    {
      // Get values from coefficients array
      new_coeff0_0 = coefficients0[dof][0];
      new_coeff0_1 = coefficients0[dof][1];
      new_coeff0_2 = coefficients0[dof][2];
      new_coeff0_3 = coefficients0[dof][3];
      new_coeff0_4 = coefficients0[dof][4];
      new_coeff0_5 = coefficients0[dof][5];
      new_coeff0_6 = coefficients0[dof][6];
      new_coeff0_7 = coefficients0[dof][7];
      new_coeff0_8 = coefficients0[dof][8];
      new_coeff0_9 = coefficients0[dof][9];
    
      // Loop derivative order
      for (unsigned int j = 0; j < n; j++)
      {
        // Update old coefficients
        coeff0_0 = new_coeff0_0;
        coeff0_1 = new_coeff0_1;
        coeff0_2 = new_coeff0_2;
        coeff0_3 = new_coeff0_3;
        coeff0_4 = new_coeff0_4;
        coeff0_5 = new_coeff0_5;
        coeff0_6 = new_coeff0_6;
        coeff0_7 = new_coeff0_7;
        coeff0_8 = new_coeff0_8;
        coeff0_9 = new_coeff0_9;
    
        if(combinations[deriv_num][j] == 0)
        {
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
          new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
          new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
          new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
          new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
          new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
          new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
        }
        if(combinations[deriv_num][j] == 1)
        {
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
          new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
          new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
          new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
          new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
          new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
          new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
        }
    
      }
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
    }
    
    // Transform derivatives back to physical element
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        values[row] += transform[row][col]*derivatives[col];
      }
    }
    // Delete pointer to array of derivatives on FIAT element
    delete [] derivatives;
    
    // Delete pointer to array of combinations of derivatives
    delete [] combinations;
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[1];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[10][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 1;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    return new MixedMixedElement_finite_element_0_1_0();
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_1_1: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_1_1() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_1_1()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Lagrange finite element of degree 3 on a triangle";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 10;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 0;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 1;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    *values = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Extract relevant coefficients
    const double coeff0_0 = coefficients0[dof][0];
    const double coeff0_1 = coefficients0[dof][1];
    const double coeff0_2 = coefficients0[dof][2];
    const double coeff0_3 = coefficients0[dof][3];
    const double coeff0_4 = coefficients0[dof][4];
    const double coeff0_5 = coefficients0[dof][5];
    const double coeff0_6 = coefficients0[dof][6];
    const double coeff0_7 = coefficients0[dof][7];
    const double coeff0_8 = coefficients0[dof][8];
    const double coeff0_9 = coefficients0[dof][9];
    
    // Compute value(s)
    *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 1*num_derivatives; j++)
      values[j] = 0;
    
    // Map degree of freedom to element degree of freedom
    const unsigned int dof = i;
    
    // Generate scalings
    const double scalings_y_0 = 1;
    const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
    const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
    const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
    // Compute psitilde_a
    const double psitilde_a_0 = 1;
    const double psitilde_a_1 = x;
    const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
    const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
    // Compute psitilde_bs
    const double psitilde_bs_0_0 = 1;
    const double psitilde_bs_0_1 = 1.5*y + 0.5;
    const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
    const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
    const double psitilde_bs_1_0 = 1;
    const double psitilde_bs_1_1 = 2.5*y + 1.5;
    const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
    const double psitilde_bs_2_0 = 1;
    const double psitilde_bs_2_1 = 3.5*y + 2.5;
    const double psitilde_bs_3_0 = 1;
    
    // Compute basisvalues
    const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
    const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
    const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
    const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
    const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
    const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
    const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
    const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
    const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
    const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
    // Table(s) of coefficients
    const static double coefficients0[10][10] = \
    {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
    {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
    {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
    {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
    {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
    {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
    {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
    {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
    // Interesting (new) part
    // Tables of derivatives of the polynomial base (transpose)
    const static double dmats0[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
    {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
    {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
    {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
    const static double dmats1[10][10] = \
    {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
    {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
    {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
    {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
    {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
    {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
    {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
    {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
    // Compute reference derivatives
    // Declare pointer to array of derivatives on FIAT element
    double *derivatives = new double [num_derivatives];
    
    // Declare coefficients
    double coeff0_0 = 0;
    double coeff0_1 = 0;
    double coeff0_2 = 0;
    double coeff0_3 = 0;
    double coeff0_4 = 0;
    double coeff0_5 = 0;
    double coeff0_6 = 0;
    double coeff0_7 = 0;
    double coeff0_8 = 0;
    double coeff0_9 = 0;
    
    // Declare new coefficients
    double new_coeff0_0 = 0;
    double new_coeff0_1 = 0;
    double new_coeff0_2 = 0;
    double new_coeff0_3 = 0;
    double new_coeff0_4 = 0;
    double new_coeff0_5 = 0;
    double new_coeff0_6 = 0;
    double new_coeff0_7 = 0;
    double new_coeff0_8 = 0;
    double new_coeff0_9 = 0;
    
    // Loop possible derivatives
    for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
    {
      // Get values from coefficients array
      new_coeff0_0 = coefficients0[dof][0];
      new_coeff0_1 = coefficients0[dof][1];
      new_coeff0_2 = coefficients0[dof][2];
      new_coeff0_3 = coefficients0[dof][3];
      new_coeff0_4 = coefficients0[dof][4];
      new_coeff0_5 = coefficients0[dof][5];
      new_coeff0_6 = coefficients0[dof][6];
      new_coeff0_7 = coefficients0[dof][7];
      new_coeff0_8 = coefficients0[dof][8];
      new_coeff0_9 = coefficients0[dof][9];
    
      // Loop derivative order
      for (unsigned int j = 0; j < n; j++)
      {
        // Update old coefficients
        coeff0_0 = new_coeff0_0;
        coeff0_1 = new_coeff0_1;
        coeff0_2 = new_coeff0_2;
        coeff0_3 = new_coeff0_3;
        coeff0_4 = new_coeff0_4;
        coeff0_5 = new_coeff0_5;
        coeff0_6 = new_coeff0_6;
        coeff0_7 = new_coeff0_7;
        coeff0_8 = new_coeff0_8;
        coeff0_9 = new_coeff0_9;
    
        if(combinations[deriv_num][j] == 0)
        {
          new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
          new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
          new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
          new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
          new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
          new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
          new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
          new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
          new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
          new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
        }
        if(combinations[deriv_num][j] == 1)
        {
          new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
          new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
          new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
          new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
          new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
          new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
          new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
          new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
          new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
          new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
        }
    
      }
      // Compute derivatives on reference element as dot product of coefficients and basisvalues
      derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
    }
    
    // Transform derivatives back to physical element
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        values[row] += transform[row][col]*derivatives[col];
      }
    }
    // Delete pointer to array of derivatives on FIAT element
    delete [] derivatives;
    
    // Delete pointer to array of combinations of derivatives
    delete [] combinations;
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[1];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[10][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 1;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    return new MixedMixedElement_finite_element_0_1_1();
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0_1: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0_1() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0_1()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 20;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 1;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 2;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    values[0] = 0;
    values[1] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 2*num_derivatives; j++)
      values[j] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[2];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[20][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}, {0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[20] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
    // Evaluate at vertices and use affine mapping
    vertex_values[3] = dof_values[10];
    vertex_values[4] = dof_values[11];
    vertex_values[5] = dof_values[12];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 2;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_finite_element_0_1_0();
      break;
    case 1:
      return new MixedMixedElement_finite_element_0_1_1();
      break;
    }
    return 0;
  }

};

/// This class defines the interface for a finite element.

class MixedMixedElement_finite_element_0: public ufc::finite_element
{
public:

  /// Constructor
  MixedMixedElement_finite_element_0() : ufc::finite_element()
  {
    // Do nothing
  }

  /// Destructor
  virtual ~MixedMixedElement_finite_element_0()
  {
    // Do nothing
  }

  /// Return a string identifying the finite element
  virtual const char* signature() const
  {
    return "Mixed finite element: [Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle], Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]]";
  }

  /// Return the cell shape
  virtual ufc::shape cell_shape() const
  {
    return ufc::triangle;
  }

  /// Return the dimension of the finite element function space
  virtual unsigned int space_dimension() const
  {
    return 40;
  }

  /// Return the rank of the value space
  virtual unsigned int value_rank() const
  {
    return 1;
  }

  /// Return the dimension of the value space for axis i
  virtual unsigned int value_dimension(unsigned int i) const
  {
    return 4;
  }

  /// Evaluate basis function i at given point in cell
  virtual void evaluate_basis(unsigned int i,
                              double* values,
                              const double* coordinates,
                              const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Reset values
    values[0] = 0;
    values[1] = 0;
    values[2] = 0;
    values[3] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
    if (20 <= i and i <= 29)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 20;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[2] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
    if (30 <= i and i <= 39)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 30;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Extract relevant coefficients
      const double coeff0_0 =   coefficients0[dof][0];
      const double coeff0_1 =   coefficients0[dof][1];
      const double coeff0_2 =   coefficients0[dof][2];
      const double coeff0_3 =   coefficients0[dof][3];
      const double coeff0_4 =   coefficients0[dof][4];
      const double coeff0_5 =   coefficients0[dof][5];
      const double coeff0_6 =   coefficients0[dof][6];
      const double coeff0_7 =   coefficients0[dof][7];
      const double coeff0_8 =   coefficients0[dof][8];
      const double coeff0_9 =   coefficients0[dof][9];
    
      // Compute value(s)
      values[3] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5 + coeff0_6*basisvalue6 + coeff0_7*basisvalue7 + coeff0_8*basisvalue8 + coeff0_9*basisvalue9;
    }
    
  }

  /// Evaluate order n derivatives of basis function i at given point in cell
  virtual void evaluate_basis_derivatives(unsigned int i,
                                          unsigned int n,
                                          double* values,
                                          const double* coordinates,
                                          const ufc::cell& c) const
  {
    // Extract vertex coordinates
    const double * const * element_coordinates = c.coordinates;
    
    // Compute Jacobian of affine map from reference cell
    const double J_00 = element_coordinates[1][0] - element_coordinates[0][0];
    const double J_01 = element_coordinates[2][0] - element_coordinates[0][0];
    const double J_10 = element_coordinates[1][1] - element_coordinates[0][1];
    const double J_11 = element_coordinates[2][1] - element_coordinates[0][1];
      
    // Compute determinant of Jacobian
    const double detJ = J_00*J_11 - J_01*J_10;
    
    // Compute constants
    const double C0 = element_coordinates[1][0] + element_coordinates[2][0];
    const double C1 = element_coordinates[1][1] + element_coordinates[2][1];
    
    // Get coordinates and map to the reference (FIAT) element
    double x = (J_01*C1 - J_11*C0 + 2.0*J_11*coordinates[0] - 2.0*J_01*coordinates[1]) / detJ;
    double y = (J_10*C0 - J_00*C1 - 2.0*J_10*coordinates[0] + 2.0*J_00*coordinates[1]) / detJ;
    
    // Map coordinates to the reference square
    if (std::abs(y - 1.0) < 1e-09)
      x = -1.0;
    else
      x = 2.0 * (1.0 + x)/(1.0 - y) - 1.0;
    
    // Compute number of derivatives
    unsigned int num_derivatives = 1;
    
    for (unsigned int j = 0; j < n; j++)
      num_derivatives *= 2;
    
    
    // Declare pointer to two dimensional array that holds combinations of derivatives and initialise
    unsigned int **combinations = new unsigned int *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      combinations[j] = new unsigned int [n];
      for (unsigned int k = 0; k < n; k++)
        combinations[j][k] = 0;
    }
        
    // Generate combinations of derivatives
    for (unsigned int row = 1; row < num_derivatives; row++)
    {
      for (unsigned int num = 0; num < row; num++)
      {
        for (unsigned int col = n-1; col+1 > 0; col--)
        {
          if (combinations[row][col] + 1 > 1)
            combinations[row][col] = 0;
          else
          {
            combinations[row][col] += 1;
            break;
          }
        }
      }
    }
    
    // Compute inverse of Jacobian, components are scaled because of difference in FFC/FIAT reference elements
    const double Jinv[2][2] =  {{2*J_11 / detJ, -2*J_01 / detJ}, {-2*J_10 / detJ, 2*J_00 / detJ}};
    
    // Declare transformation matrix
    // Declare pointer to two dimensional array and initialise
    double **transform = new double *[num_derivatives];
        
    for (unsigned int j = 0; j < num_derivatives; j++)
    {
      transform[j] = new double [num_derivatives];
      for (unsigned int k = 0; k < num_derivatives; k++)
        transform[j][k] = 1;
    }
    
    // Construct transformation matrix
    for (unsigned int row = 0; row < num_derivatives; row++)
    {
      for (unsigned int col = 0; col < num_derivatives; col++)
      {
        for (unsigned int k = 0; k < n; k++)
          transform[row][col] *= Jinv[combinations[col][k]][combinations[row][k]];
      }
    }
    
    // Reset values
    for (unsigned int j = 0; j < 4*num_derivatives; j++)
      values[j] = 0;
    
    if (0 <= i and i <= 9)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
    if (10 <= i and i <= 19)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 10;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[num_derivatives + row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
    if (20 <= i and i <= 29)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 20;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[2*num_derivatives + row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
    if (30 <= i and i <= 39)
    {
      // Map degree of freedom to element degree of freedom
      const unsigned int dof = i - 30;
    
      // Generate scalings
      const double scalings_y_0 = 1;
      const double scalings_y_1 = scalings_y_0*(0.5 - 0.5*y);
      const double scalings_y_2 = scalings_y_1*(0.5 - 0.5*y);
      const double scalings_y_3 = scalings_y_2*(0.5 - 0.5*y);
    
      // Compute psitilde_a
      const double psitilde_a_0 = 1;
      const double psitilde_a_1 = x;
      const double psitilde_a_2 = 1.5*x*psitilde_a_1 - 0.5*psitilde_a_0;
      const double psitilde_a_3 = 1.666666667*x*psitilde_a_2 - 0.6666666667*psitilde_a_1;
    
      // Compute psitilde_bs
      const double psitilde_bs_0_0 = 1;
      const double psitilde_bs_0_1 = 1.5*y + 0.5;
      const double psitilde_bs_0_2 = 0.1111111111*psitilde_bs_0_1 + 1.666666667*y*psitilde_bs_0_1 - 0.5555555556*psitilde_bs_0_0;
      const double psitilde_bs_0_3 = 0.05*psitilde_bs_0_2 + 1.75*y*psitilde_bs_0_2 - 0.7*psitilde_bs_0_1;
      const double psitilde_bs_1_0 = 1;
      const double psitilde_bs_1_1 = 2.5*y + 1.5;
      const double psitilde_bs_1_2 = 0.54*psitilde_bs_1_1 + 2.1*y*psitilde_bs_1_1 - 0.56*psitilde_bs_1_0;
      const double psitilde_bs_2_0 = 1;
      const double psitilde_bs_2_1 = 3.5*y + 2.5;
      const double psitilde_bs_3_0 = 1;
    
      // Compute basisvalues
      const double basisvalue0 = 0.7071067812*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
      const double basisvalue1 = 1.732050808*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
      const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
      const double basisvalue3 = 2.738612788*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
      const double basisvalue4 = 2.121320344*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
      const double basisvalue5 = 1.224744871*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
      const double basisvalue6 = 3.741657387*psitilde_a_3*scalings_y_3*psitilde_bs_3_0;
      const double basisvalue7 = 3.16227766*psitilde_a_2*scalings_y_2*psitilde_bs_2_1;
      const double basisvalue8 = 2.449489743*psitilde_a_1*scalings_y_1*psitilde_bs_1_2;
      const double basisvalue9 = 1.414213562*psitilde_a_0*scalings_y_0*psitilde_bs_0_3;
    
      // Table(s) of coefficients
      const static double coefficients0[10][10] =   \
      {{0.04714045208, -0.02886751346, -0.01666666667, 0.07824607964, 0.06060915267, 0.03499271061, -0.06013377943, -0.05082231954, -0.03936679944, -0.02272843225},
      {0.04714045208, 0.02886751346, -0.01666666667, 0.07824607964, -0.06060915267, 0.03499271061, 0.06013377943, -0.05082231954, 0.03936679944, -0.02272843225},
      {0.04714045208, 0, 0.03333333333, 0, 0, 0.1049781318, 0, 0, 0, 0.09091372901},
      {0.1060660172, 0.2598076211, -0.15, 0.1173691195, 0.06060915267, -0.07873359888, 0, 0.1016446391, -0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, 0.1515228817, 0.02624453296, 0, 0, 0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, 0.1173691195, -0.06060915267, -0.07873359888, 0, 0.1016446391, 0.1312226648, 0.09091372901},
      {0.1060660172, 0, 0.3, 0, -0.1515228817, 0.02624453296, 0, 0, -0.1312226648, -0.1363705935},
      {0.1060660172, -0.2598076211, -0.15, -0.07824607964, 0.09091372901, 0.09622995418, 0.1804013383, 0.05082231954, -0.01312226648, -0.02272843225},
      {0.1060660172, 0.2598076211, -0.15, -0.07824607964, -0.09091372901, 0.09622995418, -0.1804013383, 0.05082231954, 0.01312226648, -0.02272843225},
      {0.6363961031, 0, 0, -0.2347382389, 0, -0.2624453296, 0, -0.2032892782, 0, 0.09091372901}};
    
      // Interesting (new) part
      // Tables of derivatives of the polynomial base (transpose)
      const static double dmats0[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.449489743, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {0, 4.74341649, 0, 0, 0, 0, 0, 0, 0, 0},
      {2, 0, 3.535533906, 0, 0, 0, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.645751311, 0, -1.496662955, 6.831300511, 0, 0.3055050463, 0, 0, 0, 0},
      {0, 2.19089023, 0, 0, 6.260990337, 0, 0, 0, 0, 0},
      {1.732050808, 0, 3.919183588, 0, 0, 4.2, 0, 0, 0, 0},
      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
    
      const static double dmats1[10][10] =   \
      {{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.224744871, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {2.121320344, 0, 0, 0, 0, 0, 0, 0, 0, 0},
      {1.290994449, 2.371708245, -0.4564354646, 0, 0, 0, 0, 0, 0, 0},
      {1, 3.061862178, 1.767766953, 0, 0, 0, 0, 0, 0, 0},
      {-1.154700538, 0, 4.082482905, 0, 0, 0, 0, 0, 0, 0},
      {1.322875656, 2.592296279, -0.7483314774, 3.415650255, -0.5291502622, 0.1527525232, 0, 0, 0, 0},
      {1.118033989, 1.095445115, 1.264911064, 4.041451884, 3.130495168, -0.9036961141, 0, 0, 0, 0},
      {0.8660254038, -2.545584412, 1.959591794, 0, 4.849742261, 2.1, 0, 0, 0, 0},
      {2.5, 0, -1.414213562, 0, 0, 6.062177826, 0, 0, 0, 0}};
    
      // Compute reference derivatives
      // Declare pointer to array of derivatives on FIAT element
      double *derivatives = new double [num_derivatives];
    
      // Declare coefficients
      double coeff0_0 = 0;
      double coeff0_1 = 0;
      double coeff0_2 = 0;
      double coeff0_3 = 0;
      double coeff0_4 = 0;
      double coeff0_5 = 0;
      double coeff0_6 = 0;
      double coeff0_7 = 0;
      double coeff0_8 = 0;
      double coeff0_9 = 0;
    
      // Declare new coefficients
      double new_coeff0_0 = 0;
      double new_coeff0_1 = 0;
      double new_coeff0_2 = 0;
      double new_coeff0_3 = 0;
      double new_coeff0_4 = 0;
      double new_coeff0_5 = 0;
      double new_coeff0_6 = 0;
      double new_coeff0_7 = 0;
      double new_coeff0_8 = 0;
      double new_coeff0_9 = 0;
    
      // Loop possible derivatives
      for (unsigned int deriv_num = 0; deriv_num < num_derivatives; deriv_num++)
      {
        // Get values from coefficients array
        new_coeff0_0 = coefficients0[dof][0];
        new_coeff0_1 = coefficients0[dof][1];
        new_coeff0_2 = coefficients0[dof][2];
        new_coeff0_3 = coefficients0[dof][3];
        new_coeff0_4 = coefficients0[dof][4];
        new_coeff0_5 = coefficients0[dof][5];
        new_coeff0_6 = coefficients0[dof][6];
        new_coeff0_7 = coefficients0[dof][7];
        new_coeff0_8 = coefficients0[dof][8];
        new_coeff0_9 = coefficients0[dof][9];
    
        // Loop derivative order
        for (unsigned int j = 0; j < n; j++)
        {
          // Update old coefficients
          coeff0_0 = new_coeff0_0;
          coeff0_1 = new_coeff0_1;
          coeff0_2 = new_coeff0_2;
          coeff0_3 = new_coeff0_3;
          coeff0_4 = new_coeff0_4;
          coeff0_5 = new_coeff0_5;
          coeff0_6 = new_coeff0_6;
          coeff0_7 = new_coeff0_7;
          coeff0_8 = new_coeff0_8;
          coeff0_9 = new_coeff0_9;
    
          if(combinations[deriv_num][j] == 0)
          {
            new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0] + coeff0_3*dmats0[3][0] + coeff0_4*dmats0[4][0] + coeff0_5*dmats0[5][0] + coeff0_6*dmats0[6][0] + coeff0_7*dmats0[7][0] + coeff0_8*dmats0[8][0] + coeff0_9*dmats0[9][0];
            new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1] + coeff0_3*dmats0[3][1] + coeff0_4*dmats0[4][1] + coeff0_5*dmats0[5][1] + coeff0_6*dmats0[6][1] + coeff0_7*dmats0[7][1] + coeff0_8*dmats0[8][1] + coeff0_9*dmats0[9][1];
            new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2] + coeff0_3*dmats0[3][2] + coeff0_4*dmats0[4][2] + coeff0_5*dmats0[5][2] + coeff0_6*dmats0[6][2] + coeff0_7*dmats0[7][2] + coeff0_8*dmats0[8][2] + coeff0_9*dmats0[9][2];
            new_coeff0_3 = coeff0_0*dmats0[0][3] + coeff0_1*dmats0[1][3] + coeff0_2*dmats0[2][3] + coeff0_3*dmats0[3][3] + coeff0_4*dmats0[4][3] + coeff0_5*dmats0[5][3] + coeff0_6*dmats0[6][3] + coeff0_7*dmats0[7][3] + coeff0_8*dmats0[8][3] + coeff0_9*dmats0[9][3];
            new_coeff0_4 = coeff0_0*dmats0[0][4] + coeff0_1*dmats0[1][4] + coeff0_2*dmats0[2][4] + coeff0_3*dmats0[3][4] + coeff0_4*dmats0[4][4] + coeff0_5*dmats0[5][4] + coeff0_6*dmats0[6][4] + coeff0_7*dmats0[7][4] + coeff0_8*dmats0[8][4] + coeff0_9*dmats0[9][4];
            new_coeff0_5 = coeff0_0*dmats0[0][5] + coeff0_1*dmats0[1][5] + coeff0_2*dmats0[2][5] + coeff0_3*dmats0[3][5] + coeff0_4*dmats0[4][5] + coeff0_5*dmats0[5][5] + coeff0_6*dmats0[6][5] + coeff0_7*dmats0[7][5] + coeff0_8*dmats0[8][5] + coeff0_9*dmats0[9][5];
            new_coeff0_6 = coeff0_0*dmats0[0][6] + coeff0_1*dmats0[1][6] + coeff0_2*dmats0[2][6] + coeff0_3*dmats0[3][6] + coeff0_4*dmats0[4][6] + coeff0_5*dmats0[5][6] + coeff0_6*dmats0[6][6] + coeff0_7*dmats0[7][6] + coeff0_8*dmats0[8][6] + coeff0_9*dmats0[9][6];
            new_coeff0_7 = coeff0_0*dmats0[0][7] + coeff0_1*dmats0[1][7] + coeff0_2*dmats0[2][7] + coeff0_3*dmats0[3][7] + coeff0_4*dmats0[4][7] + coeff0_5*dmats0[5][7] + coeff0_6*dmats0[6][7] + coeff0_7*dmats0[7][7] + coeff0_8*dmats0[8][7] + coeff0_9*dmats0[9][7];
            new_coeff0_8 = coeff0_0*dmats0[0][8] + coeff0_1*dmats0[1][8] + coeff0_2*dmats0[2][8] + coeff0_3*dmats0[3][8] + coeff0_4*dmats0[4][8] + coeff0_5*dmats0[5][8] + coeff0_6*dmats0[6][8] + coeff0_7*dmats0[7][8] + coeff0_8*dmats0[8][8] + coeff0_9*dmats0[9][8];
            new_coeff0_9 = coeff0_0*dmats0[0][9] + coeff0_1*dmats0[1][9] + coeff0_2*dmats0[2][9] + coeff0_3*dmats0[3][9] + coeff0_4*dmats0[4][9] + coeff0_5*dmats0[5][9] + coeff0_6*dmats0[6][9] + coeff0_7*dmats0[7][9] + coeff0_8*dmats0[8][9] + coeff0_9*dmats0[9][9];
          }
          if(combinations[deriv_num][j] == 1)
          {
            new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0] + coeff0_3*dmats1[3][0] + coeff0_4*dmats1[4][0] + coeff0_5*dmats1[5][0] + coeff0_6*dmats1[6][0] + coeff0_7*dmats1[7][0] + coeff0_8*dmats1[8][0] + coeff0_9*dmats1[9][0];
            new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1] + coeff0_3*dmats1[3][1] + coeff0_4*dmats1[4][1] + coeff0_5*dmats1[5][1] + coeff0_6*dmats1[6][1] + coeff0_7*dmats1[7][1] + coeff0_8*dmats1[8][1] + coeff0_9*dmats1[9][1];
            new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2] + coeff0_3*dmats1[3][2] + coeff0_4*dmats1[4][2] + coeff0_5*dmats1[5][2] + coeff0_6*dmats1[6][2] + coeff0_7*dmats1[7][2] + coeff0_8*dmats1[8][2] + coeff0_9*dmats1[9][2];
            new_coeff0_3 = coeff0_0*dmats1[0][3] + coeff0_1*dmats1[1][3] + coeff0_2*dmats1[2][3] + coeff0_3*dmats1[3][3] + coeff0_4*dmats1[4][3] + coeff0_5*dmats1[5][3] + coeff0_6*dmats1[6][3] + coeff0_7*dmats1[7][3] + coeff0_8*dmats1[8][3] + coeff0_9*dmats1[9][3];
            new_coeff0_4 = coeff0_0*dmats1[0][4] + coeff0_1*dmats1[1][4] + coeff0_2*dmats1[2][4] + coeff0_3*dmats1[3][4] + coeff0_4*dmats1[4][4] + coeff0_5*dmats1[5][4] + coeff0_6*dmats1[6][4] + coeff0_7*dmats1[7][4] + coeff0_8*dmats1[8][4] + coeff0_9*dmats1[9][4];
            new_coeff0_5 = coeff0_0*dmats1[0][5] + coeff0_1*dmats1[1][5] + coeff0_2*dmats1[2][5] + coeff0_3*dmats1[3][5] + coeff0_4*dmats1[4][5] + coeff0_5*dmats1[5][5] + coeff0_6*dmats1[6][5] + coeff0_7*dmats1[7][5] + coeff0_8*dmats1[8][5] + coeff0_9*dmats1[9][5];
            new_coeff0_6 = coeff0_0*dmats1[0][6] + coeff0_1*dmats1[1][6] + coeff0_2*dmats1[2][6] + coeff0_3*dmats1[3][6] + coeff0_4*dmats1[4][6] + coeff0_5*dmats1[5][6] + coeff0_6*dmats1[6][6] + coeff0_7*dmats1[7][6] + coeff0_8*dmats1[8][6] + coeff0_9*dmats1[9][6];
            new_coeff0_7 = coeff0_0*dmats1[0][7] + coeff0_1*dmats1[1][7] + coeff0_2*dmats1[2][7] + coeff0_3*dmats1[3][7] + coeff0_4*dmats1[4][7] + coeff0_5*dmats1[5][7] + coeff0_6*dmats1[6][7] + coeff0_7*dmats1[7][7] + coeff0_8*dmats1[8][7] + coeff0_9*dmats1[9][7];
            new_coeff0_8 = coeff0_0*dmats1[0][8] + coeff0_1*dmats1[1][8] + coeff0_2*dmats1[2][8] + coeff0_3*dmats1[3][8] + coeff0_4*dmats1[4][8] + coeff0_5*dmats1[5][8] + coeff0_6*dmats1[6][8] + coeff0_7*dmats1[7][8] + coeff0_8*dmats1[8][8] + coeff0_9*dmats1[9][8];
            new_coeff0_9 = coeff0_0*dmats1[0][9] + coeff0_1*dmats1[1][9] + coeff0_2*dmats1[2][9] + coeff0_3*dmats1[3][9] + coeff0_4*dmats1[4][9] + coeff0_5*dmats1[5][9] + coeff0_6*dmats1[6][9] + coeff0_7*dmats1[7][9] + coeff0_8*dmats1[8][9] + coeff0_9*dmats1[9][9];
          }
    
        }
        // Compute derivatives on reference element as dot product of coefficients and basisvalues
        derivatives[deriv_num] = new_coeff0_0*basisvalue0 + new_coeff0_1*basisvalue1 + new_coeff0_2*basisvalue2 + new_coeff0_3*basisvalue3 + new_coeff0_4*basisvalue4 + new_coeff0_5*basisvalue5 + new_coeff0_6*basisvalue6 + new_coeff0_7*basisvalue7 + new_coeff0_8*basisvalue8 + new_coeff0_9*basisvalue9;
      }
    
      // Transform derivatives back to physical element
      for (unsigned int row = 0; row < num_derivatives; row++)
      {
        for (unsigned int col = 0; col < num_derivatives; col++)
        {
          values[3*num_derivatives + row] += transform[row][col]*derivatives[col];
        }
      }
      // Delete pointer to array of derivatives on FIAT element
      delete [] derivatives;
    
      // Delete pointer to array of combinations of derivatives
      delete [] combinations;
    
    }
    
  }

  /// Evaluate linear functional for dof i on the function f
  virtual double evaluate_dof(unsigned int i,
                              const ufc::function& f,
                              const ufc::cell& c) const
  {
    double values[4];
    double coordinates[2];
    
    // Nodal coordinates on reference cell
    static double X[40][2] = {{0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}, {0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}, {0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}, {0, 0}, {1, 0}, {0, 1}, {0.6666666667, 0.3333333333}, {0.3333333333, 0.6666666667}, {0, 0.3333333333}, {0, 0.6666666667}, {0.3333333333, 0}, {0.6666666667, 0}, {0.3333333333, 0.3333333333}};
    
    // Components for each dof
    static unsigned int components[40] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3};
    
    // Extract vertex coordinates
    const double * const * x = c.coordinates;
    
    // Evaluate basis functions for affine mapping
    const double w0 = 1.0 - X[i][0] - X[i][1];
    const double w1 = X[i][0];
    const double w2 = X[i][1];
    
    // Compute affine mapping x = F(X)
    coordinates[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
    coordinates[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
    
    // Evaluate function at coordinates
    f.evaluate(values, coordinates, c);
    
    // Pick component for evaluation
    return values[components[i]];
  }

  /// Interpolate vertex values from dof values
  virtual void interpolate_vertex_values(double* vertex_values,
                                         const double* dof_values,
                                         const ufc::cell& c) const
  {
    // Evaluate at vertices and use affine mapping
    vertex_values[0] = dof_values[0];
    vertex_values[1] = dof_values[1];
    vertex_values[2] = dof_values[2];
    // Evaluate at vertices and use affine mapping
    vertex_values[3] = dof_values[10];
    vertex_values[4] = dof_values[11];
    vertex_values[5] = dof_values[12];
    // Evaluate at vertices and use affine mapping
    vertex_values[6] = dof_values[20];
    vertex_values[7] = dof_values[21];
    vertex_values[8] = dof_values[22];
    // Evaluate at vertices and use affine mapping
    vertex_values[9] = dof_values[30];
    vertex_values[10] = dof_values[31];
    vertex_values[11] = dof_values[32];
  }

  /// Return the number of sub elements (for a mixed element)
  virtual unsigned int num_sub_elements() const
  {
    return 2;
  }

  /// Create a new finite element for sub element i (for a mixed element)
  virtual ufc::finite_element* create_sub_element(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_finite_element_0_0();
      break;
    case 1:
      return new MixedMixedElement_finite_element_0_1();
      break;
    }
    return 0;
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_0_0: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_0_0() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_0_0()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Lagrange finite element of degree 3 on a triangle";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = m.num_entities[0] + 2*m.num_entities[1] + m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 10;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 4;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 1;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    return new MixedMixedElement_dof_map_0_0_0();
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_0_1: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_0_1() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_0_1()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Lagrange finite element of degree 3 on a triangle";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = m.num_entities[0] + 2*m.num_entities[1] + m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 10;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 4;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 1;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    return new MixedMixedElement_dof_map_0_0_1();
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_0: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_0() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_0()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = 2*m.num_entities[0] + 4*m.num_entities[1] + 2*m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 20;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 8;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
    offset = offset + m.num_entities[2];
    dofs[10] = offset + c.entity_indices[0][0];
    dofs[11] = offset + c.entity_indices[0][1];
    dofs[12] = offset + c.entity_indices[0][2];
    offset = offset + m.num_entities[0];
    dofs[13] = offset + 2*c.entity_indices[1][0];
    dofs[14] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[15] = offset + 2*c.entity_indices[1][1];
    dofs[16] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[17] = offset + 2*c.entity_indices[1][2];
    dofs[18] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[19] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      dofs[4] = 11;
      dofs[5] = 12;
      dofs[6] = 13;
      dofs[7] = 14;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      dofs[4] = 10;
      dofs[5] = 12;
      dofs[6] = 15;
      dofs[7] = 16;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      dofs[4] = 10;
      dofs[5] = 11;
      dofs[6] = 17;
      dofs[7] = 18;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
    coordinates[10][0] = x[0][0];
    coordinates[10][1] = x[0][1];
    coordinates[11][0] = x[1][0];
    coordinates[11][1] = x[1][1];
    coordinates[12][0] = x[2][0];
    coordinates[12][1] = x[2][1];
    coordinates[13][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[13][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[14][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[14][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[15][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[15][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[16][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[16][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[17][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[17][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[18][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[18][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[19][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[19][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 2;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_dof_map_0_0_0();
      break;
    case 1:
      return new MixedMixedElement_dof_map_0_0_1();
      break;
    }
    return 0;
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_1_0: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_1_0() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_1_0()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Lagrange finite element of degree 3 on a triangle";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = m.num_entities[0] + 2*m.num_entities[1] + m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 10;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 4;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 1;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    return new MixedMixedElement_dof_map_0_1_0();
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_1_1: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_1_1() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_1_1()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Lagrange finite element of degree 3 on a triangle";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = m.num_entities[0] + 2*m.num_entities[1] + m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 10;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 4;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 1;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    return new MixedMixedElement_dof_map_0_1_1();
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0_1: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0_1() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0_1()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = 2*m.num_entities[0] + 4*m.num_entities[1] + 2*m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 20;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 8;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
    offset = offset + m.num_entities[2];
    dofs[10] = offset + c.entity_indices[0][0];
    dofs[11] = offset + c.entity_indices[0][1];
    dofs[12] = offset + c.entity_indices[0][2];
    offset = offset + m.num_entities[0];
    dofs[13] = offset + 2*c.entity_indices[1][0];
    dofs[14] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[15] = offset + 2*c.entity_indices[1][1];
    dofs[16] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[17] = offset + 2*c.entity_indices[1][2];
    dofs[18] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[19] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      dofs[4] = 11;
      dofs[5] = 12;
      dofs[6] = 13;
      dofs[7] = 14;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      dofs[4] = 10;
      dofs[5] = 12;
      dofs[6] = 15;
      dofs[7] = 16;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      dofs[4] = 10;
      dofs[5] = 11;
      dofs[6] = 17;
      dofs[7] = 18;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
    coordinates[10][0] = x[0][0];
    coordinates[10][1] = x[0][1];
    coordinates[11][0] = x[1][0];
    coordinates[11][1] = x[1][1];
    coordinates[12][0] = x[2][0];
    coordinates[12][1] = x[2][1];
    coordinates[13][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[13][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[14][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[14][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[15][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[15][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[16][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[16][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[17][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[17][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[18][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[18][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[19][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[19][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 2;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_dof_map_0_1_0();
      break;
    case 1:
      return new MixedMixedElement_dof_map_0_1_1();
      break;
    }
    return 0;
  }

};

/// This class defines the interface for a local-to-global mapping of
/// degrees of freedom (dofs).

class MixedMixedElement_dof_map_0: public ufc::dof_map
{
private:

  unsigned int __global_dimension;

public:

  /// Constructor
  MixedMixedElement_dof_map_0() : ufc::dof_map()
  {
    __global_dimension = 0;
  }

  /// Destructor
  virtual ~MixedMixedElement_dof_map_0()
  {
    // Do nothing
  }

  /// Return a string identifying the dof map
  virtual const char* signature() const
  {
    return "FFC dof map for Mixed finite element: [Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle], Mixed finite element: [Lagrange finite element of degree 3 on a triangle, Lagrange finite element of degree 3 on a triangle]]";
  }

  /// Return true iff mesh entities of topological dimension d are needed
  virtual bool needs_mesh_entities(unsigned int d) const
  {
    switch ( d )
    {
    case 0:
      return true;
      break;
    case 1:
      return true;
      break;
    case 2:
      return true;
      break;
    }
    return false;
  }

  /// Initialize dof map for mesh (return true iff init_cell() is needed)
  virtual bool init_mesh(const ufc::mesh& m)
  {
    __global_dimension = 4*m.num_entities[0] + 8*m.num_entities[1] + 4*m.num_entities[2];
    return false;
  }

  /// Initialize dof map for given cell
  virtual void init_cell(const ufc::mesh& m,
                         const ufc::cell& c)
  {
    // Do nothing
  }

  /// Finish initialization of dof map for cells
  virtual void init_cell_finalize()
  {
    // Do nothing
  }

  /// Return the dimension of the global finite element function space
  virtual unsigned int global_dimension() const
  {
    return __global_dimension;
  }

  /// Return the dimension of the local finite element function space
  virtual unsigned int local_dimension() const
  {
    return 40;
  }

  /// Return the number of dofs on each cell facet
  virtual unsigned int num_facet_dofs() const
  {
    return 16;
  }

  /// Tabulate the local-to-global mapping of dofs on a cell
  virtual void tabulate_dofs(unsigned int* dofs,
                             const ufc::mesh& m,
                             const ufc::cell& c) const
  {
    dofs[0] = c.entity_indices[0][0];
    dofs[1] = c.entity_indices[0][1];
    dofs[2] = c.entity_indices[0][2];
    unsigned int offset = m.num_entities[0];
    dofs[3] = offset + 2*c.entity_indices[1][0];
    dofs[4] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[5] = offset + 2*c.entity_indices[1][1];
    dofs[6] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[7] = offset + 2*c.entity_indices[1][2];
    dofs[8] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[9] = offset + c.entity_indices[2][0];
    offset = offset + m.num_entities[2];
    dofs[10] = offset + c.entity_indices[0][0];
    dofs[11] = offset + c.entity_indices[0][1];
    dofs[12] = offset + c.entity_indices[0][2];
    offset = offset + m.num_entities[0];
    dofs[13] = offset + 2*c.entity_indices[1][0];
    dofs[14] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[15] = offset + 2*c.entity_indices[1][1];
    dofs[16] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[17] = offset + 2*c.entity_indices[1][2];
    dofs[18] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[19] = offset + c.entity_indices[2][0];
    offset = offset + m.num_entities[2];
    dofs[20] = offset + c.entity_indices[0][0];
    dofs[21] = offset + c.entity_indices[0][1];
    dofs[22] = offset + c.entity_indices[0][2];
    offset = offset + m.num_entities[0];
    dofs[23] = offset + 2*c.entity_indices[1][0];
    dofs[24] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[25] = offset + 2*c.entity_indices[1][1];
    dofs[26] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[27] = offset + 2*c.entity_indices[1][2];
    dofs[28] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[29] = offset + c.entity_indices[2][0];
    offset = offset + m.num_entities[2];
    dofs[30] = offset + c.entity_indices[0][0];
    dofs[31] = offset + c.entity_indices[0][1];
    dofs[32] = offset + c.entity_indices[0][2];
    offset = offset + m.num_entities[0];
    dofs[33] = offset + 2*c.entity_indices[1][0];
    dofs[34] = offset + 2*c.entity_indices[1][0] + 1;
    dofs[35] = offset + 2*c.entity_indices[1][1];
    dofs[36] = offset + 2*c.entity_indices[1][1] + 1;
    dofs[37] = offset + 2*c.entity_indices[1][2];
    dofs[38] = offset + 2*c.entity_indices[1][2] + 1;
    offset = offset + 2*m.num_entities[1];
    dofs[39] = offset + c.entity_indices[2][0];
  }

  /// Tabulate the local-to-local mapping from facet dofs to cell dofs
  virtual void tabulate_facet_dofs(unsigned int* dofs,
                                   unsigned int facet) const
  {
    switch ( facet )
    {
    case 0:
      dofs[0] = 1;
      dofs[1] = 2;
      dofs[2] = 3;
      dofs[3] = 4;
      dofs[4] = 11;
      dofs[5] = 12;
      dofs[6] = 13;
      dofs[7] = 14;
      dofs[8] = 21;
      dofs[9] = 22;
      dofs[10] = 23;
      dofs[11] = 24;
      dofs[12] = 31;
      dofs[13] = 32;
      dofs[14] = 33;
      dofs[15] = 34;
      break;
    case 1:
      dofs[0] = 0;
      dofs[1] = 2;
      dofs[2] = 5;
      dofs[3] = 6;
      dofs[4] = 10;
      dofs[5] = 12;
      dofs[6] = 15;
      dofs[7] = 16;
      dofs[8] = 20;
      dofs[9] = 22;
      dofs[10] = 25;
      dofs[11] = 26;
      dofs[12] = 30;
      dofs[13] = 32;
      dofs[14] = 35;
      dofs[15] = 36;
      break;
    case 2:
      dofs[0] = 0;
      dofs[1] = 1;
      dofs[2] = 7;
      dofs[3] = 8;
      dofs[4] = 10;
      dofs[5] = 11;
      dofs[6] = 17;
      dofs[7] = 18;
      dofs[8] = 20;
      dofs[9] = 21;
      dofs[10] = 27;
      dofs[11] = 28;
      dofs[12] = 30;
      dofs[13] = 31;
      dofs[14] = 37;
      dofs[15] = 38;
      break;
    }
  }

  /// Tabulate the coordinates of all dofs on a cell
  virtual void tabulate_coordinates(double** coordinates,
                                    const ufc::cell& c) const
  {
    const double * const * x = c.coordinates;
    coordinates[0][0] = x[0][0];
    coordinates[0][1] = x[0][1];
    coordinates[1][0] = x[1][0];
    coordinates[1][1] = x[1][1];
    coordinates[2][0] = x[2][0];
    coordinates[2][1] = x[2][1];
    coordinates[3][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[3][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[4][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[4][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[5][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[5][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[6][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[6][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[7][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[7][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[8][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[8][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[9][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[9][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
    coordinates[10][0] = x[0][0];
    coordinates[10][1] = x[0][1];
    coordinates[11][0] = x[1][0];
    coordinates[11][1] = x[1][1];
    coordinates[12][0] = x[2][0];
    coordinates[12][1] = x[2][1];
    coordinates[13][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[13][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[14][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[14][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[15][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[15][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[16][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[16][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[17][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[17][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[18][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[18][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[19][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[19][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
    coordinates[20][0] = x[0][0];
    coordinates[20][1] = x[0][1];
    coordinates[21][0] = x[1][0];
    coordinates[21][1] = x[1][1];
    coordinates[22][0] = x[2][0];
    coordinates[22][1] = x[2][1];
    coordinates[23][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[23][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[24][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[24][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[25][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[25][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[26][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[26][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[27][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[27][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[28][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[28][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[29][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[29][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
    coordinates[30][0] = x[0][0];
    coordinates[30][1] = x[0][1];
    coordinates[31][0] = x[1][0];
    coordinates[31][1] = x[1][1];
    coordinates[32][0] = x[2][0];
    coordinates[32][1] = x[2][1];
    coordinates[33][0] = 0.6666666667*x[1][0] + 0.3333333333*x[2][0];
    coordinates[33][1] = 0.6666666667*x[1][1] + 0.3333333333*x[2][1];
    coordinates[34][0] = 0.3333333333*x[1][0] + 0.6666666667*x[2][0];
    coordinates[34][1] = 0.3333333333*x[1][1] + 0.6666666667*x[2][1];
    coordinates[35][0] = 0.6666666667*x[0][0] + 0.3333333333*x[2][0];
    coordinates[35][1] = 0.6666666667*x[0][1] + 0.3333333333*x[2][1];
    coordinates[36][0] = 0.3333333333*x[0][0] + 0.6666666667*x[2][0];
    coordinates[36][1] = 0.3333333333*x[0][1] + 0.6666666667*x[2][1];
    coordinates[37][0] = 0.6666666667*x[0][0] + 0.3333333333*x[1][0];
    coordinates[37][1] = 0.6666666667*x[0][1] + 0.3333333333*x[1][1];
    coordinates[38][0] = 0.3333333333*x[0][0] + 0.6666666667*x[1][0];
    coordinates[38][1] = 0.3333333333*x[0][1] + 0.6666666667*x[1][1];
    coordinates[39][0] = 0.3333333333*x[0][0] + 0.3333333333*x[1][0] + 0.3333333333*x[2][0];
    coordinates[39][1] = 0.3333333333*x[0][1] + 0.3333333333*x[1][1] + 0.3333333333*x[2][1];
  }

  /// Return the number of sub dof maps (for a mixed element)
  virtual unsigned int num_sub_dof_maps() const
  {
    return 2;
  }

  /// Create a new dof_map for sub dof map i (for a mixed element)
  virtual ufc::dof_map* create_sub_dof_map(unsigned int i) const
  {
    switch ( i )
    {
    case 0:
      return new MixedMixedElement_dof_map_0_0();
      break;
    case 1:
      return new MixedMixedElement_dof_map_0_1();
      break;
    }
    return 0;
  }

};

#endif
