[cig-commits] commit: fixed Function Space and Function Declarations in MADDs-5a, now
Mercurial
hg at geodynamics.org
Wed Dec 9 20:51:24 PST 2009
changeset: 109:6016b892ddd6
tag: 0.1.2
user: Marc Spiegelman <mspieg at ldeo.columbia.edu>
date: Wed Dec 09 23:17:37 2009 -0500
files: MADDs-5/MADDs-5a/cpp/P1.h MADDs-5/MADDs-5a/cpp/P1.ufl MADDs-5/MADDs-5a/cpp/P2v.h MADDs-5/MADDs-5a/cpp/P2v.ufl MADDs-5/MADDs-5a/cpp/forms/MagmaEquations_P2.ufl MADDs-5/MADDs-5a/cpp/forms/MeltFlux_P2.ufl MADDs-5/MADDs-5a/cpp/main.cpp
description:
fixed Function Space and Function Declarations in MADDs-5a, now
working for 0.9.5 (but need to report bug on subspaces)
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/P1.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MADDs-5/MADDs-5a/cpp/P1.h Wed Dec 09 23:17:37 2009 -0500
@@ -0,0 +1,3205 @@
+// This code conforms with the UFC specification version 1.0
+// and was automatically generated by FFC version 0.7.1.
+//
+// Warning: This code was generated with the option '-l dolfin'
+// and contains DOLFIN-specific wrappers that depend on DOLFIN.
+
+#ifndef __P1_H
+#define __P1_H
+
+#include <cmath>
+#include <stdexcept>
+#include <fstream>
+#include <ufc.h>
+
+/// This class defines the interface for a finite element.
+
+class p1_0_finite_element_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p1_0_finite_element_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_0_finite_element_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 3;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Extract relevant coefficients
+ const double coeff0_0 = coefficients0[dof][0];
+ const double coeff0_1 = coefficients0[dof][1];
+ const double coeff0_2 = coefficients0[dof][2];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[3][3] = \
+ {{0, 0, 0},
+ {4.89897948556636, 0, 0},
+ {0, 0, 0}};
+
+ static const double dmats1[3][3] = \
+ {{0, 0, 0},
+ {2.44948974278318, 0, 0},
+ {4.24264068711928, 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;
+
+ // Declare new coefficients
+ double new_coeff0_0 = 0;
+ double new_coeff0_1 = 0;
+ double new_coeff0_2 = 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];
+
+ // 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;
+
+ if(combinations[deriv_num][j] == 0)
+ {
+ new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0];
+ new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1];
+ new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2];
+ }
+ if(combinations[deriv_num][j] == 1)
+ {
+ new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0];
+ new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1];
+ new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}};
+ static const double W[3][1] = {{1}, {1}, {1}};
+ static const double D[3][1][1] = {{{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p1_0_finite_element_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p1_0_finite_element_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p1_0_finite_element_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_0_finite_element_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 3;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Extract relevant coefficients
+ const double coeff0_0 = coefficients0[dof][0];
+ const double coeff0_1 = coefficients0[dof][1];
+ const double coeff0_2 = coefficients0[dof][2];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[3][3] = \
+ {{0, 0, 0},
+ {4.89897948556636, 0, 0},
+ {0, 0, 0}};
+
+ static const double dmats1[3][3] = \
+ {{0, 0, 0},
+ {2.44948974278318, 0, 0},
+ {4.24264068711928, 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;
+
+ // Declare new coefficients
+ double new_coeff0_0 = 0;
+ double new_coeff0_1 = 0;
+ double new_coeff0_2 = 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];
+
+ // 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;
+
+ if(combinations[deriv_num][j] == 0)
+ {
+ new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0];
+ new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1];
+ new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2];
+ }
+ if(combinations[deriv_num][j] == 1)
+ {
+ new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0];
+ new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1];
+ new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}};
+ static const double W[3][1] = {{1}, {1}, {1}};
+ static const double D[3][1][1] = {{{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p1_0_finite_element_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p1_0_dof_map_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p1_0_dof_map_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p1_0_dof_map_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 false;
+ break;
+ case 2:
+ return false;
+ 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];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 3;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 3;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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 p1_0_dof_map_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p1_0_dof_map_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p1_0_dof_map_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p1_0_dof_map_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 false;
+ break;
+ case 2:
+ return false;
+ 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];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 3;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 3;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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 p1_0_dof_map_1();
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p1_0_cell_integral_0_quadrature: public ufc::cell_integral
+{
+public:
+
+ /// Constructor
+ p1_0_cell_integral_0_quadrature() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_0_cell_integral_0_quadrature()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Extract vertex coordinates
+ const double * const * x = c.coordinates;
+
+ // Compute Jacobian of affine map from reference cell
+ const double J_00 = x[1][0] - x[0][0];
+ const double J_01 = x[2][0] - x[0][0];
+ const double J_10 = x[1][1] - x[0][1];
+ const double J_11 = x[2][1] - x[0][1];
+
+ // Compute determinant of Jacobian
+ double detJ = J_00*J_11 - J_01*J_10;
+
+ // Compute inverse of Jacobian
+
+ // Set scale factor
+ const double det = std::abs(detJ);
+
+
+ // Array of quadrature weights
+ static const double W4[4] = {0.159020690871988, 0.0909793091280113, 0.159020690871988, 0.0909793091280113};
+ // Quadrature points on the UFC reference element: (0.178558728263616, 0.155051025721682), (0.0750311102226081, 0.644948974278318), (0.666390246014701, 0.155051025721682), (0.280019915499074, 0.644948974278318)
+
+ // Value of basis functions at quadrature points.
+ static const double FE0[4][3] = \
+ {{0.666390246014701, 0.178558728263616, 0.155051025721682},
+ {0.280019915499074, 0.0750311102226082, 0.644948974278318},
+ {0.178558728263616, 0.666390246014701, 0.155051025721682},
+ {0.0750311102226081, 0.280019915499074, 0.644948974278318}};
+
+
+ // Compute element tensor using UFL quadrature representation
+ // Optimisations: ('simplify expressions', True), ('ignore zero tables', True), ('non zero columns', True), ('remove zero terms', True), ('ignore ones', True)
+ // Total number of operations to compute element tensor: 112
+
+ // Loop quadrature points for integral
+ // Number of operations to compute element tensor for following IP loop = 112
+ for (unsigned int ip = 0; ip < 4; ip++)
+ {
+
+ // Number of operations to compute ip constants: 1
+ // Number of operations: 1
+ const double Gip0 = W4[ip]*det;
+
+
+ // Number of operations for primary indices: 27
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ for (unsigned int k = 0; k < 3; k++)
+ {
+ // Number of operations to compute entry: 3
+ A[j*3 + k] += FE0[ip][j]*FE0[ip][k]*Gip0;
+ }// end loop over 'k'
+ }// end loop over 'j'
+ }// end loop over 'ip'
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p1_0_cell_integral_0: public ufc::cell_integral
+{
+private:
+
+ p1_0_cell_integral_0_quadrature integral_0_quadrature;
+
+public:
+
+ /// Constructor
+ p1_0_cell_integral_0() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_0_cell_integral_0()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Reset values of the element tensor block
+ for (unsigned int j = 0; j < 9; j++)
+ A[j] = 0;
+
+ // Add all contributions to element tensor
+ integral_0_quadrature.tabulate_tensor(A, w, c);
+ }
+
+};
+
+/// This class defines the interface for the assembly of the global
+/// tensor corresponding to a form with r + n arguments, that is, a
+/// mapping
+///
+/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
+///
+/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
+/// global tensor A is defined by
+///
+/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
+///
+/// where each argument Vj represents the application to the
+/// sequence of basis functions of Vj and w1, w2, ..., wn are given
+/// fixed functions (coefficients).
+
+class p1_form_0: public ufc::form
+{
+public:
+
+ /// Constructor
+ p1_form_0() : ufc::form()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_form_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the form
+ virtual const char* signature() const
+ {
+ return "Form([Integral(Product(BasisFunction(FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1), 0), BasisFunction(FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1), 1)), Measure('cell', 0, None))])";
+ }
+
+ /// Return the rank of the global tensor (r)
+ virtual unsigned int rank() const
+ {
+ return 2;
+ }
+
+ /// Return the number of coefficients (n)
+ virtual unsigned int num_coefficients() const
+ {
+ return 0;
+ }
+
+ /// Return the number of cell integrals
+ virtual unsigned int num_cell_integrals() const
+ {
+ return 1;
+ }
+
+ /// Return the number of exterior facet integrals
+ virtual unsigned int num_exterior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Return the number of interior facet integrals
+ virtual unsigned int num_interior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Create a new finite element for argument function i
+ virtual ufc::finite_element* create_finite_element(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p1_0_finite_element_0();
+ break;
+ case 1:
+ return new p1_0_finite_element_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new dof map for argument function i
+ virtual ufc::dof_map* create_dof_map(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p1_0_dof_map_0();
+ break;
+ case 1:
+ return new p1_0_dof_map_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new cell integral on sub domain i
+ virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
+ {
+ return new p1_0_cell_integral_0();
+ }
+
+ /// Create a new exterior facet integral on sub domain i
+ virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+ /// Create a new interior facet integral on sub domain i
+ virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p1_1_finite_element_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p1_1_finite_element_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_1_finite_element_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 3;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Extract relevant coefficients
+ const double coeff0_0 = coefficients0[dof][0];
+ const double coeff0_1 = coefficients0[dof][1];
+ const double coeff0_2 = coefficients0[dof][2];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[3][3] = \
+ {{0, 0, 0},
+ {4.89897948556636, 0, 0},
+ {0, 0, 0}};
+
+ static const double dmats1[3][3] = \
+ {{0, 0, 0},
+ {2.44948974278318, 0, 0},
+ {4.24264068711928, 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;
+
+ // Declare new coefficients
+ double new_coeff0_0 = 0;
+ double new_coeff0_1 = 0;
+ double new_coeff0_2 = 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];
+
+ // 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;
+
+ if(combinations[deriv_num][j] == 0)
+ {
+ new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0];
+ new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1];
+ new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2];
+ }
+ if(combinations[deriv_num][j] == 1)
+ {
+ new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0];
+ new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1];
+ new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}};
+ static const double W[3][1] = {{1}, {1}, {1}};
+ static const double D[3][1][1] = {{{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p1_1_finite_element_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p1_1_finite_element_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p1_1_finite_element_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_1_finite_element_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 3;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Extract relevant coefficients
+ const double coeff0_0 = coefficients0[dof][0];
+ const double coeff0_1 = coefficients0[dof][1];
+ const double coeff0_2 = coefficients0[dof][2];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // Compute psitilde_a
+ const double psitilde_a_0 = 1;
+ const double psitilde_a_1 = x;
+
+ // 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_1_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*psitilde_a_1*scalings_y_1*psitilde_bs_1_0;
+ const double basisvalue2 = psitilde_a_0*scalings_y_0*psitilde_bs_0_1;
+
+ // Table(s) of coefficients
+ static const double coefficients0[3][3] = \
+ {{0.471404520791032, -0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0.288675134594813, -0.166666666666667},
+ {0.471404520791032, 0, 0.333333333333333}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[3][3] = \
+ {{0, 0, 0},
+ {4.89897948556636, 0, 0},
+ {0, 0, 0}};
+
+ static const double dmats1[3][3] = \
+ {{0, 0, 0},
+ {2.44948974278318, 0, 0},
+ {4.24264068711928, 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;
+
+ // Declare new coefficients
+ double new_coeff0_0 = 0;
+ double new_coeff0_1 = 0;
+ double new_coeff0_2 = 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];
+
+ // 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;
+
+ if(combinations[deriv_num][j] == 0)
+ {
+ new_coeff0_0 = coeff0_0*dmats0[0][0] + coeff0_1*dmats0[1][0] + coeff0_2*dmats0[2][0];
+ new_coeff0_1 = coeff0_0*dmats0[0][1] + coeff0_1*dmats0[1][1] + coeff0_2*dmats0[2][1];
+ new_coeff0_2 = coeff0_0*dmats0[0][2] + coeff0_1*dmats0[1][2] + coeff0_2*dmats0[2][2];
+ }
+ if(combinations[deriv_num][j] == 1)
+ {
+ new_coeff0_0 = coeff0_0*dmats1[0][0] + coeff0_1*dmats1[1][0] + coeff0_2*dmats1[2][0];
+ new_coeff0_1 = coeff0_0*dmats1[0][1] + coeff0_1*dmats1[1][1] + coeff0_2*dmats1[2][1];
+ new_coeff0_2 = coeff0_0*dmats1[0][2] + coeff0_1*dmats1[1][2] + coeff0_2*dmats1[2][2];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[3][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}};
+ static const double W[3][1] = {{1}, {1}, {1}};
+ static const double D[3][1][1] = {{{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p1_1_finite_element_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p1_1_dof_map_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p1_1_dof_map_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p1_1_dof_map_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 false;
+ break;
+ case 2:
+ return false;
+ 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];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 3;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 3;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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 p1_1_dof_map_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p1_1_dof_map_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p1_1_dof_map_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p1_1_dof_map_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1)";
+ }
+
+ /// 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 false;
+ break;
+ case 2:
+ return false;
+ 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];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 3;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 3;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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];
+ }
+
+ /// 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 p1_1_dof_map_1();
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p1_1_cell_integral_0_quadrature: public ufc::cell_integral
+{
+public:
+
+ /// Constructor
+ p1_1_cell_integral_0_quadrature() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_1_cell_integral_0_quadrature()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Extract vertex coordinates
+ const double * const * x = c.coordinates;
+
+ // Compute Jacobian of affine map from reference cell
+ const double J_00 = x[1][0] - x[0][0];
+ const double J_01 = x[2][0] - x[0][0];
+ const double J_10 = x[1][1] - x[0][1];
+ const double J_11 = x[2][1] - x[0][1];
+
+ // Compute determinant of Jacobian
+ double detJ = J_00*J_11 - J_01*J_10;
+
+ // Compute inverse of Jacobian
+
+ // Set scale factor
+ const double det = std::abs(detJ);
+
+
+ // Array of quadrature weights
+ static const double W4[4] = {0.159020690871988, 0.0909793091280113, 0.159020690871988, 0.0909793091280113};
+ // Quadrature points on the UFC reference element: (0.178558728263616, 0.155051025721682), (0.0750311102226081, 0.644948974278318), (0.666390246014701, 0.155051025721682), (0.280019915499074, 0.644948974278318)
+
+ // Value of basis functions at quadrature points.
+ static const double FE0[4][3] = \
+ {{0.666390246014701, 0.178558728263616, 0.155051025721682},
+ {0.280019915499074, 0.0750311102226082, 0.644948974278318},
+ {0.178558728263616, 0.666390246014701, 0.155051025721682},
+ {0.0750311102226081, 0.280019915499074, 0.644948974278318}};
+
+
+ // Compute element tensor using UFL quadrature representation
+ // Optimisations: ('simplify expressions', True), ('ignore zero tables', True), ('non zero columns', True), ('remove zero terms', True), ('ignore ones', True)
+ // Total number of operations to compute element tensor: 56
+
+ // Loop quadrature points for integral
+ // Number of operations to compute element tensor for following IP loop = 56
+ for (unsigned int ip = 0; ip < 4; ip++)
+ {
+
+ // Function declarations
+ double F0 = 0;
+
+ // Total number of operations to compute function values = 6
+ for (unsigned int r = 0; r < 3; r++)
+ {
+ F0 += FE0[ip][r]*w[0][r];
+ }// end loop over 'r'
+
+ // Number of operations to compute ip constants: 2
+ // Number of operations: 2
+ const double Gip0 = F0*W4[ip]*det;
+
+
+ // Number of operations for primary indices: 6
+ for (unsigned int j = 0; j < 3; j++)
+ {
+ // Number of operations to compute entry: 2
+ A[j] += FE0[ip][j]*Gip0;
+ }// end loop over 'j'
+ }// end loop over 'ip'
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p1_1_cell_integral_0: public ufc::cell_integral
+{
+private:
+
+ p1_1_cell_integral_0_quadrature integral_0_quadrature;
+
+public:
+
+ /// Constructor
+ p1_1_cell_integral_0() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_1_cell_integral_0()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Reset values of the element tensor block
+ for (unsigned int j = 0; j < 3; j++)
+ A[j] = 0;
+
+ // Add all contributions to element tensor
+ integral_0_quadrature.tabulate_tensor(A, w, c);
+ }
+
+};
+
+/// This class defines the interface for the assembly of the global
+/// tensor corresponding to a form with r + n arguments, that is, a
+/// mapping
+///
+/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
+///
+/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
+/// global tensor A is defined by
+///
+/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
+///
+/// where each argument Vj represents the application to the
+/// sequence of basis functions of Vj and w1, w2, ..., wn are given
+/// fixed functions (coefficients).
+
+class p1_form_1: public ufc::form
+{
+public:
+
+ /// Constructor
+ p1_form_1() : ufc::form()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p1_form_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the form
+ virtual const char* signature() const
+ {
+ return "Form([Integral(Product(BasisFunction(FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1), 0), Function(FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 1), 0)), Measure('cell', 0, None))])";
+ }
+
+ /// Return the rank of the global tensor (r)
+ virtual unsigned int rank() const
+ {
+ return 1;
+ }
+
+ /// Return the number of coefficients (n)
+ virtual unsigned int num_coefficients() const
+ {
+ return 1;
+ }
+
+ /// Return the number of cell integrals
+ virtual unsigned int num_cell_integrals() const
+ {
+ return 1;
+ }
+
+ /// Return the number of exterior facet integrals
+ virtual unsigned int num_exterior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Return the number of interior facet integrals
+ virtual unsigned int num_interior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Create a new finite element for argument function i
+ virtual ufc::finite_element* create_finite_element(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p1_1_finite_element_0();
+ break;
+ case 1:
+ return new p1_1_finite_element_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new dof map for argument function i
+ virtual ufc::dof_map* create_dof_map(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p1_1_dof_map_0();
+ break;
+ case 1:
+ return new p1_1_dof_map_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new cell integral on sub domain i
+ virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
+ {
+ return new p1_1_cell_integral_0();
+ }
+
+ /// Create a new exterior facet integral on sub domain i
+ virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+ /// Create a new interior facet integral on sub domain i
+ virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+};
+
+// DOLFIN wrappers
+
+// Standard library includes
+#include <string>
+
+// DOLFIN includes
+#include <dolfin/common/NoDeleter.h>
+#include <dolfin/fem/FiniteElement.h>
+#include <dolfin/fem/DofMap.h>
+#include <dolfin/fem/Form.h>
+#include <dolfin/function/FunctionSpace.h>
+#include <dolfin/function/GenericFunction.h>
+#include <dolfin/function/CoefficientAssigner.h>
+
+namespace P1
+{
+
+class CoefficientSpace_f: public dolfin::FunctionSpace
+{
+public:
+
+ CoefficientSpace_f(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~CoefficientSpace_f()
+ {
+ }
+
+};
+
+class Form_0_FunctionSpace_0: public dolfin::FunctionSpace
+{
+public:
+
+ Form_0_FunctionSpace_0(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_0_FunctionSpace_0()
+ {
+ }
+
+};
+
+class Form_0_FunctionSpace_1: public dolfin::FunctionSpace
+{
+public:
+
+ Form_0_FunctionSpace_1(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_0_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_0_FunctionSpace_1()
+ {
+ }
+
+};
+
+class Form_0: public dolfin::Form
+{
+public:
+
+ // Constructor
+ Form_0(const dolfin::FunctionSpace& V0, const dolfin::FunctionSpace& V1):
+ dolfin::Form(2, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+ _function_spaces[1] = reference_to_no_delete_pointer(V1);
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_0());
+ }
+
+ // Constructor
+ Form_0(boost::shared_ptr<const dolfin::FunctionSpace> V0, boost::shared_ptr<const dolfin::FunctionSpace> V1):
+ dolfin::Form(2, 0)
+ {
+ _function_spaces[0] = V0;
+ _function_spaces[1] = V1;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_0());
+ }
+
+ // Destructor
+ ~Form_0()
+ {}
+
+ /// Return the number of the coefficient with this name
+ virtual dolfin::uint coefficient_number(const std::string& name) const
+ {
+
+ dolfin::error("No coefficients.");
+ return 0;
+ }
+
+ /// Return the name of the coefficient with this number
+ virtual std::string coefficient_name(dolfin::uint i) const
+ {
+
+ dolfin::error("No coefficients.");
+ return "unnamed";
+ }
+
+ // Typedefs
+ typedef Form_0_FunctionSpace_0 TestSpace;
+ typedef Form_0_FunctionSpace_1 TrialSpace;
+
+ // Coefficients
+};
+
+class Form_1_FunctionSpace_0: public dolfin::FunctionSpace
+{
+public:
+
+ Form_1_FunctionSpace_0(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p1_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p1_1_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_1_FunctionSpace_0()
+ {
+ }
+
+};
+
+typedef CoefficientSpace_f Form_1_FunctionSpace_1;
+
+class Form_1: public dolfin::Form
+{
+public:
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0, const dolfin::GenericFunction& f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ this->f = f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0, boost::shared_ptr<const dolfin::GenericFunction> f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ this->f = *f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0, const dolfin::GenericFunction& f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ this->f = f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0, boost::shared_ptr<const dolfin::GenericFunction> f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ this->f = *f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p1_form_1());
+ }
+
+ // Destructor
+ ~Form_1()
+ {}
+
+ /// Return the number of the coefficient with this name
+ virtual dolfin::uint coefficient_number(const std::string& name) const
+ {
+ if (name == "f")
+ return 0;
+
+ dolfin::error("Invalid coefficient.");
+ return 0;
+ }
+
+ /// Return the name of the coefficient with this number
+ virtual std::string coefficient_name(dolfin::uint i) const
+ {
+ switch (i)
+ {
+ case 0:
+ return "f";
+ }
+
+ dolfin::error("Invalid coefficient.");
+ return "unnamed";
+ }
+
+ // Typedefs
+ typedef Form_1_FunctionSpace_0 TestSpace;
+ typedef Form_1_FunctionSpace_1 CoefficientSpace_f;
+
+ // Coefficients
+ dolfin::CoefficientAssigner f;
+};
+
+// Class typedefs
+typedef Form_0 BilinearForm;
+typedef Form_1 LinearForm;
+typedef Form_0::TestSpace FunctionSpace;
+
+} // namespace P1
+
+#endif
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/P1.ufl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MADDs-5/MADDs-5a/cpp/P1.ufl Wed Dec 09 23:17:37 2009 -0500
@@ -0,0 +1,21 @@
+# Copyright (C) 2009 Marc Spiegelman
+# Licensed under the GNU LGPL Version 2.1.
+#
+# First added: 10 Jul 2009 12:46:10
+# Last changed: 10 Jul 2009 12:46:18
+#
+# Function Space definitions for linear triangles
+#
+# Compile this form with FFC: ffc -l dolfin -O P1.ufl
+
+P1 = FiniteElement("Lagrange", "triangle", 1)
+
+u = TrialFunction(P1)
+v = TestFunction(P1)
+f = Function(P1)
+
+L = v*f*dx
+a = v*u*dx
+
+
+
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/P2v.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MADDs-5/MADDs-5a/cpp/P2v.h Wed Dec 09 23:17:37 2009 -0500
@@ -0,0 +1,9720 @@
+// This code conforms with the UFC specification version 1.0
+// and was automatically generated by FFC version 0.7.1.
+//
+// Warning: This code was generated with the option '-l dolfin'
+// and contains DOLFIN-specific wrappers that depend on DOLFIN.
+
+#ifndef __P2V_H
+#define __P2V_H
+
+#include <cmath>
+#include <stdexcept>
+#include <fstream>
+#include <ufc.h>
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_0_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_0_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_0_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_0_finite_element_0_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_0_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_0_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_0_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_0_finite_element_0_1();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 12;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.0*y - 1.0;
+
+ // Reset values
+ values[0] = 0;
+ values[1] = 0;
+
+ if (0 <= i && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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 && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[12][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}, {{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[12][1][2] = {{{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[2];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 2; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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[2] = dof_values[1];
+ vertex_values[4] = dof_values[2];
+ // Evaluate at vertices and use affine mapping
+ vertex_values[1] = dof_values[6];
+ vertex_values[3] = dof_values[7];
+ vertex_values[5] = dof_values[8];
+ }
+
+ /// 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 p2v_0_finite_element_0_0();
+ break;
+ case 1:
+ return new p2v_0_finite_element_0_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_1_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_1_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_1_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_0_finite_element_1_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_1_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_1_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_1_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_0_finite_element_1_1();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_0_finite_element_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_0_finite_element_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_finite_element_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 12;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.0*y - 1.0;
+
+ // Reset values
+ values[0] = 0;
+ values[1] = 0;
+
+ if (0 <= i && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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 && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[12][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}, {{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[12][1][2] = {{{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[2];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 2; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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[2] = dof_values[1];
+ vertex_values[4] = dof_values[2];
+ // Evaluate at vertices and use affine mapping
+ vertex_values[1] = dof_values[6];
+ vertex_values[3] = dof_values[7];
+ vertex_values[5] = dof_values[8];
+ }
+
+ /// 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 p2v_0_finite_element_1_0();
+ break;
+ case 1:
+ return new p2v_0_finite_element_1_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_0_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_0_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_0_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_0_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_0_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_0_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_0_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_0_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 false;
+ 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] + 2*m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 12;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 12;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 6;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ offset = offset + m.num_entities[1];
+ dofs[6] = offset + c.entity_indices[0][0];
+ dofs[7] = offset + c.entity_indices[0][1];
+ dofs[8] = offset + c.entity_indices[0][2];
+ offset = offset + m.num_entities[0];
+ dofs[9] = offset + c.entity_indices[1][0];
+ dofs[10] = offset + c.entity_indices[1][1];
+ dofs[11] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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] = 7;
+ dofs[4] = 8;
+ dofs[5] = 9;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ dofs[3] = 6;
+ dofs[4] = 8;
+ dofs[5] = 10;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ dofs[3] = 6;
+ dofs[4] = 7;
+ dofs[5] = 11;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][1];
+ coordinates[6][0] = x[0][0];
+ coordinates[6][1] = x[0][1];
+ coordinates[7][0] = x[1][0];
+ coordinates[7][1] = x[1][1];
+ coordinates[8][0] = x[2][0];
+ coordinates[8][1] = x[2][1];
+ coordinates[9][0] = 0.5*x[1][0] + 0.5*x[2][0];
+ coordinates[9][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[10][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[10][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[11][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[11][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_0_0();
+ break;
+ case 1:
+ return new p2v_0_dof_map_0_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_1_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_1_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_1_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_1_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_1_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_1_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_1_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_1_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_0_dof_map_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_0_dof_map_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_0_dof_map_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 false;
+ 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] + 2*m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 12;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 12;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 6;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ offset = offset + m.num_entities[1];
+ dofs[6] = offset + c.entity_indices[0][0];
+ dofs[7] = offset + c.entity_indices[0][1];
+ dofs[8] = offset + c.entity_indices[0][2];
+ offset = offset + m.num_entities[0];
+ dofs[9] = offset + c.entity_indices[1][0];
+ dofs[10] = offset + c.entity_indices[1][1];
+ dofs[11] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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] = 7;
+ dofs[4] = 8;
+ dofs[5] = 9;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ dofs[3] = 6;
+ dofs[4] = 8;
+ dofs[5] = 10;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ dofs[3] = 6;
+ dofs[4] = 7;
+ dofs[5] = 11;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][1];
+ coordinates[6][0] = x[0][0];
+ coordinates[6][1] = x[0][1];
+ coordinates[7][0] = x[1][0];
+ coordinates[7][1] = x[1][1];
+ coordinates[8][0] = x[2][0];
+ coordinates[8][1] = x[2][1];
+ coordinates[9][0] = 0.5*x[1][0] + 0.5*x[2][0];
+ coordinates[9][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[10][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[10][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[11][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[11][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_0_dof_map_1_0();
+ break;
+ case 1:
+ return new p2v_0_dof_map_1_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p2v_0_cell_integral_0_quadrature: public ufc::cell_integral
+{
+public:
+
+ /// Constructor
+ p2v_0_cell_integral_0_quadrature() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_cell_integral_0_quadrature()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Extract vertex coordinates
+ const double * const * x = c.coordinates;
+
+ // Compute Jacobian of affine map from reference cell
+ const double J_00 = x[1][0] - x[0][0];
+ const double J_01 = x[2][0] - x[0][0];
+ const double J_10 = x[1][1] - x[0][1];
+ const double J_11 = x[2][1] - x[0][1];
+
+ // Compute determinant of Jacobian
+ double detJ = J_00*J_11 - J_01*J_10;
+
+ // Compute inverse of Jacobian
+
+ // Set scale factor
+ const double det = std::abs(detJ);
+
+
+ // Array of quadrature weights
+ static const double W9[9] = {0.0558144204830443, 0.063678085099885, 0.0193963833059595, 0.0893030727728709, 0.101884936159816, 0.0310342132895351, 0.0558144204830443, 0.063678085099885, 0.0193963833059595};
+ // Quadrature points on the UFC reference element: (0.102717654809626, 0.088587959512704), (0.0665540678391645, 0.409466864440735), (0.0239311322870806, 0.787659461760847), (0.455706020243648, 0.088587959512704), (0.295266567779633, 0.409466864440735), (0.106170269119576, 0.787659461760847), (0.80869438567767, 0.088587959512704), (0.523979067720101, 0.409466864440735), (0.188409405952072, 0.787659461760847)
+
+ // Value of basis functions at quadrature points.
+ static const double FE0_C0[9][6] = \
+ {{0.499278833175498, -0.0816158215904472, -0.072892306371455, 0.0363981897820602, 0.286562341986258, 0.332268763018087},
+ {0.0251290590975512, -0.0576951799472843, -0.0741406382908806, 0.109006741895515, 0.858208263567716, 0.139491753677383},
+ {-0.117413197449647, -0.022785734101997, 0.453155393641927, 0.0753983311062782, 0.593609805131561, 0.0180354016718773},
+ {-0.0403700664710397, -0.0403700664710397, -0.072892306371455, 0.161480265884159, 0.161480265884159, 0.830671907545216},
+ {-0.120901875682904, -0.120901875682904, -0.0741406382908806, 0.483607502731615, 0.483607502731615, 0.348729384193458},
+ {-0.0836260170297298, -0.0836260170297298, 0.453155393641927, 0.33450406811892, 0.33450406811892, 0.0450885041796933},
+ {-0.0816158215904471, 0.499278833175498, -0.072892306371455, 0.286562341986258, 0.0363981897820602, 0.332268763018087},
+ {-0.0576951799472841, 0.0251290590975512, -0.0741406382908806, 0.858208263567716, 0.109006741895515, 0.139491753677383},
+ {-0.022785734101997, -0.117413197449647, 0.453155393641927, 0.593609805131561, 0.0753983311062783, 0.0180354016718774}};
+
+ // Array of non-zero columns
+ static const unsigned int nzc1[6] = {6, 7, 8, 9, 10, 11};
+ // Array of non-zero columns
+ static const unsigned int nzc0[6] = {0, 1, 2, 3, 4, 5};
+
+ // Compute element tensor using UFL quadrature representation
+ // Optimisations: ('simplify expressions', True), ('ignore zero tables', True), ('non zero columns', True), ('remove zero terms', True), ('ignore ones', True)
+ // Total number of operations to compute element tensor: 1953
+
+ // Loop quadrature points for integral
+ // Number of operations to compute element tensor for following IP loop = 1953
+ for (unsigned int ip = 0; ip < 9; ip++)
+ {
+
+ // Number of operations to compute ip constants: 1
+ // Number of operations: 1
+ const double Gip0 = W9[ip]*det;
+
+
+ // Number of operations for primary indices: 216
+ for (unsigned int j = 0; j < 6; j++)
+ {
+ for (unsigned int k = 0; k < 6; k++)
+ {
+ // Number of operations to compute entry: 3
+ A[nzc0[j]*12 + nzc0[k]] += FE0_C0[ip][j]*FE0_C0[ip][k]*Gip0;
+ // Number of operations to compute entry: 3
+ A[nzc1[j]*12 + nzc1[k]] += FE0_C0[ip][j]*FE0_C0[ip][k]*Gip0;
+ }// end loop over 'k'
+ }// end loop over 'j'
+ }// end loop over 'ip'
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p2v_0_cell_integral_0: public ufc::cell_integral
+{
+private:
+
+ p2v_0_cell_integral_0_quadrature integral_0_quadrature;
+
+public:
+
+ /// Constructor
+ p2v_0_cell_integral_0() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_0_cell_integral_0()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Reset values of the element tensor block
+ for (unsigned int j = 0; j < 144; j++)
+ A[j] = 0;
+
+ // Add all contributions to element tensor
+ integral_0_quadrature.tabulate_tensor(A, w, c);
+ }
+
+};
+
+/// This class defines the interface for the assembly of the global
+/// tensor corresponding to a form with r + n arguments, that is, a
+/// mapping
+///
+/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
+///
+/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
+/// global tensor A is defined by
+///
+/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
+///
+/// where each argument Vj represents the application to the
+/// sequence of basis functions of Vj and w1, w2, ..., wn are given
+/// fixed functions (coefficients).
+
+class p2v_form_0: public ufc::form
+{
+public:
+
+ /// Constructor
+ p2v_form_0() : ufc::form()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_form_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the form
+ virtual const char* signature() const
+ {
+ return "Form([Integral(IndexSum(Product(Indexed(BasisFunction(VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2), 0), MultiIndex((Index(0),), {Index(0): 2})), Indexed(BasisFunction(VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2), 1), MultiIndex((Index(0),), {Index(0): 2}))), MultiIndex((Index(0),), {Index(0): 2})), Measure('cell', 0, None))])";
+ }
+
+ /// Return the rank of the global tensor (r)
+ virtual unsigned int rank() const
+ {
+ return 2;
+ }
+
+ /// Return the number of coefficients (n)
+ virtual unsigned int num_coefficients() const
+ {
+ return 0;
+ }
+
+ /// Return the number of cell integrals
+ virtual unsigned int num_cell_integrals() const
+ {
+ return 1;
+ }
+
+ /// Return the number of exterior facet integrals
+ virtual unsigned int num_exterior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Return the number of interior facet integrals
+ virtual unsigned int num_interior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Create a new finite element for argument function i
+ virtual ufc::finite_element* create_finite_element(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p2v_0_finite_element_0();
+ break;
+ case 1:
+ return new p2v_0_finite_element_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new dof map for argument function i
+ virtual ufc::dof_map* create_dof_map(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p2v_0_dof_map_0();
+ break;
+ case 1:
+ return new p2v_0_dof_map_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new cell integral on sub domain i
+ virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
+ {
+ return new p2v_0_cell_integral_0();
+ }
+
+ /// Create a new exterior facet integral on sub domain i
+ virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+ /// Create a new interior facet integral on sub domain i
+ virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_0_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_0_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_0_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_1_finite_element_0_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_0_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_0_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_0_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_1_finite_element_0_1();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 12;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.0*y - 1.0;
+
+ // Reset values
+ values[0] = 0;
+ values[1] = 0;
+
+ if (0 <= i && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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 && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[12][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}, {{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[12][1][2] = {{{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[2];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 2; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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[2] = dof_values[1];
+ vertex_values[4] = dof_values[2];
+ // Evaluate at vertices and use affine mapping
+ vertex_values[1] = dof_values[6];
+ vertex_values[3] = dof_values[7];
+ vertex_values[5] = dof_values[8];
+ }
+
+ /// 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 p2v_1_finite_element_0_0();
+ break;
+ case 1:
+ return new p2v_1_finite_element_0_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_1_0: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_1_0() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_1_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_1_finite_element_1_0();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_1_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_1_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_1_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 6;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ *values = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[6][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[6][1] = {{1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[6][1][1] = {{{1}}, {{1}}, {{1}}, {{1}}, {{1}}, {{1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[1];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 1; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 p2v_1_finite_element_1_1();
+ }
+
+};
+
+/// This class defines the interface for a finite element.
+
+class p2v_1_finite_element_1: public ufc::finite_element
+{
+public:
+
+ /// Constructor
+ p2v_1_finite_element_1() : ufc::finite_element()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_finite_element_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the finite element
+ virtual const char* signature() const
+ {
+ return "VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 12;
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.0*y - 1.0;
+
+ // Reset values
+ values[0] = 0;
+ values[1] = 0;
+
+ if (0 <= i && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[0] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // 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];
+
+ // Compute value(s)
+ values[1] = coeff0_0*basisvalue0 + coeff0_1*basisvalue1 + coeff0_2*basisvalue2 + coeff0_3*basisvalue3 + coeff0_4*basisvalue4 + coeff0_5*basisvalue5;
+ }
+
+ }
+
+ /// Evaluate all basis functions at given point in cell
+ virtual void evaluate_basis_all(double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis() is not yet implemented.");
+ }
+
+ /// 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 inverse of Jacobian
+
+ // Get coordinates and map to the reference (UFC) element
+ double x = (element_coordinates[0][1]*element_coordinates[2][0] -\
+ element_coordinates[0][0]*element_coordinates[2][1] +\
+ J_11*coordinates[0] - J_01*coordinates[1]) / detJ;
+ double y = (element_coordinates[1][1]*element_coordinates[0][0] -\
+ element_coordinates[1][0]*element_coordinates[0][1] -\
+ J_10*coordinates[0] + J_00*coordinates[1]) / detJ;
+
+ // Map coordinates to the reference square
+ if (std::abs(y - 1.0) < 1e-14)
+ x = -1.0;
+ else
+ x = 2.0 *x/(1.0 - y) - 1.0;
+ y = 2.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
+ const double Jinv[2][2] = {{J_11 / detJ, -J_01 / detJ}, {-J_10 / detJ, 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 && i <= 5)
+ {
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ if (6 <= i && i <= 11)
+ {
+ // Map degree of freedom to element degree of freedom
+ const unsigned int dof = i - 6;
+
+ // 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);
+
+ // 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;
+
+ // 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.111111111111111*psitilde_bs_0_1 + 1.66666666666667*y*psitilde_bs_0_1 - 0.555555555555556*psitilde_bs_0_0;
+ const double psitilde_bs_1_0 = 1;
+ const double psitilde_bs_1_1 = 2.5*y + 1.5;
+ const double psitilde_bs_2_0 = 1;
+
+ // Compute basisvalues
+ const double basisvalue0 = 0.707106781186548*psitilde_a_0*scalings_y_0*psitilde_bs_0_0;
+ const double basisvalue1 = 1.73205080756888*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.73861278752583*psitilde_a_2*scalings_y_2*psitilde_bs_2_0;
+ const double basisvalue4 = 2.12132034355964*psitilde_a_1*scalings_y_1*psitilde_bs_1_1;
+ const double basisvalue5 = 1.22474487139159*psitilde_a_0*scalings_y_0*psitilde_bs_0_2;
+
+ // Table(s) of coefficients
+ static const double coefficients0[6][6] = \
+ {{0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817},
+ {0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818},
+ {0, 0, 0.2, 0, 0, 0.163299316185545},
+ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0, 0.188561808316413, -0.163299316185545},
+ {0.471404520791032, -0.23094010767585, 0.133333333333333, 0, -0.188561808316413, -0.163299316185545},
+ {0.471404520791032, 0, -0.266666666666667, -0.243432247780074, 0, 0.0544331053951817}};
+
+ // Interesting (new) part
+ // Tables of derivatives of the polynomial base (transpose)
+ static const double dmats0[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {4.89897948556636, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0},
+ {0, 9.48683298050514, 0, 0, 0, 0},
+ {4, 0, 7.07106781186548, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0}};
+
+ static const double dmats1[6][6] = \
+ {{0, 0, 0, 0, 0, 0},
+ {2.44948974278318, 0, 0, 0, 0, 0},
+ {4.24264068711928, 0, 0, 0, 0, 0},
+ {2.58198889747161, 4.74341649025257, -0.912870929175277, 0, 0, 0},
+ {2, 6.12372435695795, 3.53553390593274, 0, 0, 0},
+ {-2.3094010767585, 0, 8.16496580927726, 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;
+
+ // 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;
+
+ // 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];
+
+ // 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;
+
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ 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];
+ }
+
+ }
+ // 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;
+ }
+
+ // 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 and transform
+ for (unsigned int row = 0; row < num_derivatives; row++)
+ {
+ delete [] combinations[row];
+ delete [] transform[row];
+ }
+
+ delete [] combinations;
+ delete [] transform;
+ }
+
+ }
+
+ /// Evaluate order n derivatives of all basis functions at given point in cell
+ virtual void evaluate_basis_derivatives_all(unsigned int n,
+ double* values,
+ const double* coordinates,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("The vectorised version of evaluate_basis_derivatives() is not yet implemented.");
+ }
+
+ /// 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
+ {
+ // The reference points, direction and weights:
+ static const double X[12][1][2] = {{{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}, {{0, 0}}, {{1, 0}}, {{0, 1}}, {{0.5, 0.5}}, {{0, 0.5}}, {{0.5, 0}}};
+ static const double W[12][1] = {{1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}, {1}};
+ static const double D[12][1][2] = {{{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{1, 0}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}, {{0, 1}}};
+
+ const double * const * x = c.coordinates;
+ double result = 0.0;
+ // Iterate over the points:
+ // Evaluate basis functions for affine mapping
+ const double w0 = 1.0 - X[i][0][0] - X[i][0][1];
+ const double w1 = X[i][0][0];
+ const double w2 = X[i][0][1];
+
+ // Compute affine mapping y = F(X)
+ double y[2];
+ y[0] = w0*x[0][0] + w1*x[1][0] + w2*x[2][0];
+ y[1] = w0*x[0][1] + w1*x[1][1] + w2*x[2][1];
+
+ // Evaluate function at physical points
+ double values[2];
+ f.evaluate(values, y, c);
+
+ // Map function values using appropriate mapping
+ // Affine map: Do nothing
+
+ // Note that we do not map the weights (yet).
+
+ // Take directional components
+ for(int k = 0; k < 2; k++)
+ result += values[k]*D[i][0][k];
+ // Multiply by weights
+ result *= W[i][0];
+
+ return result;
+ }
+
+ /// Evaluate linear functionals for all dofs on the function f
+ virtual void evaluate_dofs(double* values,
+ const ufc::function& f,
+ const ufc::cell& c) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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[2] = dof_values[1];
+ vertex_values[4] = dof_values[2];
+ // Evaluate at vertices and use affine mapping
+ vertex_values[1] = dof_values[6];
+ vertex_values[3] = dof_values[7];
+ vertex_values[5] = dof_values[8];
+ }
+
+ /// 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 p2v_1_finite_element_1_0();
+ break;
+ case 1:
+ return new p2v_1_finite_element_1_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_0_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_0_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_0_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_0_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_0_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_0_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_0_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_0_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 false;
+ 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] + 2*m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 12;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 12;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 6;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ offset = offset + m.num_entities[1];
+ dofs[6] = offset + c.entity_indices[0][0];
+ dofs[7] = offset + c.entity_indices[0][1];
+ dofs[8] = offset + c.entity_indices[0][2];
+ offset = offset + m.num_entities[0];
+ dofs[9] = offset + c.entity_indices[1][0];
+ dofs[10] = offset + c.entity_indices[1][1];
+ dofs[11] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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] = 7;
+ dofs[4] = 8;
+ dofs[5] = 9;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ dofs[3] = 6;
+ dofs[4] = 8;
+ dofs[5] = 10;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ dofs[3] = 6;
+ dofs[4] = 7;
+ dofs[5] = 11;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][1];
+ coordinates[6][0] = x[0][0];
+ coordinates[6][1] = x[0][1];
+ coordinates[7][0] = x[1][0];
+ coordinates[7][1] = x[1][1];
+ coordinates[8][0] = x[2][0];
+ coordinates[8][1] = x[2][1];
+ coordinates[9][0] = 0.5*x[1][0] + 0.5*x[2][0];
+ coordinates[9][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[10][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[10][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[11][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[11][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_0_0();
+ break;
+ case 1:
+ return new p2v_1_dof_map_0_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_1_0: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_1_0() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_1_0()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_1_0();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_1_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_1_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_1_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for FiniteElement('Lagrange', Cell('triangle', 1, Space(2)), 2)";
+ }
+
+ /// 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 false;
+ 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] + m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 6;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 6;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 3;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_1_1();
+ }
+
+};
+
+/// This class defines the interface for a local-to-global mapping of
+/// degrees of freedom (dofs).
+
+class p2v_1_dof_map_1: public ufc::dof_map
+{
+private:
+
+ unsigned int __global_dimension;
+
+public:
+
+ /// Constructor
+ p2v_1_dof_map_1() : ufc::dof_map()
+ {
+ __global_dimension = 0;
+ }
+
+ /// Destructor
+ virtual ~p2v_1_dof_map_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the dof map
+ virtual const char* signature() const
+ {
+ return "FFC dof map for VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2)";
+ }
+
+ /// 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 false;
+ 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] + 2*m.num_entities[1];
+ 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 for a cell
+ virtual unsigned int local_dimension(const ufc::cell& c) const
+ {
+ return 12;
+ }
+
+ /// Return the maximum dimension of the local finite element function space
+ virtual unsigned int max_local_dimension() const
+ {
+ return 12;
+ }
+
+ // Return the geometric dimension of the coordinates this dof map provides
+ virtual unsigned int geometric_dimension() const
+ {
+ return 2;
+ }
+
+ /// Return the number of dofs on each cell facet
+ virtual unsigned int num_facet_dofs() const
+ {
+ return 6;
+ }
+
+ /// Return the number of dofs associated with each cell entity of dimension d
+ virtual unsigned int num_entity_dofs(unsigned int d) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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 + c.entity_indices[1][0];
+ dofs[4] = offset + c.entity_indices[1][1];
+ dofs[5] = offset + c.entity_indices[1][2];
+ offset = offset + m.num_entities[1];
+ dofs[6] = offset + c.entity_indices[0][0];
+ dofs[7] = offset + c.entity_indices[0][1];
+ dofs[8] = offset + c.entity_indices[0][2];
+ offset = offset + m.num_entities[0];
+ dofs[9] = offset + c.entity_indices[1][0];
+ dofs[10] = offset + c.entity_indices[1][1];
+ dofs[11] = offset + c.entity_indices[1][2];
+ }
+
+ /// 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] = 7;
+ dofs[4] = 8;
+ dofs[5] = 9;
+ break;
+ case 1:
+ dofs[0] = 0;
+ dofs[1] = 2;
+ dofs[2] = 4;
+ dofs[3] = 6;
+ dofs[4] = 8;
+ dofs[5] = 10;
+ break;
+ case 2:
+ dofs[0] = 0;
+ dofs[1] = 1;
+ dofs[2] = 5;
+ dofs[3] = 6;
+ dofs[4] = 7;
+ dofs[5] = 11;
+ break;
+ }
+ }
+
+ /// Tabulate the local-to-local mapping of dofs on entity (d, i)
+ virtual void tabulate_entity_dofs(unsigned int* dofs,
+ unsigned int d, unsigned int i) const
+ {
+ throw std::runtime_error("Not implemented (introduced in UFC v1.1).");
+ }
+
+ /// 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.5*x[1][0] + 0.5*x[2][0];
+ coordinates[3][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[4][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[4][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[5][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[5][1] = 0.5*x[0][1] + 0.5*x[1][1];
+ coordinates[6][0] = x[0][0];
+ coordinates[6][1] = x[0][1];
+ coordinates[7][0] = x[1][0];
+ coordinates[7][1] = x[1][1];
+ coordinates[8][0] = x[2][0];
+ coordinates[8][1] = x[2][1];
+ coordinates[9][0] = 0.5*x[1][0] + 0.5*x[2][0];
+ coordinates[9][1] = 0.5*x[1][1] + 0.5*x[2][1];
+ coordinates[10][0] = 0.5*x[0][0] + 0.5*x[2][0];
+ coordinates[10][1] = 0.5*x[0][1] + 0.5*x[2][1];
+ coordinates[11][0] = 0.5*x[0][0] + 0.5*x[1][0];
+ coordinates[11][1] = 0.5*x[0][1] + 0.5*x[1][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 p2v_1_dof_map_1_0();
+ break;
+ case 1:
+ return new p2v_1_dof_map_1_1();
+ break;
+ }
+ return 0;
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p2v_1_cell_integral_0_quadrature: public ufc::cell_integral
+{
+public:
+
+ /// Constructor
+ p2v_1_cell_integral_0_quadrature() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_cell_integral_0_quadrature()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Extract vertex coordinates
+ const double * const * x = c.coordinates;
+
+ // Compute Jacobian of affine map from reference cell
+ const double J_00 = x[1][0] - x[0][0];
+ const double J_01 = x[2][0] - x[0][0];
+ const double J_10 = x[1][1] - x[0][1];
+ const double J_11 = x[2][1] - x[0][1];
+
+ // Compute determinant of Jacobian
+ double detJ = J_00*J_11 - J_01*J_10;
+
+ // Compute inverse of Jacobian
+
+ // Set scale factor
+ const double det = std::abs(detJ);
+
+
+ // Array of quadrature weights
+ static const double W9[9] = {0.0558144204830443, 0.063678085099885, 0.0193963833059595, 0.0893030727728709, 0.101884936159816, 0.0310342132895351, 0.0558144204830443, 0.063678085099885, 0.0193963833059595};
+ // Quadrature points on the UFC reference element: (0.102717654809626, 0.088587959512704), (0.0665540678391645, 0.409466864440735), (0.0239311322870806, 0.787659461760847), (0.455706020243648, 0.088587959512704), (0.295266567779633, 0.409466864440735), (0.106170269119576, 0.787659461760847), (0.80869438567767, 0.088587959512704), (0.523979067720101, 0.409466864440735), (0.188409405952072, 0.787659461760847)
+
+ // Value of basis functions at quadrature points.
+ static const double FE0_C0[9][6] = \
+ {{0.499278833175498, -0.0816158215904472, -0.072892306371455, 0.0363981897820602, 0.286562341986258, 0.332268763018087},
+ {0.0251290590975511, -0.0576951799472843, -0.0741406382908807, 0.109006741895515, 0.858208263567716, 0.139491753677383},
+ {-0.117413197449647, -0.0227857341019971, 0.453155393641927, 0.0753983311062782, 0.593609805131561, 0.0180354016718773},
+ {-0.0403700664710398, -0.0403700664710398, -0.072892306371455, 0.161480265884159, 0.161480265884159, 0.830671907545216},
+ {-0.120901875682904, -0.120901875682904, -0.0741406382908807, 0.483607502731615, 0.483607502731615, 0.348729384193458},
+ {-0.0836260170297299, -0.0836260170297299, 0.453155393641927, 0.33450406811892, 0.33450406811892, 0.0450885041796933},
+ {-0.0816158215904472, 0.499278833175498, -0.072892306371455, 0.286562341986258, 0.0363981897820602, 0.332268763018087},
+ {-0.0576951799472842, 0.0251290590975512, -0.0741406382908807, 0.858208263567716, 0.109006741895515, 0.139491753677383},
+ {-0.0227857341019971, -0.117413197449647, 0.453155393641927, 0.593609805131561, 0.0753983311062783, 0.0180354016718774}};
+
+ // Array of non-zero columns
+ static const unsigned int nzc1[6] = {6, 7, 8, 9, 10, 11};
+ // Array of non-zero columns
+ static const unsigned int nzc0[6] = {0, 1, 2, 3, 4, 5};
+
+ // Compute element tensor using UFL quadrature representation
+ // Optimisations: ('simplify expressions', True), ('ignore zero tables', True), ('non zero columns', True), ('remove zero terms', True), ('ignore ones', True)
+ // Total number of operations to compute element tensor: 468
+
+ // Loop quadrature points for integral
+ // Number of operations to compute element tensor for following IP loop = 468
+ for (unsigned int ip = 0; ip < 9; ip++)
+ {
+
+ // Function declarations
+ double F0 = 0;
+ double F1 = 0;
+
+ // Total number of operations to compute function values = 24
+ for (unsigned int r = 0; r < 6; r++)
+ {
+ F0 += FE0_C0[ip][r]*w[0][nzc0[r]];
+ F1 += FE0_C0[ip][r]*w[0][nzc1[r]];
+ }// end loop over 'r'
+
+ // Number of operations to compute ip constants: 4
+ // Number of operations: 2
+ const double Gip0 = F0*W9[ip]*det;
+
+ // Number of operations: 2
+ const double Gip1 = F1*W9[ip]*det;
+
+
+ // Number of operations for primary indices: 24
+ for (unsigned int j = 0; j < 6; j++)
+ {
+ // Number of operations to compute entry: 2
+ A[nzc0[j]] += FE0_C0[ip][j]*Gip0;
+ // Number of operations to compute entry: 2
+ A[nzc1[j]] += FE0_C0[ip][j]*Gip1;
+ }// end loop over 'j'
+ }// end loop over 'ip'
+ }
+
+};
+
+/// This class defines the interface for the tabulation of the cell
+/// tensor corresponding to the local contribution to a form from
+/// the integral over a cell.
+
+class p2v_1_cell_integral_0: public ufc::cell_integral
+{
+private:
+
+ p2v_1_cell_integral_0_quadrature integral_0_quadrature;
+
+public:
+
+ /// Constructor
+ p2v_1_cell_integral_0() : ufc::cell_integral()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_1_cell_integral_0()
+ {
+ // Do nothing
+ }
+
+ /// Tabulate the tensor for the contribution from a local cell
+ virtual void tabulate_tensor(double* A,
+ const double * const * w,
+ const ufc::cell& c) const
+ {
+ // Reset values of the element tensor block
+ for (unsigned int j = 0; j < 12; j++)
+ A[j] = 0;
+
+ // Add all contributions to element tensor
+ integral_0_quadrature.tabulate_tensor(A, w, c);
+ }
+
+};
+
+/// This class defines the interface for the assembly of the global
+/// tensor corresponding to a form with r + n arguments, that is, a
+/// mapping
+///
+/// a : V1 x V2 x ... Vr x W1 x W2 x ... x Wn -> R
+///
+/// with arguments v1, v2, ..., vr, w1, w2, ..., wn. The rank r
+/// global tensor A is defined by
+///
+/// A = a(V1, V2, ..., Vr, w1, w2, ..., wn),
+///
+/// where each argument Vj represents the application to the
+/// sequence of basis functions of Vj and w1, w2, ..., wn are given
+/// fixed functions (coefficients).
+
+class p2v_form_1: public ufc::form
+{
+public:
+
+ /// Constructor
+ p2v_form_1() : ufc::form()
+ {
+ // Do nothing
+ }
+
+ /// Destructor
+ virtual ~p2v_form_1()
+ {
+ // Do nothing
+ }
+
+ /// Return a string identifying the form
+ virtual const char* signature() const
+ {
+ return "Form([Integral(IndexSum(Product(Indexed(BasisFunction(VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2), 0), MultiIndex((Index(0),), {Index(0): 2})), Indexed(Function(VectorElement('Lagrange', Cell('triangle', 1, Space(2)), 2, 2), 0), MultiIndex((Index(0),), {Index(0): 2}))), MultiIndex((Index(0),), {Index(0): 2})), Measure('cell', 0, None))])";
+ }
+
+ /// Return the rank of the global tensor (r)
+ virtual unsigned int rank() const
+ {
+ return 1;
+ }
+
+ /// Return the number of coefficients (n)
+ virtual unsigned int num_coefficients() const
+ {
+ return 1;
+ }
+
+ /// Return the number of cell integrals
+ virtual unsigned int num_cell_integrals() const
+ {
+ return 1;
+ }
+
+ /// Return the number of exterior facet integrals
+ virtual unsigned int num_exterior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Return the number of interior facet integrals
+ virtual unsigned int num_interior_facet_integrals() const
+ {
+ return 0;
+ }
+
+ /// Create a new finite element for argument function i
+ virtual ufc::finite_element* create_finite_element(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p2v_1_finite_element_0();
+ break;
+ case 1:
+ return new p2v_1_finite_element_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new dof map for argument function i
+ virtual ufc::dof_map* create_dof_map(unsigned int i) const
+ {
+ switch ( i )
+ {
+ case 0:
+ return new p2v_1_dof_map_0();
+ break;
+ case 1:
+ return new p2v_1_dof_map_1();
+ break;
+ }
+ return 0;
+ }
+
+ /// Create a new cell integral on sub domain i
+ virtual ufc::cell_integral* create_cell_integral(unsigned int i) const
+ {
+ return new p2v_1_cell_integral_0();
+ }
+
+ /// Create a new exterior facet integral on sub domain i
+ virtual ufc::exterior_facet_integral* create_exterior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+ /// Create a new interior facet integral on sub domain i
+ virtual ufc::interior_facet_integral* create_interior_facet_integral(unsigned int i) const
+ {
+ return 0;
+ }
+
+};
+
+// DOLFIN wrappers
+
+// Standard library includes
+#include <string>
+
+// DOLFIN includes
+#include <dolfin/common/NoDeleter.h>
+#include <dolfin/fem/FiniteElement.h>
+#include <dolfin/fem/DofMap.h>
+#include <dolfin/fem/Form.h>
+#include <dolfin/function/FunctionSpace.h>
+#include <dolfin/function/GenericFunction.h>
+#include <dolfin/function/CoefficientAssigner.h>
+
+namespace P2v
+{
+
+class CoefficientSpace_f: public dolfin::FunctionSpace
+{
+public:
+
+ CoefficientSpace_f(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ CoefficientSpace_f(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~CoefficientSpace_f()
+ {
+ }
+
+};
+
+class Form_0_FunctionSpace_0: public dolfin::FunctionSpace
+{
+public:
+
+ Form_0_FunctionSpace_0(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_0(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_0_FunctionSpace_0()
+ {
+ }
+
+};
+
+class Form_0_FunctionSpace_1: public dolfin::FunctionSpace
+{
+public:
+
+ Form_0_FunctionSpace_1(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_1()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_0_FunctionSpace_1(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_0_finite_element_1()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_0_dof_map_1()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_0_FunctionSpace_1()
+ {
+ }
+
+};
+
+class Form_0: public dolfin::Form
+{
+public:
+
+ // Constructor
+ Form_0(const dolfin::FunctionSpace& V0, const dolfin::FunctionSpace& V1):
+ dolfin::Form(2, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+ _function_spaces[1] = reference_to_no_delete_pointer(V1);
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_0());
+ }
+
+ // Constructor
+ Form_0(boost::shared_ptr<const dolfin::FunctionSpace> V0, boost::shared_ptr<const dolfin::FunctionSpace> V1):
+ dolfin::Form(2, 0)
+ {
+ _function_spaces[0] = V0;
+ _function_spaces[1] = V1;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_0());
+ }
+
+ // Destructor
+ ~Form_0()
+ {}
+
+ /// Return the number of the coefficient with this name
+ virtual dolfin::uint coefficient_number(const std::string& name) const
+ {
+
+ dolfin::error("No coefficients.");
+ return 0;
+ }
+
+ /// Return the name of the coefficient with this number
+ virtual std::string coefficient_name(dolfin::uint i) const
+ {
+
+ dolfin::error("No coefficients.");
+ return "unnamed";
+ }
+
+ // Typedefs
+ typedef Form_0_FunctionSpace_0 TestSpace;
+ typedef Form_0_FunctionSpace_1 TrialSpace;
+
+ // Coefficients
+};
+
+class Form_1_FunctionSpace_0: public dolfin::FunctionSpace
+{
+public:
+
+ Form_1_FunctionSpace_0(const dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(dolfin::Mesh& mesh):
+ dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh),
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_0()), mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(boost::shared_ptr<dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+ Form_1_FunctionSpace_0(boost::shared_ptr<const dolfin::Mesh> mesh):
+ dolfin::FunctionSpace(mesh,
+ boost::shared_ptr<const dolfin::FiniteElement>(new dolfin::FiniteElement(boost::shared_ptr<ufc::finite_element>(new p2v_1_finite_element_0()))),
+ boost::shared_ptr<const dolfin::DofMap>(new dolfin::DofMap(boost::shared_ptr<ufc::dof_map>(new p2v_1_dof_map_0()), *mesh)))
+ {
+ // Do nothing
+ }
+
+
+ ~Form_1_FunctionSpace_0()
+ {
+ }
+
+};
+
+typedef CoefficientSpace_f Form_1_FunctionSpace_1;
+
+class Form_1: public dolfin::Form
+{
+public:
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0, const dolfin::GenericFunction& f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ this->f = f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Constructor
+ Form_1(const dolfin::FunctionSpace& V0, boost::shared_ptr<const dolfin::GenericFunction> f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = reference_to_no_delete_pointer(V0);
+
+ this->f = *f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0, const dolfin::GenericFunction& f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ this->f = f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Constructor
+ Form_1(boost::shared_ptr<const dolfin::FunctionSpace> V0, boost::shared_ptr<const dolfin::GenericFunction> f):
+ dolfin::Form(1, 1), f(*this, 0)
+ {
+ _function_spaces[0] = V0;
+
+ this->f = *f;
+
+ _ufc_form = boost::shared_ptr<const ufc::form>(new p2v_form_1());
+ }
+
+ // Destructor
+ ~Form_1()
+ {}
+
+ /// Return the number of the coefficient with this name
+ virtual dolfin::uint coefficient_number(const std::string& name) const
+ {
+ if (name == "f")
+ return 0;
+
+ dolfin::error("Invalid coefficient.");
+ return 0;
+ }
+
+ /// Return the name of the coefficient with this number
+ virtual std::string coefficient_name(dolfin::uint i) const
+ {
+ switch (i)
+ {
+ case 0:
+ return "f";
+ }
+
+ dolfin::error("Invalid coefficient.");
+ return "unnamed";
+ }
+
+ // Typedefs
+ typedef Form_1_FunctionSpace_0 TestSpace;
+ typedef Form_1_FunctionSpace_1 CoefficientSpace_f;
+
+ // Coefficients
+ dolfin::CoefficientAssigner f;
+};
+
+// Class typedefs
+typedef Form_0 BilinearForm;
+typedef Form_1 LinearForm;
+typedef Form_0::TestSpace FunctionSpace;
+
+} // namespace P2v
+
+#endif
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/P2v.ufl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/MADDs-5/MADDs-5a/cpp/P2v.ufl Wed Dec 09 23:17:37 2009 -0500
@@ -0,0 +1,21 @@
+# Copyright (C) 2009 Marc Spiegelman
+# Licensed under the GNU LGPL Version 2.1.
+#
+# First added: 10 Jul 2009 12:46:10
+# Last changed: 10 Jul 2009 12:46:18
+#
+# Function Space definitions for linear triangles
+#
+# Compile this form with FFC: ffc -l dolfin -O P1.ufl
+
+P2v = VectorElement("Lagrange", triangle, 2)
+
+u = TrialFunction(P2v)
+v = TestFunction(P2v)
+f = Function(P2v)
+
+L = inner(v,f)*dx
+a = inner(v,u)*dx
+
+
+
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/forms/MagmaEquations_P2.ufl
--- a/MADDs-5/MADDs-5a/cpp/forms/MagmaEquations_P2.ufl Wed Dec 09 11:40:33 2009 -0500
+++ b/MADDs-5/MADDs-5a/cpp/forms/MagmaEquations_P2.ufl Wed Dec 09 23:17:37 2009 -0500
@@ -54,8 +54,8 @@ zero = 0.
zero = 0.
# permeability function
-K = (f+eps)**2 # regularized
-K0 = f**2 # not regularized
+K = (f+eps)*(f+eps) # regularized
+K0 = f*f # not regularized
# bulk viscosity function
Xi = hsquared*iEta*(f+eps)
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/forms/MeltFlux_P2.ufl
--- a/MADDs-5/MADDs-5a/cpp/forms/MeltFlux_P2.ufl Wed Dec 09 11:40:33 2009 -0500
+++ b/MADDs-5/MADDs-5a/cpp/forms/MeltFlux_P2.ufl Wed Dec 09 23:17:37 2009 -0500
@@ -44,8 +44,8 @@ V = Function(VP2)
# regularized permeability function
eps = Constant(triangle)
zero = 0.
-K = (f+eps)**2
-K0 = f**2
+K = (f+eps)*(f+eps)
+K0 = f*f
# define new BDM function spaces
diff -r 0b40db868a4f -r 6016b892ddd6 MADDs-5/MADDs-5a/cpp/main.cpp
--- a/MADDs-5/MADDs-5a/cpp/main.cpp Wed Dec 09 11:40:33 2009 -0500
+++ b/MADDs-5/MADDs-5a/cpp/main.cpp Wed Dec 09 23:17:37 2009 -0500
@@ -18,6 +18,8 @@
#include <math.h>
#include <string.h>
#include "Stokes_P2P1.h"
+#include "P2v.h"
+#include "P1.h"
#include "MagmaEquations.h"
#include "SemiLagrangianRHS.h"
#include "Projection.h"
@@ -315,11 +317,13 @@ int main(int argc, char* argv[])
mesh.init();
mesh.order();
- //Set function spaces for Stokes solutions (this may be broken)
- Stokes_P2P1::FunctionSpace W(mesh);
- SubSpace W0(W, 0); //velocity
- SubSpace W01(W0,1); //vertical velocity
- SubSpace W1(W, 1); //pressure
+ //Set function spaces for Stokes solutions (this should work but is broken)
+ // Stokes_P2P1::FunctionSpace W(mesh);
+ // SubSpace W0(W, 0); //velocity
+ // SubSpace W01(W0,1); //vertical velocity
+ // SubSpace W1(W, 1); //pressure
+ P2v::FunctionSpace W0(mesh);
+ P1::FunctionSpace W1(mesh);
//set FunctionSpace for PressurePorosity
MagmaEquations::FunctionSpace V(mesh);
@@ -457,13 +461,17 @@ int main(int argc, char* argv[])
// IO
File Vfile("Velocity.pvd","compressed");
+ File Pfile("Pressure.pvd","compressed");
File vfile("MeltFlux.pvd","compressed");
File Gammafile("Gamma.pvd","compressed");
File deltafile("delta.pvd","compressed");
- Function p=u[0], f = u[1];
- Function f0(f.function_space());
- Function delta(f.function_space());
+ File iEtafile("iEta.pvd","compressed");
+ Function p(V[0]), f(V[1]);
+ Function f0(V[1]);
+ Function delta(V[1]);
Vfile << Velocity;
+ Pfile << Pressure;
+ iEtafile << iEta;
Gammafile << Gamma;
@@ -544,8 +552,8 @@ int main(int argc, char* argv[])
//calculate melt flux
p = u[0];
f = u[1];
- Lm.p = p;
- Lm.f = f;
+ Lm.p = u[0];
+ Lm.f = u[1];
qmelt.solve(melt_flux);
FindMaxMeltVelocity(max_mag_v, melt_flux, f, U0onw0, epsilon);
dt_check = std::min(delta_t0, cfl*dh/max_mag_v);
More information about the CIG-COMMITS
mailing list