// This code conforms with the UFC specification version 1.5.0 // and was automatically generated by FFC version 1.5.0. // // This code was generated with the option '-l dolfin' and // contains DOLFIN-specific wrappers that depend on DOLFIN. // // This code was generated with the following parameters: // // cache_dir: '' // convert_exceptions_to_warnings: False // cpp_optimize: True // cpp_optimize_flags: '-O2' // epsilon: 1e-14 // error_control: False // form_postfix: True // format: 'dolfin' // log_level: 20 // log_prefix: '' // optimize: True // output_dir: '.' // precision: 15 // quadrature_degree: 'auto' // quadrature_rule: 'auto' // representation: 'auto' // restrict_keyword: '' // split: False #ifndef __MTH_H #define __MTH_H #include #include #include #include /// This class defines the interface for a finite element. class mth_finite_element_0: public ufc::finite_element { public: /// Constructor mth_finite_element_0() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_0() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 3; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 0; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { return 1; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values *values = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values = 0.0; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 3; r++) { _evaluate_basis(r, &dof_values, x, vertex_coordinates, cell_orientation); values[r] = dof_values; } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[2][1]; for (unsigned int row = 0; row < 2; row++) { for (unsigned int col = 0; col < 1; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[2][2]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 3; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Helper variable to hold values of a single dof. double dof_values[2]; for (unsigned int r = 0; r < 2; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 3; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0]; vertex_values[1] = dof_values[1]; vertex_values[2] = dof_values[2]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const { return 0; } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_0(); } }; /// This class defines the interface for a finite element. class mth_finite_element_1: public ufc::finite_element { public: /// Constructor mth_finite_element_1() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_1() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "VectorElement('Lagrange', Domain(Cell('triangle', 2)), 1, 2, None)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 6; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 1; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { switch (i) { case 0: { return 2; break; } } return 0; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values values[0] = 0.0; values[1] = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values[2] = {0.0, 0.0}; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 6; r++) { _evaluate_basis(r, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 2; s++) { values[r*2 + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < 2*num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[2][1]; for (unsigned int row = 0; row < 2; row++) { for (unsigned int col = 0; col < 1; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[2][2]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 6; r++) { for (unsigned int s = 0; s < 2*num_derivatives; s++) { values[r*2*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Helper variable to hold values of a single dof. double dof_values[4]; for (unsigned int r = 0; r < 4; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 6; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 2*num_derivatives; s++) { values[r*2*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[2]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 3: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[1]; break; } case 4: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[1]; break; } case 5: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[2]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[3] = vals[1]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[4] = vals[1]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[5] = vals[1]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0]; vertex_values[2] = dof_values[1]; vertex_values[4] = dof_values[2]; // Evaluate function and change variables vertex_values[1] = dof_values[3]; vertex_values[3] = dof_values[4]; vertex_values[5] = dof_values[5]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t 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(std::size_t i) const { switch (i) { case 0: { return new mth_finite_element_0(); break; } case 1: { return new mth_finite_element_0(); break; } } return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_1(); } }; /// This class defines the interface for a finite element. class mth_finite_element_2: public ufc::finite_element { public: /// Constructor mth_finite_element_2() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_2() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 2, None)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 6; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 0; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { return 1; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values *values = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values = 0.0; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 6; r++) { _evaluate_basis(r, &dof_values, x, vertex_coordinates, cell_orientation); values[r] = dof_values; } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[4][2]; for (unsigned int row = 0; row < 4; row++) { for (unsigned int col = 0; col < 2; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[4][4]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 6; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Helper variable to hold values of a single dof. double dof_values[4]; for (unsigned int r = 0; r < 4; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 6; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 3: { y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 4: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 5: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[3] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[4] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); values[5] = vals[0]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0]; vertex_values[1] = dof_values[1]; vertex_values[2] = dof_values[2]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const { return 0; } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_2(); } }; /// This class defines the interface for a finite element. class mth_finite_element_3: public ufc::finite_element { public: /// Constructor mth_finite_element_3() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_3() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "VectorElement('Lagrange', Domain(Cell('triangle', 2)), 2, 2, None)"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 12; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 1; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { switch (i) { case 0: { return 2; break; } } return 0; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values values[0] = 0.0; values[1] = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 6: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 7: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 8: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 9: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 10: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 11: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values[2] = {0.0, 0.0}; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 12; r++) { _evaluate_basis(r, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 2; s++) { values[r*2 + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < 2*num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[4][2]; for (unsigned int row = 0; row < 4; row++) { for (unsigned int col = 0; col < 2; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[4][4]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 6: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 7: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 8: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 9: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 10: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 11: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 12; r++) { for (unsigned int s = 0; s < 2*num_derivatives; s++) { values[r*2*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Helper variable to hold values of a single dof. double dof_values[8]; for (unsigned int r = 0; r < 8; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 12; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 2*num_derivatives; s++) { values[r*2*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[2]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 3: { y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 4: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 5: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 6: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[1]; break; } case 7: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[1]; break; } case 8: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 9: { y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 10: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 11: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[1]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[2]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[3] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[4] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); values[5] = vals[0]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[6] = vals[1]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[7] = vals[1]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[8] = vals[1]; y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[9] = vals[1]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[10] = vals[1]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); values[11] = vals[1]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0]; vertex_values[2] = dof_values[1]; vertex_values[4] = dof_values[2]; // Evaluate function and change variables vertex_values[1] = dof_values[6]; vertex_values[3] = dof_values[7]; vertex_values[5] = dof_values[8]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t 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(std::size_t i) const { switch (i) { case 0: { return new mth_finite_element_2(); break; } case 1: { return new mth_finite_element_2(); break; } } return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_3(); } }; /// This class defines the interface for a finite element. class mth_finite_element_4: public ufc::finite_element { public: /// Constructor mth_finite_element_4() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_4() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "EnrichedElement(FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None), FiniteElement('Discontinuous Lagrange', Domain(Cell('triangle', 2)), 0, None))"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 4; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 0; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { return 1; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values *values = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[1] = {0.0}; // Declare helper variables // Compute basisvalues basisvalues[0] = 1.0; // Table(s) of coefficients static const double coefficients0[1] = \ {1.0}; // Compute value(s) for (unsigned int r = 0; r < 1; r++) { *values += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values = 0.0; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 4; r++) { _evaluate_basis(r, &dof_values, x, vertex_coordinates, cell_orientation); values[r] = dof_values; } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[2][1]; for (unsigned int row = 0; row < 2; row++) { for (unsigned int col = 0; col < 1; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[2][2]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[1] = {0.0}; // Declare helper variables // Compute basisvalues basisvalues[0] = 1.0; // Table(s) of coefficients static const double coefficients0[1] = \ {1.0}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[1][1] = \ {{0.0}}; static const double dmats1[1][1] = \ {{0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[2]; for (unsigned int r = 0; r < 2; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[1][1] = \ {{1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[1][1] = \ {{1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { for (unsigned int tu = 0; tu < 1; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { for (unsigned int tu = 0; tu < 1; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 1; s++) { for (unsigned int t = 0; t < 1; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 4; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 1) { return ; } // Helper variable to hold values of a single dof. double dof_values[2]; for (unsigned int r = 0; r < 2; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 4; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < num_derivatives; s++) { values[r*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 3: { y[0] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; y[1] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[1]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; y[0] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; y[1] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; f.evaluate(vals, y, c); values[3] = vals[0]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0] + dof_values[3]; vertex_values[1] = dof_values[1] + dof_values[3]; vertex_values[2] = dof_values[2] + dof_values[3]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t num_sub_elements() const { return 0; } /// Create a new finite element for sub element i (for a mixed element) virtual ufc::finite_element* create_sub_element(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_4(); } }; /// This class defines the interface for a finite element. class mth_finite_element_5: public ufc::finite_element { public: /// Constructor mth_finite_element_5() : ufc::finite_element() { // Do nothing } /// Destructor virtual ~mth_finite_element_5() { // Do nothing } /// Return a string identifying the finite element virtual const char* signature() const { return "MixedElement(VectorElement('Lagrange', Domain(Cell('triangle', 2)), 2, 2, None), EnrichedElement(FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None), FiniteElement('Discontinuous Lagrange', Domain(Cell('triangle', 2)), 0, None)), **{'value_shape': (3,) })"; } /// Return the cell shape virtual ufc::shape cell_shape() const { return ufc::triangle; } /// Return the topological dimension of the cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the finite element function space virtual std::size_t space_dimension() const { return 16; } /// Return the rank of the value space virtual std::size_t value_rank() const { return 1; } /// Return the dimension of the value space for axis i virtual std::size_t value_dimension(std::size_t i) const { switch (i) { case 0: { return 3; break; } } return 0; } /// Evaluate basis function i at given point x in cell (actual implementation) static void _evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Reset values values[0] = 0.0; values[1] = 0.0; values[2] = 0.0; switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[0] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 6: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 7: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 8: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 9: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 10: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 11: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Compute value(s) for (unsigned int r = 0; r < 6; r++) { values[1] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 12: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[2] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 13: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[2] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 14: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Compute value(s) for (unsigned int r = 0; r < 3; r++) { values[2] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } case 15: { // Array of basisvalues double basisvalues[1] = {0.0}; // Declare helper variables // Compute basisvalues basisvalues[0] = 1.0; // Table(s) of coefficients static const double coefficients0[1] = \ {1.0}; // Compute value(s) for (unsigned int r = 0; r < 1; r++) { values[2] += coefficients0[r]*basisvalues[r]; } // end loop over 'r' break; } } } /// Evaluate basis function i at given point x in cell (non-static member function) virtual void evaluate_basis(std::size_t i, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); } /// Evaluate all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Helper variable to hold values of a single dof. double dof_values[3] = {0.0, 0.0, 0.0}; // Loop dofs and call evaluate_basis for (unsigned int r = 0; r < 16; r++) { _evaluate_basis(r, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 3; s++) { values[r*3 + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_all(double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of basis function i at given point x in cell (actual implementation) static void _evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Reset values. Assuming that values is always an array. for (unsigned int r = 0; r < 3*num_derivatives; r++) { values[r] = 0.0; } // end loop over 'r' // Call evaluate_basis if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis(i, values, x, vertex_coordinates, cell_orientation); return ; } // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Compute constants const double C0 = vertex_coordinates[2] + vertex_coordinates[4]; const double C1 = vertex_coordinates[3] + vertex_coordinates[5]; // Get coordinates and map to the reference (FIAT) element double X = (J[1]*(C1 - 2.0*x[1]) + J[3]*(2.0*x[0] - C0)) / detJ; double Y = (J[0]*(2.0*x[1] - C1) + J[2]*(C0 - 2.0*x[0])) / detJ; // Declare two dimensional array that holds combinations of derivatives and initialise unsigned int combinations[4][2]; for (unsigned int row = 0; row < 4; row++) { for (unsigned int col = 0; col < 2; col++) combinations[row][col] = 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] = {{K[0], K[1]}, {K[2], K[3]}}; // Declare transformation matrix // Declare pointer to two dimensional array and initialise double transform[4][4]; for (unsigned int j = 0; j < num_derivatives; j++) { 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]]; } } switch (i) { case 0: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 1: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 2: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 3: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 4: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 5: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 6: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, -0.173205080756888, -0.1, 0.121716123890037, 0.0942809041582064, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 7: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.173205080756888, -0.1, 0.121716123890037, -0.0942809041582063, 0.0544331053951818}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 8: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.0, 0.0, 0.2, 0.0, 0.0, 0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 9: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.23094010767585, 0.133333333333333, 0.0, 0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 10: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791031, -0.23094010767585, 0.133333333333333, 0.0, -0.188561808316413, -0.163299316185545}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 11: { // Array of basisvalues double basisvalues[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; double tmp1 = (1.0 - Y)/2.0; double tmp2 = tmp1*tmp1; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[3] = basisvalues[1]*1.5*tmp0 - basisvalues[0]*0.5*tmp2; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[4] = basisvalues[1]*(1.5 + 2.5*Y); basisvalues[5] = basisvalues[2]*(0.111111111111111 + Y*1.66666666666667) - basisvalues[0]*0.555555555555556; basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[5] *= std::sqrt(1.5); basisvalues[1] *= std::sqrt(3.0); basisvalues[4] *= std::sqrt(4.5); basisvalues[3] *= std::sqrt(7.5); // Table(s) of coefficients static const double coefficients0[6] = \ {0.471404520791032, 0.0, -0.266666666666667, -0.243432247780074, 0.0, 0.0544331053951817}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 9.48683298050515, 0.0, 0.0, 0.0, 0.0}, {3.99999999999999, 0.0, 7.07106781186547, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}}; static const double dmats1[6][6] = \ {{0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0, 0.0, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0, 0.0, 0.0, 0.0}, {2.58198889747162, 4.74341649025257, -0.912870929175279, 0.0, 0.0, 0.0}, {1.99999999999991, 6.12372435695794, 3.53553390593273, 0.0, 0.0, 0.0}, {-2.30940107675849, 0.0, 8.16496580927727, 0.0, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[6][6] = \ {{1.0, 0.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 1.0, 0.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 1.0, 0.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 1.0, 0.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 1.0, 0.0}, {0.0, 0.0, 0.0, 0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 6; t++) { for (unsigned int u = 0; u < 6; u++) { for (unsigned int tu = 0; tu < 6; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 6; s++) { for (unsigned int t = 0; t < 6; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 12: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, -0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[2*num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 13: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.288675134594813, -0.166666666666667}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[2*num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 14: { // Array of basisvalues double basisvalues[3] = {0.0, 0.0, 0.0}; // Declare helper variables double tmp0 = (1.0 + Y + 2.0*X)/2.0; // Compute basisvalues basisvalues[0] = 1.0; basisvalues[1] = tmp0; basisvalues[2] = basisvalues[0]*(0.5 + 1.5*Y); basisvalues[0] *= std::sqrt(0.5); basisvalues[2] *= std::sqrt(1.0); basisvalues[1] *= std::sqrt(3.0); // Table(s) of coefficients static const double coefficients0[3] = \ {0.471404520791032, 0.0, 0.333333333333333}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[3][3] = \ {{0.0, 0.0, 0.0}, {4.89897948556635, 0.0, 0.0}, {0.0, 0.0, 0.0}}; static const double dmats1[3][3] = \ {{0.0, 0.0, 0.0}, {2.44948974278318, 0.0, 0.0}, {4.24264068711928, 0.0, 0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[3][3] = \ {{1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 3; t++) { for (unsigned int u = 0; u < 3; u++) { for (unsigned int tu = 0; tu < 3; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 3; s++) { for (unsigned int t = 0; t < 3; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[2*num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } case 15: { // Array of basisvalues double basisvalues[1] = {0.0}; // Declare helper variables // Compute basisvalues basisvalues[0] = 1.0; // Table(s) of coefficients static const double coefficients0[1] = \ {1.0}; // Tables of derivatives of the polynomial base (transpose). static const double dmats0[1][1] = \ {{0.0}}; static const double dmats1[1][1] = \ {{0.0}}; // Compute reference derivatives. // Declare array of derivatives on FIAT element. double derivatives[4]; for (unsigned int r = 0; r < 4; r++) { derivatives[r] = 0.0; } // end loop over 'r' // Declare derivative matrix (of polynomial basis). double dmats[1][1] = \ {{1.0}}; // Declare (auxiliary) derivative matrix (of polynomial basis). double dmats_old[1][1] = \ {{1.0}}; // Loop possible derivatives. for (unsigned int r = 0; r < num_derivatives; r++) { // Resetting dmats values to compute next derivative. for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { dmats[t][u] = 0.0; if (t == u) { dmats[t][u] = 1.0; } } // end loop over 'u' } // end loop over 't' // Looping derivative order to generate dmats. for (unsigned int s = 0; s < n; s++) { // Updating dmats_old with new values and resetting dmats. for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { dmats_old[t][u] = dmats[t][u]; dmats[t][u] = 0.0; } // end loop over 'u' } // end loop over 't' // Update dmats using an inner product. if (combinations[r][s] == 0) { for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { for (unsigned int tu = 0; tu < 1; tu++) { dmats[t][u] += dmats0[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } if (combinations[r][s] == 1) { for (unsigned int t = 0; t < 1; t++) { for (unsigned int u = 0; u < 1; u++) { for (unsigned int tu = 0; tu < 1; tu++) { dmats[t][u] += dmats1[t][tu]*dmats_old[tu][u]; } // end loop over 'tu' } // end loop over 'u' } // end loop over 't' } } // end loop over 's' for (unsigned int s = 0; s < 1; s++) { for (unsigned int t = 0; t < 1; t++) { derivatives[r] += coefficients0[s]*dmats[s][t]*basisvalues[t]; } // end loop over 't' } // end loop over 's' } // end loop over 'r' // Transform derivatives back to physical element for (unsigned int r = 0; r < num_derivatives; r++) { for (unsigned int s = 0; s < num_derivatives; s++) { values[2*num_derivatives + r] += transform[r][s]*derivatives[s]; } // end loop over 's' } // end loop over 'r' break; } } } /// Evaluate order n derivatives of basis function i at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives(std::size_t i, std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives(i, n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate order n derivatives of all basis functions at given point x in cell (actual implementation) static void _evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) { // Call evaluate_basis_all if order of derivatives is equal to zero. if (n == 0) { _evaluate_basis_all(values, x, vertex_coordinates, cell_orientation); return ; } // Compute number of derivatives. unsigned int num_derivatives = 1; for (unsigned int r = 0; r < n; r++) { num_derivatives *= 2; } // end loop over 'r' // Set values equal to zero. for (unsigned int r = 0; r < 16; r++) { for (unsigned int s = 0; s < 3*num_derivatives; s++) { values[r*3*num_derivatives + s] = 0.0; } // end loop over 's' } // end loop over 'r' // If order of derivatives is greater than the maximum polynomial degree, return zeros. if (n > 2) { return ; } // Helper variable to hold values of a single dof. double dof_values[12]; for (unsigned int r = 0; r < 12; r++) { dof_values[r] = 0.0; } // end loop over 'r' // Loop dofs and call evaluate_basis_derivatives. for (unsigned int r = 0; r < 16; r++) { _evaluate_basis_derivatives(r, n, dof_values, x, vertex_coordinates, cell_orientation); for (unsigned int s = 0; s < 3*num_derivatives; s++) { values[r*3*num_derivatives + s] = dof_values[s]; } // end loop over 's' } // end loop over 'r' } /// Evaluate order n derivatives of all basis functions at given point x in cell (non-static member function) virtual void evaluate_basis_derivatives_all(std::size_t n, double* values, const double* x, const double* vertex_coordinates, int cell_orientation) const { _evaluate_basis_derivatives_all(n, values, x, vertex_coordinates, cell_orientation); } /// Evaluate linear functional for dof i on the function f virtual double evaluate_dof(std::size_t i, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[3]; // Declare variable for physical coordinates double y[2]; switch (i) { case 0: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[0]; break; } case 1: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 2: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 3: { y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 4: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[0]; break; } case 5: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[0]; break; } case 6: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[1]; break; } case 7: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[1]; break; } case 8: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 9: { y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 10: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[1]; break; } case 11: { y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[1]; break; } case 12: { y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); return vals[2]; break; } case 13: { y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); return vals[2]; break; } case 14: { y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[2]; break; } case 15: { y[0] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; y[1] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; f.evaluate(vals, y, c); return vals[2]; break; } } return 0.0; } /// Evaluate linear functionals for all dofs on the function f virtual void evaluate_dofs(double* values, const ufc::function& f, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Declare variables for result of evaluation double vals[3]; // Declare variable for physical coordinates double y[2]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[0] = vals[0]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[1] = vals[0]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[2] = vals[0]; y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[3] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[4] = vals[0]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); values[5] = vals[0]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[6] = vals[1]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[7] = vals[1]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[8] = vals[1]; y[0] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[9] = vals[1]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; f.evaluate(vals, y, c); values[10] = vals[1]; y[0] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; y[1] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; f.evaluate(vals, y, c); values[11] = vals[1]; y[0] = vertex_coordinates[0]; y[1] = vertex_coordinates[1]; f.evaluate(vals, y, c); values[12] = vals[2]; y[0] = vertex_coordinates[2]; y[1] = vertex_coordinates[3]; f.evaluate(vals, y, c); values[13] = vals[2]; y[0] = vertex_coordinates[4]; y[1] = vertex_coordinates[5]; f.evaluate(vals, y, c); values[14] = vals[2]; y[0] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; y[1] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; f.evaluate(vals, y, c); values[15] = vals[2]; } /// Interpolate vertex values from dof values virtual void interpolate_vertex_values(double* vertex_values, const double* dof_values, const double* vertex_coordinates, int cell_orientation, const ufc::cell& c) const { // Evaluate function and change variables vertex_values[0] = dof_values[0]; vertex_values[3] = dof_values[1]; vertex_values[6] = dof_values[2]; // Evaluate function and change variables vertex_values[1] = dof_values[6]; vertex_values[4] = dof_values[7]; vertex_values[7] = dof_values[8]; // Evaluate function and change variables vertex_values[2] = dof_values[12] + dof_values[15]; vertex_values[5] = dof_values[13] + dof_values[15]; vertex_values[8] = dof_values[14] + dof_values[15]; } /// Map coordinate xhat from reference cell to coordinate x in cell virtual void map_from_reference_cell(double* x, const double* xhat, const ufc::cell& c) const { throw std::runtime_error("map_from_reference_cell not yet implemented."); } /// Map from coordinate x in cell to coordinate xhat in reference cell virtual void map_to_reference_cell(double* xhat, const double* x, const ufc::cell& c) const { throw std::runtime_error("map_to_reference_cell not yet implemented."); } /// Return the number of sub elements (for a mixed element) virtual std::size_t 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(std::size_t i) const { switch (i) { case 0: { return new mth_finite_element_3(); break; } case 1: { return new mth_finite_element_4(); break; } } return 0; } /// Create a new class instance virtual ufc::finite_element* create() const { return new mth_finite_element_5(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_0: public ufc::dofmap { public: /// Constructor mth_dofmap_0() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_0() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return false; break; } case 2: { return false; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return num_global_entities[0]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 3; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 2; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 1; break; } case 1: { return 0; break; } case 2: { return 0; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, 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(std::size_t* dofs, std::size_t 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(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; break; } case 1: { dofs[0] = 1; break; } case 2: { dofs[0] = 2; break; } } break; } case 1: { break; } case 2: { break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 0; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_0(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_1: public ufc::dofmap { public: /// Constructor mth_dofmap_1() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_1() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for VectorElement('Lagrange', Domain(Cell('triangle', 2)), 1, 2, None)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return false; break; } case 2: { return false; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return 2*num_global_entities[0]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 6; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 4; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 2; break; } case 1: { return 0; break; } case 2: { return 0; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { unsigned int offset = 0; dofs[0] = offset + c.entity_indices[0][0]; dofs[1] = offset + c.entity_indices[0][1]; dofs[2] = offset + c.entity_indices[0][2]; offset += num_global_entities[0]; dofs[3] = offset + c.entity_indices[0][0]; dofs[4] = offset + c.entity_indices[0][1]; dofs[5] = offset + c.entity_indices[0][2]; offset += num_global_entities[0]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const { switch (facet) { case 0: { dofs[0] = 1; dofs[1] = 2; dofs[2] = 4; dofs[3] = 5; break; } case 1: { dofs[0] = 0; dofs[1] = 2; dofs[2] = 3; dofs[3] = 5; break; } case 2: { dofs[0] = 0; dofs[1] = 1; dofs[2] = 3; dofs[3] = 4; break; } } } /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; dofs[1] = 3; break; } case 1: { dofs[0] = 1; dofs[1] = 4; break; } case 2: { dofs[0] = 2; dofs[1] = 5; break; } } break; } case 1: { break; } case 2: { break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; dof_coordinates[6] = vertex_coordinates[0]; dof_coordinates[7] = vertex_coordinates[1]; dof_coordinates[8] = vertex_coordinates[2]; dof_coordinates[9] = vertex_coordinates[3]; dof_coordinates[10] = vertex_coordinates[4]; dof_coordinates[11] = vertex_coordinates[5]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 2; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { switch (i) { case 0: { return new mth_dofmap_0(); break; } case 1: { return new mth_dofmap_0(); break; } } return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_1(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_2: public ufc::dofmap { public: /// Constructor mth_dofmap_2() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_2() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 2, None)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return true; break; } case 2: { return false; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return num_global_entities[0] + num_global_entities[1]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 6; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 3; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 1; break; } case 1: { return 1; break; } case 2: { return 0; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { unsigned int offset = 0; dofs[0] = offset + c.entity_indices[0][0]; dofs[1] = offset + c.entity_indices[0][1]; dofs[2] = offset + c.entity_indices[0][2]; offset += num_global_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 += num_global_entities[1]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t 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(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; break; } case 1: { dofs[0] = 1; break; } case 2: { dofs[0] = 2; break; } } break; } case 1: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 3; break; } case 1: { dofs[0] = 4; break; } case 2: { dofs[0] = 5; break; } } break; } case 2: { break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; dof_coordinates[6] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; dof_coordinates[7] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; dof_coordinates[8] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; dof_coordinates[9] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; dof_coordinates[10] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; dof_coordinates[11] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 0; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_2(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_3: public ufc::dofmap { public: /// Constructor mth_dofmap_3() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_3() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for VectorElement('Lagrange', Domain(Cell('triangle', 2)), 2, 2, None)"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return true; break; } case 2: { return false; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return 2*num_global_entities[0] + 2*num_global_entities[1]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 12; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 6; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 2; break; } case 1: { return 2; break; } case 2: { return 0; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { unsigned int offset = 0; dofs[0] = offset + c.entity_indices[0][0]; dofs[1] = offset + c.entity_indices[0][1]; dofs[2] = offset + c.entity_indices[0][2]; offset += num_global_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 += num_global_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 += num_global_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]; offset += num_global_entities[1]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t 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(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; dofs[1] = 6; break; } case 1: { dofs[0] = 1; dofs[1] = 7; break; } case 2: { dofs[0] = 2; dofs[1] = 8; break; } } break; } case 1: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 3; dofs[1] = 9; break; } case 1: { dofs[0] = 4; dofs[1] = 10; break; } case 2: { dofs[0] = 5; dofs[1] = 11; break; } } break; } case 2: { break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; dof_coordinates[6] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; dof_coordinates[7] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; dof_coordinates[8] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; dof_coordinates[9] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; dof_coordinates[10] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; dof_coordinates[11] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; dof_coordinates[12] = vertex_coordinates[0]; dof_coordinates[13] = vertex_coordinates[1]; dof_coordinates[14] = vertex_coordinates[2]; dof_coordinates[15] = vertex_coordinates[3]; dof_coordinates[16] = vertex_coordinates[4]; dof_coordinates[17] = vertex_coordinates[5]; dof_coordinates[18] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; dof_coordinates[19] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; dof_coordinates[20] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; dof_coordinates[21] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; dof_coordinates[22] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; dof_coordinates[23] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 2; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { switch (i) { case 0: { return new mth_dofmap_2(); break; } case 1: { return new mth_dofmap_2(); break; } } return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_3(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_4: public ufc::dofmap { public: /// Constructor mth_dofmap_4() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_4() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for EnrichedElement(FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None), FiniteElement('Discontinuous Lagrange', Domain(Cell('triangle', 2)), 0, None))"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return false; break; } case 2: { return true; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return num_global_entities[0] + num_global_entities[2]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 4; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 2; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 1; break; } case 1: { return 0; break; } case 2: { return 1; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { unsigned int offset = 0; dofs[0] = offset + c.entity_indices[0][0]; dofs[1] = offset + c.entity_indices[0][1]; dofs[2] = offset + c.entity_indices[0][2]; offset += num_global_entities[0]; dofs[3] = offset + c.entity_indices[2][0]; offset += num_global_entities[2]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t 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(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; break; } case 1: { dofs[0] = 1; break; } case 2: { dofs[0] = 2; break; } } break; } case 1: { break; } case 2: { if (i > 0) { throw std::runtime_error("i is larger than number of entities (0)"); } dofs[0] = 3; break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; dof_coordinates[6] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; dof_coordinates[7] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 0; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_4(); } }; /// This class defines the interface for a local-to-global mapping of /// degrees of freedom (dofs). class mth_dofmap_5: public ufc::dofmap { public: /// Constructor mth_dofmap_5() : ufc::dofmap() { // Do nothing } /// Destructor virtual ~mth_dofmap_5() { // Do nothing } /// Return a string identifying the dofmap virtual const char* signature() const { return "FFC dofmap for MixedElement(VectorElement('Lagrange', Domain(Cell('triangle', 2)), 2, 2, None), EnrichedElement(FiniteElement('Lagrange', Domain(Cell('triangle', 2)), 1, None), FiniteElement('Discontinuous Lagrange', Domain(Cell('triangle', 2)), 0, None)), **{'value_shape': (3,) })"; } /// Return true iff mesh entities of topological dimension d are needed virtual bool needs_mesh_entities(std::size_t d) const { switch (d) { case 0: { return true; break; } case 1: { return true; break; } case 2: { return true; break; } } return false; } /// Return the topological dimension of the associated cell shape virtual std::size_t topological_dimension() const { return 2; } /// Return the geometric dimension of the associated cell shape virtual std::size_t geometric_dimension() const { return 2; } /// Return the dimension of the global finite element function space virtual std::size_t global_dimension(const std::vector& num_global_entities) const { return 3*num_global_entities[0] + 2*num_global_entities[1] + num_global_entities[2]; } /// Return the dimension of the local finite element function space for a cell virtual std::size_t local_dimension() const { return 16; } /// Return the number of dofs on each cell facet virtual std::size_t num_facet_dofs() const { return 8; } /// Return the number of dofs associated with each cell entity of dimension d virtual std::size_t num_entity_dofs(std::size_t d) const { switch (d) { case 0: { return 3; break; } case 1: { return 2; break; } case 2: { return 1; break; } } return 0; } /// Tabulate the local-to-global mapping of dofs on a cell virtual void tabulate_dofs(std::size_t* dofs, const std::vector& num_global_entities, const ufc::cell& c) const { unsigned int offset = 0; dofs[0] = offset + c.entity_indices[0][0]; dofs[1] = offset + c.entity_indices[0][1]; dofs[2] = offset + c.entity_indices[0][2]; offset += num_global_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 += num_global_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 += num_global_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]; offset += num_global_entities[1]; dofs[12] = offset + c.entity_indices[0][0]; dofs[13] = offset + c.entity_indices[0][1]; dofs[14] = offset + c.entity_indices[0][2]; offset += num_global_entities[0]; dofs[15] = offset + c.entity_indices[2][0]; offset += num_global_entities[2]; } /// Tabulate the local-to-local mapping from facet dofs to cell dofs virtual void tabulate_facet_dofs(std::size_t* dofs, std::size_t facet) const { switch (facet) { case 0: { dofs[0] = 1; dofs[1] = 2; dofs[2] = 3; dofs[3] = 7; dofs[4] = 8; dofs[5] = 9; dofs[6] = 13; dofs[7] = 14; break; } case 1: { dofs[0] = 0; dofs[1] = 2; dofs[2] = 4; dofs[3] = 6; dofs[4] = 8; dofs[5] = 10; dofs[6] = 12; dofs[7] = 14; break; } case 2: { dofs[0] = 0; dofs[1] = 1; dofs[2] = 5; dofs[3] = 6; dofs[4] = 7; dofs[5] = 11; dofs[6] = 12; dofs[7] = 13; break; } } } /// Tabulate the local-to-local mapping of dofs on entity (d, i) virtual void tabulate_entity_dofs(std::size_t* dofs, std::size_t d, std::size_t i) const { if (d > 2) { throw std::runtime_error("d is larger than dimension (2)"); } switch (d) { case 0: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 0; dofs[1] = 6; dofs[2] = 12; break; } case 1: { dofs[0] = 1; dofs[1] = 7; dofs[2] = 13; break; } case 2: { dofs[0] = 2; dofs[1] = 8; dofs[2] = 14; break; } } break; } case 1: { if (i > 2) { throw std::runtime_error("i is larger than number of entities (2)"); } switch (i) { case 0: { dofs[0] = 3; dofs[1] = 9; break; } case 1: { dofs[0] = 4; dofs[1] = 10; break; } case 2: { dofs[0] = 5; dofs[1] = 11; break; } } break; } case 2: { if (i > 0) { throw std::runtime_error("i is larger than number of entities (0)"); } dofs[0] = 15; break; } } } /// Tabulate the coordinates of all dofs on a cell virtual void tabulate_coordinates(double* dof_coordinates, const double* vertex_coordinates) const { dof_coordinates[0] = vertex_coordinates[0]; dof_coordinates[1] = vertex_coordinates[1]; dof_coordinates[2] = vertex_coordinates[2]; dof_coordinates[3] = vertex_coordinates[3]; dof_coordinates[4] = vertex_coordinates[4]; dof_coordinates[5] = vertex_coordinates[5]; dof_coordinates[6] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; dof_coordinates[7] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; dof_coordinates[8] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; dof_coordinates[9] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; dof_coordinates[10] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; dof_coordinates[11] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; dof_coordinates[12] = vertex_coordinates[0]; dof_coordinates[13] = vertex_coordinates[1]; dof_coordinates[14] = vertex_coordinates[2]; dof_coordinates[15] = vertex_coordinates[3]; dof_coordinates[16] = vertex_coordinates[4]; dof_coordinates[17] = vertex_coordinates[5]; dof_coordinates[18] = 0.5*vertex_coordinates[2] + 0.5*vertex_coordinates[4]; dof_coordinates[19] = 0.5*vertex_coordinates[3] + 0.5*vertex_coordinates[5]; dof_coordinates[20] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[4]; dof_coordinates[21] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[5]; dof_coordinates[22] = 0.5*vertex_coordinates[0] + 0.5*vertex_coordinates[2]; dof_coordinates[23] = 0.5*vertex_coordinates[1] + 0.5*vertex_coordinates[3]; dof_coordinates[24] = vertex_coordinates[0]; dof_coordinates[25] = vertex_coordinates[1]; dof_coordinates[26] = vertex_coordinates[2]; dof_coordinates[27] = vertex_coordinates[3]; dof_coordinates[28] = vertex_coordinates[4]; dof_coordinates[29] = vertex_coordinates[5]; dof_coordinates[30] = 0.333333333333333*vertex_coordinates[0] + 0.333333333333333*vertex_coordinates[2] + 0.333333333333333*vertex_coordinates[4]; dof_coordinates[31] = 0.333333333333333*vertex_coordinates[1] + 0.333333333333333*vertex_coordinates[3] + 0.333333333333333*vertex_coordinates[5]; } /// Return the number of sub dofmaps (for a mixed element) virtual std::size_t num_sub_dofmaps() const { return 2; } /// Create a new dofmap for sub dofmap i (for a mixed element) virtual ufc::dofmap* create_sub_dofmap(std::size_t i) const { switch (i) { case 0: { return new mth_dofmap_3(); break; } case 1: { return new mth_dofmap_4(); break; } } return 0; } /// Create a new class instance virtual ufc::dofmap* create() const { return new mth_dofmap_5(); } }; /// 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 mth_cell_integral_0_otherwise: public ufc::cell_integral { public: /// Constructor mth_cell_integral_0_otherwise() : ufc::cell_integral() { // Do nothing } /// Destructor virtual ~mth_cell_integral_0_otherwise() { // Do nothing } /// Tabulate which form coefficients are used by this integral virtual const std::vector & enabled_coefficients() const { static const std::vector enabled({}); return enabled; } /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates, int cell_orientation) const { // Number of operations (multiply-add pairs) for Jacobian data: 3 // Number of operations (multiply-add pairs) for geometry tensor: 32 // Number of operations (multiply-add pairs) for tensor contraction: 302 // Total number of operations (multiply-add pairs): 337 // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Set scale factor const double det = std::abs(detJ); // Compute geometry tensor const double G0_0_0 = det*K[0]*K[0]*(1.0); const double G0_0_1 = det*K[0]*K[2]*(1.0); const double G0_1_0 = det*K[2]*K[0]*(1.0); const double G0_1_1 = det*K[2]*K[2]*(1.0); const double G1_0_0 = det*K[0]*K[0]*(1.0); const double G1_0_1 = det*K[0]*K[2]*(1.0); const double G1_1_0 = det*K[2]*K[0]*(1.0); const double G1_1_1 = det*K[2]*K[2]*(1.0); const double G2_0_0 = det*K[1]*K[1]*(1.0); const double G2_0_1 = det*K[1]*K[3]*(1.0); const double G2_1_0 = det*K[3]*K[1]*(1.0); const double G2_1_1 = det*K[3]*K[3]*(1.0); const double G3_0_0 = det*K[1]*K[1]*(1.0); const double G3_0_1 = det*K[1]*K[3]*(1.0); const double G3_1_0 = det*K[3]*K[1]*(1.0); const double G3_1_1 = det*K[3]*K[3]*(1.0); const double G4_0 = det*K[0]*(1.0); const double G4_1 = det*K[2]*(1.0); const double G5_0 = det*K[1]*(1.0); const double G5_1 = det*K[3]*(1.0); const double G6_0 = det*K[0]*(1.0); const double G6_1 = det*K[2]*(1.0); const double G7_0 = det*K[1]*(1.0); const double G7_1 = det*K[3]*(1.0); // Compute element tensor A[0] = 0.5*G0_0_0 + 0.5*G0_0_1 + 0.5*G0_1_0 + 0.5*G0_1_1 + 0.5*G2_0_0 + 0.5*G2_0_1 + 0.5*G2_1_0 + 0.5*G2_1_1; A[1] = 0.166666666666668*G0_0_0 + 0.166666666666666*G0_1_0 + 0.166666666666668*G2_0_0 + 0.166666666666666*G2_1_0; A[2] = 0.166666666666666*G0_0_1 + 0.166666666666665*G0_1_1 + 0.166666666666666*G2_0_1 + 0.166666666666665*G2_1_1; A[3] = 0.0; A[4] = -0.666666666666667*G0_0_1 - 0.666666666666667*G0_1_1 - 0.666666666666667*G2_0_1 - 0.666666666666667*G2_1_1; A[5] = -0.666666666666667*G0_0_0 - 0.666666666666667*G0_1_0 - 0.666666666666667*G2_0_0 - 0.666666666666667*G2_1_0; A[6] = 0.0; A[7] = 0.0; A[8] = 0.0; A[9] = 0.0; A[10] = 0.0; A[11] = 0.0; A[12] = 0.166666666666666*G4_0 + 0.166666666666667*G4_1; A[13] = 0.0; A[14] = 0.0; A[15] = 0.166666666666666*G4_0 + 0.166666666666669*G4_1; A[16] = 0.166666666666668*G0_0_0 + 0.166666666666666*G0_0_1 + 0.166666666666668*G2_0_0 + 0.166666666666666*G2_0_1; A[17] = 0.5*G0_0_0 + 0.5*G2_0_0; A[18] = -0.166666666666666*G0_0_1 - 0.166666666666666*G2_0_1; A[19] = 0.666666666666663*G0_0_1 + 0.666666666666663*G2_0_1; A[20] = 0.0; A[21] = -0.666666666666667*G0_0_0 - 0.666666666666666*G0_0_1 - 0.666666666666667*G2_0_0 - 0.666666666666666*G2_0_1; A[22] = 0.0; A[23] = 0.0; A[24] = 0.0; A[25] = 0.0; A[26] = 0.0; A[27] = 0.0; A[28] = 0.0; A[29] = -0.166666666666666*G4_0; A[30] = 0.0; A[31] = -0.166666666666666*G4_0; A[32] = 0.166666666666666*G0_1_0 + 0.166666666666665*G0_1_1 + 0.166666666666666*G2_1_0 + 0.166666666666665*G2_1_1; A[33] = -0.166666666666666*G0_1_0 - 0.166666666666666*G2_1_0; A[34] = 0.5*G0_1_1 + 0.5*G2_1_1; A[35] = 0.666666666666666*G0_1_0 + 0.666666666666666*G2_1_0; A[36] = -0.666666666666666*G0_1_0 - 0.666666666666665*G0_1_1 - 0.666666666666666*G2_1_0 - 0.666666666666665*G2_1_1; A[37] = 0.0; A[38] = 0.0; A[39] = 0.0; A[40] = 0.0; A[41] = 0.0; A[42] = 0.0; A[43] = 0.0; A[44] = 0.0; A[45] = 0.0; A[46] = -0.166666666666667*G4_1; A[47] = -0.166666666666667*G4_1; A[48] = 0.0; A[49] = 0.666666666666663*G0_1_0 + 0.666666666666663*G2_1_0; A[50] = 0.666666666666666*G0_0_1 + 0.666666666666666*G2_0_1; A[51] = 1.33333333333333*G0_0_0 + 0.666666666666656*G0_0_1 + 0.666666666666656*G0_1_0 + 1.33333333333331*G0_1_1 + 1.33333333333333*G2_0_0 + 0.666666666666656*G2_0_1 + 0.666666666666656*G2_1_0 + 1.33333333333331*G2_1_1; A[52] = -1.33333333333333*G0_0_0 - 0.666666666666659*G0_0_1 - 0.666666666666656*G0_1_0 - 1.33333333333333*G2_0_0 - 0.666666666666659*G2_0_1 - 0.666666666666656*G2_1_0; A[53] = -0.666666666666665*G0_0_1 - 0.666666666666665*G0_1_0 - 1.33333333333332*G0_1_1 - 0.666666666666665*G2_0_1 - 0.666666666666665*G2_1_0 - 1.33333333333332*G2_1_1; A[54] = 0.0; A[55] = 0.0; A[56] = 0.0; A[57] = 0.0; A[58] = 0.0; A[59] = 0.0; A[60] = -0.166666666666666*G4_0 - 0.166666666666665*G4_1; A[61] = -0.166666666666666*G4_0 - 0.333333333333331*G4_1; A[62] = -0.333333333333333*G4_0 - 0.166666666666664*G4_1; A[63] = -0.666666666666665*G4_0 - 0.66666666666666*G4_1; A[64] = -0.666666666666667*G0_1_0 - 0.666666666666667*G0_1_1 - 0.666666666666667*G2_1_0 - 0.666666666666667*G2_1_1; A[65] = 0.0; A[66] = -0.666666666666666*G0_0_1 - 0.666666666666665*G0_1_1 - 0.666666666666666*G2_0_1 - 0.666666666666665*G2_1_1; A[67] = -1.33333333333333*G0_0_0 - 0.666666666666656*G0_0_1 - 0.666666666666659*G0_1_0 - 1.33333333333333*G2_0_0 - 0.666666666666656*G2_0_1 - 0.666666666666659*G2_1_0; A[68] = 1.33333333333333*G0_0_0 + 0.666666666666659*G0_0_1 + 0.666666666666659*G0_1_0 + 1.33333333333333*G0_1_1 + 1.33333333333333*G2_0_0 + 0.666666666666659*G2_0_1 + 0.666666666666659*G2_1_0 + 1.33333333333333*G2_1_1; A[69] = 0.666666666666665*G0_0_1 + 0.666666666666665*G0_1_0 + 0.666666666666665*G2_0_1 + 0.666666666666665*G2_1_0; A[70] = 0.0; A[71] = 0.0; A[72] = 0.0; A[73] = 0.0; A[74] = 0.0; A[75] = 0.0; A[76] = 0.166666666666666*G4_0 - 0.166666666666668*G4_1; A[77] = 0.166666666666666*G4_0; A[78] = 0.333333333333333*G4_0 + 0.166666666666665*G4_1; A[79] = 0.666666666666665*G4_0; A[80] = -0.666666666666667*G0_0_0 - 0.666666666666667*G0_0_1 - 0.666666666666667*G2_0_0 - 0.666666666666667*G2_0_1; A[81] = -0.666666666666667*G0_0_0 - 0.666666666666666*G0_1_0 - 0.666666666666667*G2_0_0 - 0.666666666666666*G2_1_0; A[82] = 0.0; A[83] = -0.666666666666665*G0_0_1 - 0.666666666666665*G0_1_0 - 1.33333333333332*G0_1_1 - 0.666666666666665*G2_0_1 - 0.666666666666665*G2_1_0 - 1.33333333333332*G2_1_1; A[84] = 0.666666666666665*G0_0_1 + 0.666666666666665*G0_1_0 + 0.666666666666665*G2_0_1 + 0.666666666666665*G2_1_0; A[85] = 1.33333333333333*G0_0_0 + 0.666666666666667*G0_0_1 + 0.666666666666667*G0_1_0 + 1.33333333333333*G0_1_1 + 1.33333333333333*G2_0_0 + 0.666666666666667*G2_0_1 + 0.666666666666667*G2_1_0 + 1.33333333333333*G2_1_1; A[86] = 0.0; A[87] = 0.0; A[88] = 0.0; A[89] = 0.0; A[90] = 0.0; A[91] = 0.0; A[92] = -0.166666666666667*G4_0 + 0.166666666666667*G4_1; A[93] = 0.166666666666667*G4_0 + 0.333333333333333*G4_1; A[94] = 0.166666666666667*G4_1; A[95] = 0.666666666666667*G4_1; A[96] = 0.0; A[97] = 0.0; A[98] = 0.0; A[99] = 0.0; A[100] = 0.0; A[101] = 0.0; A[102] = 0.5*G1_0_0 + 0.5*G1_0_1 + 0.5*G1_1_0 + 0.5*G1_1_1 + 0.5*G3_0_0 + 0.5*G3_0_1 + 0.5*G3_1_0 + 0.5*G3_1_1; A[103] = 0.166666666666668*G1_0_0 + 0.166666666666666*G1_1_0 + 0.166666666666668*G3_0_0 + 0.166666666666666*G3_1_0; A[104] = 0.166666666666666*G1_0_1 + 0.166666666666665*G1_1_1 + 0.166666666666666*G3_0_1 + 0.166666666666665*G3_1_1; A[105] = 0.0; A[106] = -0.666666666666667*G1_0_1 - 0.666666666666667*G1_1_1 - 0.666666666666667*G3_0_1 - 0.666666666666667*G3_1_1; A[107] = -0.666666666666667*G1_0_0 - 0.666666666666667*G1_1_0 - 0.666666666666667*G3_0_0 - 0.666666666666667*G3_1_0; A[108] = 0.166666666666666*G5_0 + 0.166666666666667*G5_1; A[109] = 0.0; A[110] = 0.0; A[111] = 0.166666666666666*G5_0 + 0.166666666666669*G5_1; A[112] = 0.0; A[113] = 0.0; A[114] = 0.0; A[115] = 0.0; A[116] = 0.0; A[117] = 0.0; A[118] = 0.166666666666668*G1_0_0 + 0.166666666666666*G1_0_1 + 0.166666666666668*G3_0_0 + 0.166666666666666*G3_0_1; A[119] = 0.5*G1_0_0 + 0.5*G3_0_0; A[120] = -0.166666666666666*G1_0_1 - 0.166666666666666*G3_0_1; A[121] = 0.666666666666663*G1_0_1 + 0.666666666666663*G3_0_1; A[122] = 0.0; A[123] = -0.666666666666667*G1_0_0 - 0.666666666666666*G1_0_1 - 0.666666666666667*G3_0_0 - 0.666666666666666*G3_0_1; A[124] = 0.0; A[125] = -0.166666666666666*G5_0; A[126] = 0.0; A[127] = -0.166666666666666*G5_0; A[128] = 0.0; A[129] = 0.0; A[130] = 0.0; A[131] = 0.0; A[132] = 0.0; A[133] = 0.0; A[134] = 0.166666666666666*G1_1_0 + 0.166666666666665*G1_1_1 + 0.166666666666666*G3_1_0 + 0.166666666666665*G3_1_1; A[135] = -0.166666666666666*G1_1_0 - 0.166666666666666*G3_1_0; A[136] = 0.5*G1_1_1 + 0.5*G3_1_1; A[137] = 0.666666666666666*G1_1_0 + 0.666666666666666*G3_1_0; A[138] = -0.666666666666666*G1_1_0 - 0.666666666666665*G1_1_1 - 0.666666666666666*G3_1_0 - 0.666666666666665*G3_1_1; A[139] = 0.0; A[140] = 0.0; A[141] = 0.0; A[142] = -0.166666666666667*G5_1; A[143] = -0.166666666666667*G5_1; A[144] = 0.0; A[145] = 0.0; A[146] = 0.0; A[147] = 0.0; A[148] = 0.0; A[149] = 0.0; A[150] = 0.0; A[151] = 0.666666666666663*G1_1_0 + 0.666666666666663*G3_1_0; A[152] = 0.666666666666666*G1_0_1 + 0.666666666666666*G3_0_1; A[153] = 1.33333333333333*G1_0_0 + 0.666666666666656*G1_0_1 + 0.666666666666656*G1_1_0 + 1.33333333333331*G1_1_1 + 1.33333333333333*G3_0_0 + 0.666666666666656*G3_0_1 + 0.666666666666656*G3_1_0 + 1.33333333333331*G3_1_1; A[154] = -1.33333333333333*G1_0_0 - 0.666666666666659*G1_0_1 - 0.666666666666656*G1_1_0 - 1.33333333333333*G3_0_0 - 0.666666666666659*G3_0_1 - 0.666666666666656*G3_1_0; A[155] = -0.666666666666665*G1_0_1 - 0.666666666666665*G1_1_0 - 1.33333333333332*G1_1_1 - 0.666666666666665*G3_0_1 - 0.666666666666665*G3_1_0 - 1.33333333333332*G3_1_1; A[156] = -0.166666666666666*G5_0 - 0.166666666666665*G5_1; A[157] = -0.166666666666666*G5_0 - 0.333333333333331*G5_1; A[158] = -0.333333333333333*G5_0 - 0.166666666666664*G5_1; A[159] = -0.666666666666665*G5_0 - 0.66666666666666*G5_1; A[160] = 0.0; A[161] = 0.0; A[162] = 0.0; A[163] = 0.0; A[164] = 0.0; A[165] = 0.0; A[166] = -0.666666666666667*G1_1_0 - 0.666666666666667*G1_1_1 - 0.666666666666667*G3_1_0 - 0.666666666666667*G3_1_1; A[167] = 0.0; A[168] = -0.666666666666666*G1_0_1 - 0.666666666666665*G1_1_1 - 0.666666666666666*G3_0_1 - 0.666666666666665*G3_1_1; A[169] = -1.33333333333333*G1_0_0 - 0.666666666666656*G1_0_1 - 0.666666666666659*G1_1_0 - 1.33333333333333*G3_0_0 - 0.666666666666656*G3_0_1 - 0.666666666666659*G3_1_0; A[170] = 1.33333333333333*G1_0_0 + 0.666666666666659*G1_0_1 + 0.666666666666659*G1_1_0 + 1.33333333333333*G1_1_1 + 1.33333333333333*G3_0_0 + 0.666666666666659*G3_0_1 + 0.666666666666659*G3_1_0 + 1.33333333333333*G3_1_1; A[171] = 0.666666666666665*G1_0_1 + 0.666666666666665*G1_1_0 + 0.666666666666665*G3_0_1 + 0.666666666666665*G3_1_0; A[172] = 0.166666666666666*G5_0 - 0.166666666666668*G5_1; A[173] = 0.166666666666666*G5_0; A[174] = 0.333333333333333*G5_0 + 0.166666666666665*G5_1; A[175] = 0.666666666666665*G5_0; A[176] = 0.0; A[177] = 0.0; A[178] = 0.0; A[179] = 0.0; A[180] = 0.0; A[181] = 0.0; A[182] = -0.666666666666667*G1_0_0 - 0.666666666666667*G1_0_1 - 0.666666666666667*G3_0_0 - 0.666666666666667*G3_0_1; A[183] = -0.666666666666667*G1_0_0 - 0.666666666666666*G1_1_0 - 0.666666666666667*G3_0_0 - 0.666666666666666*G3_1_0; A[184] = 0.0; A[185] = -0.666666666666665*G1_0_1 - 0.666666666666665*G1_1_0 - 1.33333333333332*G1_1_1 - 0.666666666666665*G3_0_1 - 0.666666666666665*G3_1_0 - 1.33333333333332*G3_1_1; A[186] = 0.666666666666665*G1_0_1 + 0.666666666666665*G1_1_0 + 0.666666666666665*G3_0_1 + 0.666666666666665*G3_1_0; A[187] = 1.33333333333333*G1_0_0 + 0.666666666666667*G1_0_1 + 0.666666666666667*G1_1_0 + 1.33333333333333*G1_1_1 + 1.33333333333333*G3_0_0 + 0.666666666666667*G3_0_1 + 0.666666666666667*G3_1_0 + 1.33333333333333*G3_1_1; A[188] = -0.166666666666667*G5_0 + 0.166666666666667*G5_1; A[189] = 0.166666666666667*G5_0 + 0.333333333333333*G5_1; A[190] = 0.166666666666667*G5_1; A[191] = 0.666666666666667*G5_1; A[192] = -0.166666666666666*G6_0 - 0.166666666666667*G6_1; A[193] = 0.0; A[194] = 0.0; A[195] = 0.166666666666666*G6_0 + 0.166666666666665*G6_1; A[196] = -0.166666666666666*G6_0 + 0.166666666666668*G6_1; A[197] = 0.166666666666667*G6_0 - 0.166666666666667*G6_1; A[198] = -0.166666666666666*G7_0 - 0.166666666666667*G7_1; A[199] = 0.0; A[200] = 0.0; A[201] = 0.166666666666666*G7_0 + 0.166666666666665*G7_1; A[202] = -0.166666666666666*G7_0 + 0.166666666666668*G7_1; A[203] = 0.166666666666667*G7_0 - 0.166666666666667*G7_1; A[204] = 0.0; A[205] = 0.0; A[206] = 0.0; A[207] = 0.0; A[208] = 0.0; A[209] = 0.166666666666666*G6_0; A[210] = 0.0; A[211] = 0.166666666666666*G6_0 + 0.333333333333331*G6_1; A[212] = -0.166666666666666*G6_0; A[213] = -0.166666666666667*G6_0 - 0.333333333333333*G6_1; A[214] = 0.0; A[215] = 0.166666666666666*G7_0; A[216] = 0.0; A[217] = 0.166666666666666*G7_0 + 0.333333333333331*G7_1; A[218] = -0.166666666666666*G7_0; A[219] = -0.166666666666667*G7_0 - 0.333333333333333*G7_1; A[220] = 0.0; A[221] = 0.0; A[222] = 0.0; A[223] = 0.0; A[224] = 0.0; A[225] = 0.0; A[226] = 0.166666666666667*G6_1; A[227] = 0.333333333333333*G6_0 + 0.166666666666664*G6_1; A[228] = -0.333333333333333*G6_0 - 0.166666666666665*G6_1; A[229] = -0.166666666666667*G6_1; A[230] = 0.0; A[231] = 0.0; A[232] = 0.166666666666667*G7_1; A[233] = 0.333333333333333*G7_0 + 0.166666666666664*G7_1; A[234] = -0.333333333333333*G7_0 - 0.166666666666665*G7_1; A[235] = -0.166666666666667*G7_1; A[236] = 0.0; A[237] = 0.0; A[238] = 0.0; A[239] = 0.0; A[240] = -0.166666666666666*G6_0 - 0.166666666666669*G6_1; A[241] = 0.166666666666666*G6_0; A[242] = 0.166666666666667*G6_1; A[243] = 0.666666666666665*G6_0 + 0.66666666666666*G6_1; A[244] = -0.666666666666665*G6_0; A[245] = -0.666666666666667*G6_1; A[246] = -0.166666666666666*G7_0 - 0.166666666666669*G7_1; A[247] = 0.166666666666666*G7_0; A[248] = 0.166666666666667*G7_1; A[249] = 0.666666666666665*G7_0 + 0.66666666666666*G7_1; A[250] = -0.666666666666665*G7_0; A[251] = -0.666666666666667*G7_1; A[252] = 0.0; A[253] = 0.0; A[254] = 0.0; A[255] = 0.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 mth_cell_integral_1_otherwise: public ufc::cell_integral { public: /// Constructor mth_cell_integral_1_otherwise() : ufc::cell_integral() { // Do nothing } /// Destructor virtual ~mth_cell_integral_1_otherwise() { // Do nothing } /// Tabulate which form coefficients are used by this integral virtual const std::vector & enabled_coefficients() const { static const std::vector enabled({true}); return enabled; } /// Tabulate the tensor for the contribution from a local cell virtual void tabulate_tensor(double* A, const double * const * w, const double* vertex_coordinates, int cell_orientation) const { // Number of operations (multiply-add pairs) for Jacobian data: 3 // Number of operations (multiply-add pairs) for geometry tensor: 6 // Number of operations (multiply-add pairs) for tensor contraction: 30 // Total number of operations (multiply-add pairs): 39 // Compute Jacobian double J[4]; compute_jacobian_triangle_2d(J, vertex_coordinates); // Compute Jacobian inverse and determinant double K[4]; double detJ; compute_jacobian_inverse_triangle_2d(K, detJ, J); // Set scale factor const double det = std::abs(detJ); // Compute geometry tensor const double G0_0 = det*w[0][0]*(1.0); const double G0_1 = det*w[0][1]*(1.0); const double G0_2 = det*w[0][2]*(1.0); const double G1_3 = det*w[0][3]*(1.0); const double G1_4 = det*w[0][4]*(1.0); const double G1_5 = det*w[0][5]*(1.0); // Compute element tensor A[0] = 0.0166666666666666*G0_0 - 0.00833333333333332*G0_1 - 0.00833333333333332*G0_2; A[1] = -0.00833333333333333*G0_0 + 0.0166666666666666*G0_1 - 0.00833333333333333*G0_2; A[2] = -0.00833333333333332*G0_0 - 0.00833333333333332*G0_1 + 0.0166666666666666*G0_2; A[3] = 0.0333333333333333*G0_0 + 0.0666666666666667*G0_1 + 0.0666666666666667*G0_2; A[4] = 0.0666666666666667*G0_0 + 0.0333333333333333*G0_1 + 0.0666666666666667*G0_2; A[5] = 0.0666666666666667*G0_0 + 0.0666666666666667*G0_1 + 0.0333333333333333*G0_2; A[6] = 0.0166666666666666*G1_3 - 0.00833333333333332*G1_4 - 0.00833333333333332*G1_5; A[7] = -0.00833333333333333*G1_3 + 0.0166666666666666*G1_4 - 0.00833333333333333*G1_5; A[8] = -0.00833333333333332*G1_3 - 0.00833333333333332*G1_4 + 0.0166666666666666*G1_5; A[9] = 0.0333333333333333*G1_3 + 0.0666666666666667*G1_4 + 0.0666666666666667*G1_5; A[10] = 0.0666666666666667*G1_3 + 0.0333333333333333*G1_4 + 0.0666666666666667*G1_5; A[11] = 0.0666666666666667*G1_3 + 0.0666666666666667*G1_4 + 0.0333333333333333*G1_5; A[12] = 0.0; A[13] = 0.0; A[14] = 0.0; A[15] = 0.0; } }; /// 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 mth_form_0: public ufc::form { public: /// Constructor mth_form_0() : ufc::form() { // Do nothing } /// Destructor virtual ~mth_form_0() { // Do nothing } /// Return a string identifying the form virtual const char* signature() const { return "9ef2d602761a16cad5e071d632c15ef7219e9536d2f549d9ec63840872bec33efde8c896523f154702b672d943833fd7ead5c9c769b9bf0a601c18d4d879aa7d"; } /// Return original coefficient position for each coefficient (0 <= i < n) virtual std::size_t original_coefficient_position(std::size_t i) const { static const std::vector position({}); return position[i]; } /// Return the rank of the global tensor (r) virtual std::size_t rank() const { return 2; } /// Return the number of coefficients (n) virtual std::size_t num_coefficients() const { return 0; } /// Return the number of cell domains virtual std::size_t num_cell_domains() const { return 0; } /// Return the number of exterior facet domains virtual std::size_t num_exterior_facet_domains() const { return 0; } /// Return the number of interior facet domains virtual std::size_t num_interior_facet_domains() const { return 0; } /// Return the number of point domains virtual std::size_t num_point_domains() const { return 0; } /// Return the number of custom domains virtual std::size_t num_custom_domains() const { return 0; } /// Return whether the form has any cell integrals virtual bool has_cell_integrals() const { return true; } /// Return whether the form has any exterior facet integrals virtual bool has_exterior_facet_integrals() const { return false; } /// Return whether the form has any interior facet integrals virtual bool has_interior_facet_integrals() const { return false; } /// Return whether the form has any point integrals virtual bool has_point_integrals() const { return false; } /// Return whether the form has any custom integrals virtual bool has_custom_integrals() const { return false; } /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(std::size_t i) const { switch (i) { case 0: { return new mth_finite_element_5(); break; } case 1: { return new mth_finite_element_5(); break; } } return 0; } /// Create a new dofmap for argument function i virtual ufc::dofmap* create_dofmap(std::size_t i) const { switch (i) { case 0: { return new mth_dofmap_5(); break; } case 1: { return new mth_dofmap_5(); break; } } return 0; } /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(std::size_t i) const { return 0; } /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(std::size_t i) const { return 0; } /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(std::size_t i) const { return 0; } /// Create a new point integral on sub domain i virtual ufc::point_integral* create_point_integral(std::size_t i) const { return 0; } /// Create a new custom integral on sub domain i virtual ufc::custom_integral* create_custom_integral(std::size_t i) const { return 0; } /// Create a new cell integral on everywhere else virtual ufc::cell_integral* create_default_cell_integral() const { return new mth_cell_integral_0_otherwise(); } /// Create a new exterior facet integral on everywhere else virtual ufc::exterior_facet_integral* create_default_exterior_facet_integral() const { return 0; } /// Create a new interior facet integral on everywhere else virtual ufc::interior_facet_integral* create_default_interior_facet_integral() const { return 0; } /// Create a new point integral on everywhere else virtual ufc::point_integral* create_default_point_integral() const { return 0; } /// Create a new custom integral on everywhere else virtual ufc::custom_integral* create_default_custom_integral() const { return 0; } }; /// 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 mth_form_1: public ufc::form { public: /// Constructor mth_form_1() : ufc::form() { // Do nothing } /// Destructor virtual ~mth_form_1() { // Do nothing } /// Return a string identifying the form virtual const char* signature() const { return "dbd3357db3ff3365672af45a8254cb3daebd1d24a08f708892968b3cbb1389fa0514011ac84961c93723986c3e70d5c6fa56c66a9cbd245c6081820a6e63842f"; } /// Return original coefficient position for each coefficient (0 <= i < n) virtual std::size_t original_coefficient_position(std::size_t i) const { static const std::vector position({0}); return position[i]; } /// Return the rank of the global tensor (r) virtual std::size_t rank() const { return 1; } /// Return the number of coefficients (n) virtual std::size_t num_coefficients() const { return 1; } /// Return the number of cell domains virtual std::size_t num_cell_domains() const { return 0; } /// Return the number of exterior facet domains virtual std::size_t num_exterior_facet_domains() const { return 0; } /// Return the number of interior facet domains virtual std::size_t num_interior_facet_domains() const { return 0; } /// Return the number of point domains virtual std::size_t num_point_domains() const { return 0; } /// Return the number of custom domains virtual std::size_t num_custom_domains() const { return 0; } /// Return whether the form has any cell integrals virtual bool has_cell_integrals() const { return true; } /// Return whether the form has any exterior facet integrals virtual bool has_exterior_facet_integrals() const { return false; } /// Return whether the form has any interior facet integrals virtual bool has_interior_facet_integrals() const { return false; } /// Return whether the form has any point integrals virtual bool has_point_integrals() const { return false; } /// Return whether the form has any custom integrals virtual bool has_custom_integrals() const { return false; } /// Create a new finite element for argument function i virtual ufc::finite_element* create_finite_element(std::size_t i) const { switch (i) { case 0: { return new mth_finite_element_5(); break; } case 1: { return new mth_finite_element_1(); break; } } return 0; } /// Create a new dofmap for argument function i virtual ufc::dofmap* create_dofmap(std::size_t i) const { switch (i) { case 0: { return new mth_dofmap_5(); break; } case 1: { return new mth_dofmap_1(); break; } } return 0; } /// Create a new cell integral on sub domain i virtual ufc::cell_integral* create_cell_integral(std::size_t i) const { return 0; } /// Create a new exterior facet integral on sub domain i virtual ufc::exterior_facet_integral* create_exterior_facet_integral(std::size_t i) const { return 0; } /// Create a new interior facet integral on sub domain i virtual ufc::interior_facet_integral* create_interior_facet_integral(std::size_t i) const { return 0; } /// Create a new point integral on sub domain i virtual ufc::point_integral* create_point_integral(std::size_t i) const { return 0; } /// Create a new custom integral on sub domain i virtual ufc::custom_integral* create_custom_integral(std::size_t i) const { return 0; } /// Create a new cell integral on everywhere else virtual ufc::cell_integral* create_default_cell_integral() const { return new mth_cell_integral_1_otherwise(); } /// Create a new exterior facet integral on everywhere else virtual ufc::exterior_facet_integral* create_default_exterior_facet_integral() const { return 0; } /// Create a new interior facet integral on everywhere else virtual ufc::interior_facet_integral* create_default_interior_facet_integral() const { return 0; } /// Create a new point integral on everywhere else virtual ufc::point_integral* create_default_point_integral() const { return 0; } /// Create a new custom integral on everywhere else virtual ufc::custom_integral* create_default_custom_integral() const { return 0; } }; // DOLFIN wrappers // Standard library includes #include // DOLFIN includes #include #include #include #include #include #include #include #include #include namespace MTH { class CoefficientSpace_f: public dolfin::FunctionSpace { public: //--- Constructors for standard function space, 2 different versions --- // Create standard function space (reference version) CoefficientSpace_f(const dolfin::Mesh& mesh): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_1()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_1()), mesh))) { // Do nothing } // Create standard function space (shared pointer version) CoefficientSpace_f(std::shared_ptr mesh): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_1()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_1()), *mesh))) { // Do nothing } //--- Constructors for constrained function space, 2 different versions --- // Create standard function space (reference version) CoefficientSpace_f(const dolfin::Mesh& mesh, const dolfin::SubDomain& constrained_domain): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_1()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_1()), mesh, dolfin::reference_to_no_delete_pointer(constrained_domain)))) { // Do nothing } // Create standard function space (shared pointer version) CoefficientSpace_f(std::shared_ptr mesh, std::shared_ptr constrained_domain): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_1()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_1()), *mesh, constrained_domain))) { // Do nothing } }; class Form_a_FunctionSpace_0: public dolfin::FunctionSpace { public: //--- Constructors for standard function space, 2 different versions --- // Create standard function space (reference version) Form_a_FunctionSpace_0(const dolfin::Mesh& mesh): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh))) { // Do nothing } // Create standard function space (shared pointer version) Form_a_FunctionSpace_0(std::shared_ptr mesh): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh))) { // Do nothing } //--- Constructors for constrained function space, 2 different versions --- // Create standard function space (reference version) Form_a_FunctionSpace_0(const dolfin::Mesh& mesh, const dolfin::SubDomain& constrained_domain): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh, dolfin::reference_to_no_delete_pointer(constrained_domain)))) { // Do nothing } // Create standard function space (shared pointer version) Form_a_FunctionSpace_0(std::shared_ptr mesh, std::shared_ptr constrained_domain): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh, constrained_domain))) { // Do nothing } }; class Form_a_FunctionSpace_1: public dolfin::FunctionSpace { public: //--- Constructors for standard function space, 2 different versions --- // Create standard function space (reference version) Form_a_FunctionSpace_1(const dolfin::Mesh& mesh): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh))) { // Do nothing } // Create standard function space (shared pointer version) Form_a_FunctionSpace_1(std::shared_ptr mesh): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh))) { // Do nothing } //--- Constructors for constrained function space, 2 different versions --- // Create standard function space (reference version) Form_a_FunctionSpace_1(const dolfin::Mesh& mesh, const dolfin::SubDomain& constrained_domain): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh, dolfin::reference_to_no_delete_pointer(constrained_domain)))) { // Do nothing } // Create standard function space (shared pointer version) Form_a_FunctionSpace_1(std::shared_ptr mesh, std::shared_ptr constrained_domain): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh, constrained_domain))) { // Do nothing } }; class Form_a: public dolfin::Form { public: // Constructor Form_a(const dolfin::FunctionSpace& V1, const dolfin::FunctionSpace& V0): dolfin::Form(2, 0) { _function_spaces[0] = reference_to_no_delete_pointer(V0); _function_spaces[1] = reference_to_no_delete_pointer(V1); _ufc_form = std::shared_ptr(new mth_form_0()); } // Constructor Form_a(std::shared_ptr V1, std::shared_ptr V0): dolfin::Form(2, 0) { _function_spaces[0] = V0; _function_spaces[1] = V1; _ufc_form = std::shared_ptr(new mth_form_0()); } // Destructor ~Form_a() {} /// Return the number of the coefficient with this name virtual std::size_t coefficient_number(const std::string& name) const { dolfin::dolfin_error("generated code for class Form", "access coefficient data", "There are no coefficients"); return 0; } /// Return the name of the coefficient with this number virtual std::string coefficient_name(std::size_t i) const { dolfin::dolfin_error("generated code for class Form", "access coefficient data", "There are no coefficients"); return "unnamed"; } // Typedefs typedef Form_a_FunctionSpace_0 TestSpace; typedef Form_a_FunctionSpace_1 TrialSpace; // Coefficients }; class Form_L_FunctionSpace_0: public dolfin::FunctionSpace { public: //--- Constructors for standard function space, 2 different versions --- // Create standard function space (reference version) Form_L_FunctionSpace_0(const dolfin::Mesh& mesh): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh))) { // Do nothing } // Create standard function space (shared pointer version) Form_L_FunctionSpace_0(std::shared_ptr mesh): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh))) { // Do nothing } //--- Constructors for constrained function space, 2 different versions --- // Create standard function space (reference version) Form_L_FunctionSpace_0(const dolfin::Mesh& mesh, const dolfin::SubDomain& constrained_domain): dolfin::FunctionSpace(dolfin::reference_to_no_delete_pointer(mesh), std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), mesh, dolfin::reference_to_no_delete_pointer(constrained_domain)))) { // Do nothing } // Create standard function space (shared pointer version) Form_L_FunctionSpace_0(std::shared_ptr mesh, std::shared_ptr constrained_domain): dolfin::FunctionSpace(mesh, std::shared_ptr(new dolfin::FiniteElement(std::shared_ptr(new mth_finite_element_5()))), std::shared_ptr(new dolfin::DofMap(std::shared_ptr(new mth_dofmap_5()), *mesh, constrained_domain))) { // Do nothing } }; typedef CoefficientSpace_f Form_L_FunctionSpace_1; class Form_L: public dolfin::Form { public: // Constructor Form_L(const dolfin::FunctionSpace& V0): dolfin::Form(1, 1), f(*this, 0) { _function_spaces[0] = reference_to_no_delete_pointer(V0); _ufc_form = std::shared_ptr(new mth_form_1()); } // Constructor Form_L(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 = std::shared_ptr(new mth_form_1()); } // Constructor Form_L(const dolfin::FunctionSpace& V0, std::shared_ptr f): dolfin::Form(1, 1), f(*this, 0) { _function_spaces[0] = reference_to_no_delete_pointer(V0); this->f = *f; _ufc_form = std::shared_ptr(new mth_form_1()); } // Constructor Form_L(std::shared_ptr V0): dolfin::Form(1, 1), f(*this, 0) { _function_spaces[0] = V0; _ufc_form = std::shared_ptr(new mth_form_1()); } // Constructor Form_L(std::shared_ptr V0, const dolfin::GenericFunction& f): dolfin::Form(1, 1), f(*this, 0) { _function_spaces[0] = V0; this->f = f; _ufc_form = std::shared_ptr(new mth_form_1()); } // Constructor Form_L(std::shared_ptr V0, std::shared_ptr f): dolfin::Form(1, 1), f(*this, 0) { _function_spaces[0] = V0; this->f = *f; _ufc_form = std::shared_ptr(new mth_form_1()); } // Destructor ~Form_L() {} /// Return the number of the coefficient with this name virtual std::size_t coefficient_number(const std::string& name) const { if (name == "f") return 0; dolfin::dolfin_error("generated code for class Form", "access coefficient data", "Invalid coefficient"); return 0; } /// Return the name of the coefficient with this number virtual std::string coefficient_name(std::size_t i) const { switch (i) { case 0: return "f"; } dolfin::dolfin_error("generated code for class Form", "access coefficient data", "Invalid coefficient"); return "unnamed"; } // Typedefs typedef Form_L_FunctionSpace_0 TestSpace; typedef Form_L_FunctionSpace_1 CoefficientSpace_f; // Coefficients dolfin::CoefficientAssigner f; }; // Class typedefs typedef Form_a BilinearForm; typedef Form_a JacobianForm; typedef Form_L LinearForm; typedef Form_L ResidualForm; typedef Form_a::TestSpace FunctionSpace; } #endif